fleas
tech: fleas - replace spores with little hoppers frame-dragging - time dilation field stops time when you aren't moving or firing, +33% defense the odds of finding this tech is low because I find it kinda annoying, but maybe you will like it molecular assembler field energy meter is yellow wormhole is lavender perfect diamagnetism is blue time dilation is green blue pilot wave is black new room in labs: hopBossMom harpoon now auto targets by default, but disabled when crouched pulse + neocognitron auto targeting also disabled when crouched bug fixes
This commit is contained in:
200
js/bullet.js
200
js/bullet.js
@@ -583,7 +583,7 @@ const b = {
|
|||||||
v1: null,
|
v1: null,
|
||||||
v2: null
|
v2: null
|
||||||
};
|
};
|
||||||
if (tech.isPulseAim) { //find mobs in line of sight
|
if (tech.isPulseAim && input.down) { //find mobs in line of sight
|
||||||
let dist = 2200
|
let dist = 2200
|
||||||
for (let i = 0, len = mob.length; i < len; i++) {
|
for (let i = 0, len = mob.length; i < len; i++) {
|
||||||
const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position))
|
const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position))
|
||||||
@@ -2386,9 +2386,9 @@ const b = {
|
|||||||
if (best.who.alive) {
|
if (best.who.alive) {
|
||||||
best.who.locatePlayer();
|
best.who.locatePlayer();
|
||||||
if (best.who.damageReduction) {
|
if (best.who.damageReduction) {
|
||||||
if ( //crit
|
if ( //iridescence
|
||||||
tech.laserCrit && !best.who.shield &&
|
tech.laserCrit && !best.who.shield &&
|
||||||
Vector.dot(Vector.normalise(Vector.sub(best.who.position, path[path.length - 1])), Vector.normalise(Vector.sub(path[path.length - 1], path[path.length - 2]))) > 0.99 - 0.6 / best.who.radius
|
Vector.dot(Vector.normalise(Vector.sub(best.who.position, path[path.length - 1])), Vector.normalise(Vector.sub(path[path.length - 1], path[path.length - 2]))) > 0.995 - 0.6 / best.who.radius
|
||||||
) {
|
) {
|
||||||
damage *= 1 + tech.laserCrit
|
damage *= 1 + tech.laserCrit
|
||||||
simulation.drawList.push({ //add dmg to draw queue
|
simulation.drawList.push({ //add dmg to draw queue
|
||||||
@@ -2663,8 +2663,7 @@ const b = {
|
|||||||
!mob[i].isBadTarget &&
|
!mob[i].isBadTarget &&
|
||||||
Vector.magnitude(Vector.sub(this.position, mob[i].position)) < 700 + mob[i].radius + random &&
|
Vector.magnitude(Vector.sub(this.position, mob[i].position)) < 700 + mob[i].radius + random &&
|
||||||
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
|
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
|
||||||
Matter.Query.ray(body, this.position, mob[i].position).length === 0 &&
|
Matter.Query.ray(body, this.position, mob[i].position).length === 0
|
||||||
!mob[i].isInvulnerable
|
|
||||||
) {
|
) {
|
||||||
if (tech.isStun) b.AoEStunEffect(this.position, 700 + mob[i].radius + random); //AoEStunEffect(where, range, cycles = 90 + 60 * Math.random()) {
|
if (tech.isStun) b.AoEStunEffect(this.position, 700 + mob[i].radius + random); //AoEStunEffect(where, range, cycles = 90 + 60 * Math.random()) {
|
||||||
if (tech.isMineSentry) {
|
if (tech.isMineSentry) {
|
||||||
@@ -2961,7 +2960,7 @@ const b = {
|
|||||||
friction: 0,
|
friction: 0,
|
||||||
frictionAir: 0.023,
|
frictionAir: 0.023,
|
||||||
restitution: 0.9,
|
restitution: 0.9,
|
||||||
dmg: 1, //damage done in addition to the damage from momentum
|
dmg: 1.2, //damage done in addition to the damage from momentum
|
||||||
lookFrequency: 14 + Math.floor(8 * Math.random()),
|
lookFrequency: 14 + Math.floor(8 * Math.random()),
|
||||||
endCycle: simulation.cycle + 100 * tech.isBulletsLastLonger + Math.floor(25 * Math.random()),
|
endCycle: simulation.cycle + 100 * tech.isBulletsLastLonger + Math.floor(25 * Math.random()),
|
||||||
classType: "bullet",
|
classType: "bullet",
|
||||||
@@ -3022,6 +3021,128 @@ const b = {
|
|||||||
// y: m.Vy / 2 + speed * Math.sin(dir)
|
// y: m.Vy / 2 + speed * Math.sin(dir)
|
||||||
// });
|
// });
|
||||||
},
|
},
|
||||||
|
flea(where, velocity, radius = 7 + 3 * Math.random()) {
|
||||||
|
const me = bullet.length;
|
||||||
|
bullet[me] = Bodies.polygon(where.x, where.y, 5, radius, {
|
||||||
|
isFlea: true,
|
||||||
|
angle: 0.5 * Math.random(),
|
||||||
|
friction: 1,
|
||||||
|
frictionStatic: 1,
|
||||||
|
frictionAir: 0, //0.01,
|
||||||
|
restitution: 0,
|
||||||
|
density: 0.0005, // 0.001 is normal density
|
||||||
|
dmg: 9 * (tech.isMutualism ? 2.5 : 1), //damage done in addition to the damage from momentum //spores do 7 dmg, worms do 18
|
||||||
|
lookFrequency: 19 + Math.floor(11 * Math.random()),
|
||||||
|
endCycle: simulation.cycle + Math.floor((780 * tech.isBulletsLastLonger + 360 * Math.random()) + Math.max(0, 150 - bullet.length)), // 13 - 19s
|
||||||
|
classType: "bullet",
|
||||||
|
collisionFilter: {
|
||||||
|
category: cat.bullet,
|
||||||
|
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
|
||||||
|
},
|
||||||
|
minDmgSpeed: 0,
|
||||||
|
lockedOn: null,
|
||||||
|
delay: 50,
|
||||||
|
cd: simulation.cycle + 10,
|
||||||
|
beforeDmg(who) {
|
||||||
|
// this.endCycle = 0
|
||||||
|
Matter.Body.setVelocity(this, Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), 10 + 10 * Math.random())); //push away from target
|
||||||
|
|
||||||
|
this.endCycle -= 180
|
||||||
|
this.cd = simulation.cycle + this.delay;
|
||||||
|
// this.collisionFilter.mask = cat.map
|
||||||
|
if (tech.isSporeFreeze) mobs.statusSlow(who, 90)
|
||||||
|
if (tech.isSpawnBulletsOnDeath && who.alive && who.isDropPowerUp) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!who.alive) {
|
||||||
|
for (let i = 0; i < 3; i++) { //spawn 3 more
|
||||||
|
const speed = 10 + 5 * Math.random()
|
||||||
|
const angle = 2 * Math.PI * Math.random()
|
||||||
|
b.flea(this.position, { x: speed * Math.cos(angle), y: speed * Math.sin(angle) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.endCycle = 0;
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onEnd() {},
|
||||||
|
gravity: 0.002 + 0.002 * tech.isSporeFollow,
|
||||||
|
do() {
|
||||||
|
// if (true && this.lockedOn && this.cd < simulation.cycle) { //blink towards mobs
|
||||||
|
// //needs it's own cooldown variables
|
||||||
|
// // this.cd = simulation.cycle + this.delay;
|
||||||
|
|
||||||
|
// const sub = Vector.sub(this.lockedOn.position, this.position);
|
||||||
|
// const distMag = Vector.magnitude(sub);
|
||||||
|
// if (distMag < 500) {
|
||||||
|
// const unit = Vector.normalise(sub)
|
||||||
|
// Matter.Body.setVelocity(this, Vector.mult(unit, Math.max(20, this.speed * 1.5)));
|
||||||
|
// ctx.beginPath();
|
||||||
|
// ctx.moveTo(this.position.x, this.position.y);
|
||||||
|
// Matter.Body.translate(this, Vector.mult(unit, Math.min(350, distMag - this.lockedOn.radius + 10)));
|
||||||
|
// ctx.lineTo(this.position.x, this.position.y);
|
||||||
|
// ctx.lineWidth = radius * 2;
|
||||||
|
// ctx.strokeStyle = "rgba(0,0,0,0.5)";
|
||||||
|
// ctx.stroke();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
this.force.y += this.gravity * this.mass
|
||||||
|
if (this.cd < simulation.cycle && (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length)) { //if on the ground and not on jump cooldown //
|
||||||
|
// this.collisionFilter.mask = cat.map | cat.mob | cat.mobBullet | cat.mobShield
|
||||||
|
|
||||||
|
this.cd = simulation.cycle + this.delay;
|
||||||
|
this.lockedOn = null; //find a target
|
||||||
|
let closeDist = Infinity;
|
||||||
|
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||||
|
if (
|
||||||
|
!mob[i].isBadTarget &&
|
||||||
|
!mob[i].isInvulnerable &&
|
||||||
|
mob[i].alive &&
|
||||||
|
this.position.y - mob[i].position.y < 1500 && //this is about how high fleas can jump with capMaxY = 0.12 + 0.04 * Math.random()
|
||||||
|
this.position.y - mob[i].position.y > -300 && //not too far below the flea (note that fleas should be on the ground most of the time when doing this check)
|
||||||
|
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
|
||||||
|
Matter.Query.ray(body, this.position, mob[i].position).length === 0
|
||||||
|
) {
|
||||||
|
const TARGET_VECTOR = Vector.sub(this.position, mob[i].position)
|
||||||
|
const DIST = Vector.magnitude(TARGET_VECTOR);
|
||||||
|
if (DIST < closeDist) {
|
||||||
|
closeDist = DIST;
|
||||||
|
this.lockedOn = mob[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tech.isSporeFollow && !this.lockedOn && Matter.Query.ray(map, this.position, m.pos).length === 0) {
|
||||||
|
this.lockedOn = { //make target player if there are no mobs to target
|
||||||
|
position: m.pos,
|
||||||
|
velocity: { x: 0, y: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.lockedOn) { //hop towards mob target
|
||||||
|
const where = Vector.add(this.lockedOn.position, Vector.mult(this.lockedOn.velocity, 5)) //estimate where the mob will be in 5 cycles
|
||||||
|
const Dy = Math.max(0, this.position.y - where.y) //can't be negative because you can't hop down
|
||||||
|
const Dx = this.position.x - where.x
|
||||||
|
const Vx = -0.06 * Dx / Math.sqrt(2 * Dy / this.gravity) //calibrated to hit target, don't mess with this
|
||||||
|
const Vy = 0.085 * Math.sqrt(this.gravity * Dy) //calibrated to hit target, don't mess with this
|
||||||
|
const capX = 0.07 + 0.02 * tech.isSporeFollow
|
||||||
|
const capMaxY = 0.12 + 0.04 * Math.random() + 0.05 * tech.isSporeFollow
|
||||||
|
const capMinY = closeDist > 500 ? 0.05 + 0.02 * Math.random() : 0.02 + 0.01 * Math.random() //don't jump super low, unless you are very close to mob target
|
||||||
|
this.force.x = Math.max(-capX, Math.min(capX, Vx)) * this.mass;
|
||||||
|
this.force.y = -Math.max(capMinY, Math.min(capMaxY, Vy)) * this.mass
|
||||||
|
} else { //random hops
|
||||||
|
if (Math.random() < 0.5) { //chance to continue in the same horizontal direction
|
||||||
|
this.force.x = (0.01 + 0.03 * Math.random()) * this.mass * (this.velocity.x > 0 ? 1 : -1); //random move
|
||||||
|
} else {
|
||||||
|
this.force.x = (0.01 + 0.03 * Math.random()) * this.mass * (Math.random() < 0.5 ? 1 : -1); //random move
|
||||||
|
}
|
||||||
|
this.force.y = -(0.03 + 0.08 * Math.random()) * this.mass
|
||||||
|
}
|
||||||
|
Matter.Body.setVelocity(this, { x: 0, y: 0 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Composite.add(engine.world, bullet[me]); //add bullet to world
|
||||||
|
Matter.Body.setVelocity(bullet[me], velocity);
|
||||||
|
},
|
||||||
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 me = bullet.length;
|
||||||
const THRUST = 0.0015
|
const THRUST = 0.0015
|
||||||
@@ -3774,7 +3895,13 @@ const b = {
|
|||||||
this.force.y += this.mass * tech.foamGravity; //gravity
|
this.force.y += this.mass * tech.foamGravity; //gravity
|
||||||
if (tech.isFoamAttract) {
|
if (tech.isFoamAttract) {
|
||||||
for (let i = 0, len = mob.length; i < len; i++) {
|
for (let i = 0, len = mob.length; i < len; i++) {
|
||||||
if (!mob[i].isBadTarget && Vector.magnitude(Vector.sub(mob[i].position, this.position)) < 375 && mob[i].alive && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
|
if (
|
||||||
|
!mob[i].isBadTarget &&
|
||||||
|
Vector.magnitude(Vector.sub(mob[i].position, this.position)) < 375 &&
|
||||||
|
mob[i].alive &&
|
||||||
|
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
|
||||||
|
!mob[i].isInvulnerable
|
||||||
|
) {
|
||||||
this.force = Vector.mult(Vector.normalise(Vector.sub(mob[i].position, this.position)), this.mass * 0.004)
|
this.force = Vector.mult(Vector.normalise(Vector.sub(mob[i].position, this.position)), this.mass * 0.004)
|
||||||
const slow = 0.9
|
const slow = 0.9
|
||||||
Matter.Body.setVelocity(this, {
|
Matter.Body.setVelocity(this, {
|
||||||
@@ -3800,7 +3927,7 @@ const b = {
|
|||||||
targetedBlock(who, speed = 50 - Math.min(20, who.mass * 2), range = 1600) {
|
targetedBlock(who, speed = 50 - Math.min(20, who.mass * 2), range = 1600) {
|
||||||
let closestMob, dist
|
let closestMob, dist
|
||||||
for (let i = 0, len = mob.length; i < len; i++) {
|
for (let i = 0, len = mob.length; i < len; i++) {
|
||||||
if (who !== mob[i] && !mob[i].isBadTarget) {
|
if (who !== mob[i] && !mob[i].isBadTarget && !mob[i].isInvulnerable) {
|
||||||
dist = Vector.magnitude(Vector.sub(who.position, mob[i].position));
|
dist = Vector.magnitude(Vector.sub(who.position, mob[i].position));
|
||||||
if (dist < range && Matter.Query.ray(map, who.position, mob[i].position).length === 0) { //&& Matter.Query.ray(body, position, mob[i].position).length === 0
|
if (dist < range && Matter.Query.ray(map, who.position, mob[i].position).length === 0) { //&& Matter.Query.ray(body, position, mob[i].position).length === 0
|
||||||
closestMob = mob[i]
|
closestMob = mob[i]
|
||||||
@@ -4331,7 +4458,7 @@ const b = {
|
|||||||
minDmgSpeed: 2,
|
minDmgSpeed: 2,
|
||||||
// lookFrequency: 56 + Math.floor(17 * Math.random()) - isUpgraded * 20,
|
// lookFrequency: 56 + Math.floor(17 * Math.random()) - isUpgraded * 20,
|
||||||
lastLookCycle: simulation.cycle + 60 * Math.random(),
|
lastLookCycle: simulation.cycle + 60 * Math.random(),
|
||||||
delay: Math.floor((tech.isNailBotUpgrade ? 21 : 110) * b.fireCDscale),
|
delay: Math.floor((tech.isNailBotUpgrade ? 20 : 105) * b.fireCDscale),
|
||||||
acceleration: 0.005 * (1 + 0.5 * Math.random()),
|
acceleration: 0.005 * (1 + 0.5 * Math.random()),
|
||||||
range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots(),
|
range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots(),
|
||||||
endCycle: Infinity,
|
endCycle: Infinity,
|
||||||
@@ -4492,7 +4619,7 @@ const b = {
|
|||||||
let target
|
let target
|
||||||
for (let i = 0, len = mob.length; i < len; i++) {
|
for (let i = 0, len = mob.length; i < len; i++) {
|
||||||
const dist2 = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
|
const dist2 = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
|
||||||
if (dist2 < 1000000 && !mob[i].isBadTarget && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
|
if (dist2 < 1000000 && !mob[i].isBadTarget && Matter.Query.ray(map, this.position, mob[i].position).length === 0 && !mob[i].isInvulnerable) {
|
||||||
this.cd = simulation.cycle + this.delay;
|
this.cd = simulation.cycle + this.delay;
|
||||||
target = Vector.add(mob[i].position, Vector.mult(mob[i].velocity, Math.sqrt(dist2) / 60))
|
target = Vector.add(mob[i].position, Vector.mult(mob[i].velocity, Math.sqrt(dist2) / 60))
|
||||||
const radius = 6 + 7 * Math.random()
|
const radius = 6 + 7 * Math.random()
|
||||||
@@ -4523,10 +4650,7 @@ const b = {
|
|||||||
restitution: 0.5 * (1 + 0.5 * Math.random()),
|
restitution: 0.5 * (1 + 0.5 * Math.random()),
|
||||||
acceleration: 0.0015 * (1 + 0.3 * Math.random()),
|
acceleration: 0.0015 * (1 + 0.3 * Math.random()),
|
||||||
playerRange: 140 + Math.floor(30 * Math.random()) + 2 * b.totalBots(),
|
playerRange: 140 + Math.floor(30 * Math.random()) + 2 * b.totalBots(),
|
||||||
offPlayer: {
|
offPlayer: { x: 0, y: 0, },
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
},
|
|
||||||
dmg: 0, //damage done in addition to the damage from momentum
|
dmg: 0, //damage done in addition to the damage from momentum
|
||||||
minDmgSpeed: 2,
|
minDmgSpeed: 2,
|
||||||
lookFrequency: 40 + Math.floor(7 * Math.random()) - 10 * tech.isLaserBotUpgrade,
|
lookFrequency: 40 + Math.floor(7 * Math.random()) - 10 * tech.isLaserBotUpgrade,
|
||||||
@@ -4562,11 +4686,14 @@ const b = {
|
|||||||
let closeDist = this.range;
|
let closeDist = this.range;
|
||||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||||
const DIST = Vector.magnitude(Vector.sub(this.vertices[0], mob[i].position));
|
const DIST = Vector.magnitude(Vector.sub(this.vertices[0], mob[i].position));
|
||||||
if (DIST - mob[i].radius < closeDist &&
|
if (
|
||||||
|
DIST - mob[i].radius < closeDist &&
|
||||||
!mob[i].isShielded &&
|
!mob[i].isShielded &&
|
||||||
(!mob[i].isBadTarget || mob[i].isMobBullet) &&
|
(!mob[i].isBadTarget || mob[i].isMobBullet) &&
|
||||||
Matter.Query.ray(map, this.vertices[0], mob[i].position).length === 0 &&
|
Matter.Query.ray(map, this.vertices[0], mob[i].position).length === 0 &&
|
||||||
Matter.Query.ray(body, this.vertices[0], mob[i].position).length === 0) {
|
Matter.Query.ray(body, this.vertices[0], mob[i].position).length === 0 &&
|
||||||
|
!mob[i].isInvulnerable
|
||||||
|
) {
|
||||||
closeDist = DIST;
|
closeDist = DIST;
|
||||||
this.lockedOn = mob[i]
|
this.lockedOn = mob[i]
|
||||||
}
|
}
|
||||||
@@ -4686,10 +4813,13 @@ const b = {
|
|||||||
let closeDist = this.range;
|
let closeDist = this.range;
|
||||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||||
const DIST = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius;
|
const DIST = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius;
|
||||||
if (DIST < closeDist &&
|
if (
|
||||||
|
DIST < closeDist &&
|
||||||
!mob[i].isBadTarget &&
|
!mob[i].isBadTarget &&
|
||||||
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
|
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
|
||||||
Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
|
Matter.Query.ray(body, this.position, mob[i].position).length === 0 &&
|
||||||
|
!mob[i].isInvulnerable
|
||||||
|
) {
|
||||||
closeDist = DIST;
|
closeDist = DIST;
|
||||||
this.lockedOn = mob[i]
|
this.lockedOn = mob[i]
|
||||||
}
|
}
|
||||||
@@ -4842,7 +4972,7 @@ const b = {
|
|||||||
y: best.y
|
y: best.y
|
||||||
};
|
};
|
||||||
if (best.who.alive) {
|
if (best.who.alive) {
|
||||||
const dmg = 0.6 * m.dmgScale; //********** SCALE DAMAGE HERE *********************
|
const dmg = 0.65 * m.dmgScale; //********** SCALE DAMAGE HERE *********************
|
||||||
best.who.damage(dmg);
|
best.who.damage(dmg);
|
||||||
best.who.locatePlayer();
|
best.who.locatePlayer();
|
||||||
//push mobs away
|
//push mobs away
|
||||||
@@ -4948,7 +5078,7 @@ const b = {
|
|||||||
})
|
})
|
||||||
for (let i = 0; i < q.length; i++) {
|
for (let i = 0; i < q.length; i++) {
|
||||||
if (!q[i].isShielded) {
|
if (!q[i].isShielded) {
|
||||||
mobs.statusStun(q[i], 180)
|
mobs.statusStun(q[i], 210)
|
||||||
const dmg = 0.4 * m.dmgScale * (this.isUpgraded ? 4 : 1) * (tech.isCrit ? 4 : 1)
|
const dmg = 0.4 * m.dmgScale * (this.isUpgraded ? 4 : 1) * (tech.isCrit ? 4 : 1)
|
||||||
q[i].damage(dmg);
|
q[i].damage(dmg);
|
||||||
if (q[i].alive) q[i].foundPlayer();
|
if (q[i].alive) q[i].foundPlayer();
|
||||||
@@ -6273,12 +6403,17 @@ const b = {
|
|||||||
this.stuck(); //runs different code based on what the bullet is stuck to
|
this.stuck(); //runs different code based on what the bullet is stuck to
|
||||||
let scale = 1.01
|
let scale = 1.01
|
||||||
if (tech.isSporeGrowth && !(simulation.cycle % 40)) { //release a spore
|
if (tech.isSporeGrowth && !(simulation.cycle % 40)) { //release a spore
|
||||||
if (tech.isSporeWorm) {
|
if (tech.isSporeFlea) {
|
||||||
|
if (!(simulation.cycle % 80)) {
|
||||||
|
const speed = 10 + 5 * Math.random()
|
||||||
|
const angle = 2 * Math.PI * Math.random()
|
||||||
|
b.flea(this.position, { x: speed * Math.cos(angle), y: speed * Math.sin(angle) })
|
||||||
|
}
|
||||||
|
} else if (tech.isSporeWorm) {
|
||||||
if (!(simulation.cycle % 80)) b.worm(this.position)
|
if (!(simulation.cycle % 80)) b.worm(this.position)
|
||||||
} else {
|
} else {
|
||||||
b.spore(this.position)
|
b.spore(this.position)
|
||||||
}
|
}
|
||||||
// this.totalSpores--
|
|
||||||
scale = 0.96
|
scale = 0.96
|
||||||
if (this.stuckTo && this.stuckTo.alive) scale = 0.9
|
if (this.stuckTo && this.stuckTo.alive) scale = 0.9
|
||||||
Matter.Body.scale(this, scale, scale);
|
Matter.Body.scale(this, scale, scale);
|
||||||
@@ -6289,18 +6424,21 @@ const b = {
|
|||||||
this.radius *= scale
|
this.radius *= scale
|
||||||
if (this.radius > this.maxRadius) this.endCycle = 0;
|
if (this.radius > this.maxRadius) this.endCycle = 0;
|
||||||
}
|
}
|
||||||
// this.force.y += this.mass * 0.00045;
|
|
||||||
|
|
||||||
//draw green glow
|
//draw green glow
|
||||||
ctx.fillStyle = "rgba(0,200,125,0.16)";
|
ctx.fillStyle = "rgba(0,200,125,0.16)";
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(this.position.x, this.position.y, this.maxRadius, 0, 2 * Math.PI);
|
ctx.arc(this.position.x, this.position.y, this.maxRadius, 0, 2 * Math.PI);
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
};
|
};
|
||||||
|
|
||||||
//spawn bullets on end
|
//spawn bullets on end
|
||||||
bullet[me].onEnd = function() {
|
bullet[me].onEnd = function() {
|
||||||
if (tech.isSporeWorm) {
|
if (tech.isSporeFlea) {
|
||||||
|
for (let i = 0, len = this.totalSpores * 0.5; i < len; i++) {
|
||||||
|
const speed = 10 + 5 * Math.random()
|
||||||
|
const angle = 2 * Math.PI * Math.random()
|
||||||
|
b.flea(this.position, { x: speed * Math.cos(angle), y: speed * Math.sin(angle) })
|
||||||
|
}
|
||||||
|
} else if (tech.isSporeWorm) {
|
||||||
for (let i = 0, len = this.totalSpores * 0.5; i < len; i++) b.worm(this.position)
|
for (let i = 0, len = this.totalSpores * 0.5; i < len; i++) b.worm(this.position)
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < this.totalSpores; i++) b.spore(this.position)
|
for (let i = 0; i < this.totalSpores; i++) b.spore(this.position)
|
||||||
@@ -6549,7 +6687,7 @@ const b = {
|
|||||||
if (dot > 0.95 - Math.min(dist * 0.00015, 0.3)) { //lower dot product threshold for targeting then if you only have one harpoon //target closest mob that player is looking at and isn't too close to target
|
if (dot > 0.95 - Math.min(dist * 0.00015, 0.3)) { //lower dot product threshold for targeting then if you only have one harpoon //target closest mob that player is looking at and isn't too close to target
|
||||||
// if (this.ammo > -1) {
|
// if (this.ammo > -1) {
|
||||||
// this.ammo--
|
// this.ammo--
|
||||||
b.harpoon(where, input.down ? mob[i] : null, angle, harpoonSize, false) //Vector.angle(Vector.sub(where, mob[i].position), { x: 0, y: 0 })
|
b.harpoon(where, input.down ? null : mob[i], angle, harpoonSize, false) //Vector.angle(Vector.sub(where, mob[i].position), { x: 0, y: 0 })
|
||||||
angle += SPREAD
|
angle += SPREAD
|
||||||
targetCount++
|
targetCount++
|
||||||
if (targetCount > tech.extraHarpoons) break
|
if (targetCount > tech.extraHarpoons) break
|
||||||
@@ -6574,7 +6712,7 @@ const b = {
|
|||||||
//look for closest mob in player's LoS
|
//look for closest mob in player's LoS
|
||||||
const dir = { x: Math.cos(m.angle), y: Math.sin(m.angle) }; //make a vector for the player's direction of length 1; used in dot product
|
const dir = { x: Math.cos(m.angle), y: Math.sin(m.angle) }; //make a vector for the player's direction of length 1; used in dot product
|
||||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||||
if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, m.pos, mob[i].position).length === 0) {
|
if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, m.pos, mob[i].position).length === 0 && !mob[i].isInvulnerable) {
|
||||||
const dot = Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, m.pos))) //the dot product of diff and dir will return how much over lap between the vectors
|
const dot = Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, m.pos))) //the dot product of diff and dir will return how much over lap between the vectors
|
||||||
const dist = Vector.magnitude(Vector.sub(where, mob[i].position))
|
const dist = Vector.magnitude(Vector.sub(where, mob[i].position))
|
||||||
if (dist < closest.distance && dot > 0.98 - Math.min(dist * 0.00014, 0.3)) { //target closest mob that player is looking at and isn't too close to target
|
if (dist < closest.distance && dot > 0.98 - Math.min(dist * 0.00014, 0.3)) { //target closest mob that player is looking at and isn't too close to target
|
||||||
@@ -7066,7 +7204,11 @@ const b = {
|
|||||||
fire() {},
|
fire() {},
|
||||||
chooseFireMethod() {
|
chooseFireMethod() {
|
||||||
this.lensDamage = 1
|
this.lensDamage = 1
|
||||||
if (tech.isLaserLens) this.do = this.lens
|
if (tech.isLaserLens) {
|
||||||
|
this.do = this.lens
|
||||||
|
} else {
|
||||||
|
this.do = this.stuckOn
|
||||||
|
}
|
||||||
if (tech.isPulseLaser) {
|
if (tech.isPulseLaser) {
|
||||||
this.fire = () => {
|
this.fire = () => {
|
||||||
const drain = 0.01 * tech.isLaserDiode * (tech.isCapacitor ? 10 : 1)
|
const drain = 0.01 * tech.isLaserDiode * (tech.isCapacitor ? 10 : 1)
|
||||||
|
|||||||
@@ -263,9 +263,8 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
|
|||||||
text += `<div class="pause-grid-module"><div class="grid-title"><div class="circle-grid gun"></div> ${build.nameLink(b.guns[b.inventory[i]].name)} - <span style="font-size:100%;font-weight: 100;">${b.guns[b.inventory[i]].ammo}</span></div> ${b.guns[b.inventory[i]].description}</div>`
|
text += `<div class="pause-grid-module"><div class="grid-title"><div class="circle-grid gun"></div> ${build.nameLink(b.guns[b.inventory[i]].name)} - <span style="font-size:100%;font-weight: 100;">${b.guns[b.inventory[i]].ammo}</span></div> ${b.guns[b.inventory[i]].description}</div>`
|
||||||
}
|
}
|
||||||
let el = document.getElementById("pause-grid-left")
|
let el = document.getElementById("pause-grid-left")
|
||||||
el.style.display = "grid"
|
el.style.display = tech.isNoDraftPause ? "none" : "grid" //disabled for eternalism because eternalism lets the player play while this menu is up but the menu doesn't update
|
||||||
el.innerHTML = text
|
el.innerHTML = text
|
||||||
|
|
||||||
//right side
|
//right side
|
||||||
text = "";
|
text = "";
|
||||||
if (tech.isPauseSwitchField && !simulation.isChoosing) {
|
if (tech.isPauseSwitchField && !simulation.isChoosing) {
|
||||||
@@ -304,7 +303,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
el = document.getElementById("pause-grid-right")
|
el = document.getElementById("pause-grid-right")
|
||||||
el.style.display = "grid"
|
el.style.display = tech.isNoDraftPause ? "none" : "grid" //disabled for eternalism because eternalism lets the player play while this menu is up but the menu doesn't update
|
||||||
el.innerHTML = text
|
el.innerHTML = text
|
||||||
|
|
||||||
document.getElementById("tech").style.display = "none"
|
document.getElementById("tech").style.display = "none"
|
||||||
@@ -933,7 +932,7 @@ window.addEventListener("keydown", function(event) {
|
|||||||
if (m.alive && localSettings.loreCount > 0) {
|
if (m.alive && localSettings.loreCount > 0) {
|
||||||
if (simulation.difficultyMode > 4) {
|
if (simulation.difficultyMode > 4) {
|
||||||
simulation.makeTextLog("<em>testing mode disabled for this difficulty</em>");
|
simulation.makeTextLog("<em>testing mode disabled for this difficulty</em>");
|
||||||
break
|
// break
|
||||||
}
|
}
|
||||||
if (simulation.testing) {
|
if (simulation.testing) {
|
||||||
simulation.testing = false;
|
simulation.testing = false;
|
||||||
|
|||||||
169
js/level.js
169
js/level.js
@@ -15,40 +15,31 @@ const level = {
|
|||||||
levels: [],
|
levels: [],
|
||||||
start() {
|
start() {
|
||||||
if (level.levelsCleared === 0) { //this code only runs on the first level
|
if (level.levelsCleared === 0) { //this code only runs on the first level
|
||||||
|
// simulation.enableConstructMode() //used to build maps in testing mode
|
||||||
// simulation.isHorizontalFlipped = true
|
// simulation.isHorizontalFlipped = true
|
||||||
// m.addHealth(Infinity)
|
// m.addHealth(Infinity)
|
||||||
// m.setField("time dilation")
|
// m.setField("molecular assembler")
|
||||||
// b.giveGuns("laser")
|
// b.giveGuns("spores")
|
||||||
|
// tech.giveTech("fleas")
|
||||||
|
// tech.giveTech("flagella")
|
||||||
// b.guns[0].ammo = 10000
|
// b.guns[0].ammo = 10000
|
||||||
// // b.giveGuns("mine")
|
// for (let i = 0; i < 1; ++i) tech.giveTech("mycelium manufacturing")
|
||||||
// tech.giveTech("lens")
|
// for (let i = 0; i < 9; ++i) tech.giveTech("WIMPs")
|
||||||
// for (let i = 0; i < 2; ++i) tech.giveTech("diffraction grating")
|
|
||||||
// for (let i = 0; i < 9; ++i) tech.giveTech("propagator")
|
|
||||||
// for (let i = 0; i < 100; ++i) tech.giveTech("nail-bot")
|
// for (let i = 0; i < 100; ++i) tech.giveTech("nail-bot")
|
||||||
// for (let i = 0; i < 9; ++i) tech.giveTech("emergence")
|
// for (let i = 0; i < 1; ++i) tech.giveTech("necrophage")
|
||||||
// tech.giveTech("laser-bot")
|
// for (let i = 0; i < 1; i++) tech.giveTech("cryodesiccation")
|
||||||
// tech.giveTech("slow light")
|
|
||||||
// tech.giveTech("iridescence")
|
|
||||||
// m.maxHealth = 100
|
|
||||||
// m.health = m.maxHealth
|
|
||||||
// for (let i = 0; i < 10; i++) tech.giveTech("tungsten carbide")
|
|
||||||
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech");
|
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech");
|
||||||
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "research");
|
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "research");
|
||||||
// for (let i = 0; i < 15; i++) tech.giveTech()
|
// m.maxHealth = m.health = 100
|
||||||
// for (let i = 10; i < tech.tech.length; i++) { tech.tech[i].isBanished = true }
|
|
||||||
// powerUps.research.changeRerolls(100000)
|
// powerUps.research.changeRerolls(100000)
|
||||||
// tech.tech[297].frequency = 100
|
|
||||||
// m.immuneCycle = Infinity //you can't take damage
|
// m.immuneCycle = Infinity //you can't take damage
|
||||||
// simulation.enableConstructMode() //used to build maps in testing mode
|
|
||||||
// level.temple();
|
|
||||||
// spawn.cellBossCulture(1900, -500)
|
|
||||||
// powerUps.research.changeRerolls(100)
|
// powerUps.research.changeRerolls(100)
|
||||||
// spawn.starter(1900, -500, 40)
|
// tech.tech[297].frequency = 100
|
||||||
// spawn.starter(1900, -500, 20)
|
// spawn.starter(1900, -500, 200)
|
||||||
// spawn.starter(1900, -500, 100)
|
// for (let i = 0; i < 10; ++i) spawn.hopBullet(1900, -500)
|
||||||
// for (let i = 0; i < 20; ++i) spawn.exploder(1900, -500)
|
// spawn.hopMomBoss(1900, -500)
|
||||||
// spawn.timeSkipBoss(1900, -500)
|
// spawn.grenadier(1900, -1450, 10)
|
||||||
// level.difficultyIncrease(50) //30 is near max on hard //60 is near max on why
|
// level.difficultyIncrease(8 * 4) //30 is near max on hard //60 is near max on why
|
||||||
// level.testing(); //not in rotation, used for testing
|
// level.testing(); //not in rotation, used for testing
|
||||||
// for (let i = 0; i < 7; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research");
|
// for (let i = 0; i < 7; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research");
|
||||||
// for (let i = 0; i < 4; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech");
|
// for (let i = 0; i < 4; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech");
|
||||||
@@ -2215,11 +2206,124 @@ const level = {
|
|||||||
// spawn.randomLevelBoss(x + 950, y + -2200);
|
// spawn.randomLevelBoss(x + 950, y + -2200);
|
||||||
|
|
||||||
// },
|
// },
|
||||||
|
// (x = offset.x, y = offset.y) => { //hopBoss1
|
||||||
|
// const button = level.button(x + 935, y + 0)
|
||||||
|
// button.isUp = true
|
||||||
|
// // spawn.mapVertex(x + 5, y + -1318, "0 0 0 -250 125 -250"); //left ledges
|
||||||
|
// // spawn.mapVertex(x + 1995, y + -1318, "0 0 0 -250 -125 -250"); // right ledges
|
||||||
|
// doCustomTopLayer.push(
|
||||||
|
// () => {
|
||||||
|
// button.draw();
|
||||||
|
// if (button.isUp) {
|
||||||
|
// button.query();
|
||||||
|
// if (!button.isUp) {
|
||||||
|
// // doCustomTopLayer.push(() => {
|
||||||
|
// // ctx.fillStyle = "rgba(150,255,220,0.15)"
|
||||||
|
// // ctx.fillRect(x + 250, y + -2725, 625, 725)
|
||||||
|
// // })
|
||||||
|
// const mapStartingLength = map.length //track this so you know how many you added when running addMapToLevelInProgress
|
||||||
|
// addMapToLevelInProgress = (who) => { //adds new map elements to the level while the level is already running //don't forget to run simulation.draw.setPaths() after you all the the elements so they show up visually
|
||||||
|
// who.collisionFilter.category = cat.map;
|
||||||
|
// who.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet;
|
||||||
|
// Matter.Body.setStatic(who, true); //make static
|
||||||
|
// Composite.add(engine.world, who); //add to world
|
||||||
|
// }
|
||||||
|
// //map elements go here
|
||||||
|
// // spawn.mapRect(x + -50, y + -1875, 875, 200);
|
||||||
|
// // spawn.mapRect(x + 650, y + -2700, 125, 625);
|
||||||
|
// // spawn.mapRect(x + 1200, y + -2250, 250, 25);
|
||||||
|
|
||||||
|
// spawn.mapRect(x + -25, y + -1875, 1250, 200);
|
||||||
|
// // spawn.mapRect(x + 1075, y + -2700, 100, 650);
|
||||||
|
// spawn.mapRect(x + 1325, y + -1875, 475, 200);
|
||||||
|
// // spawn.mapRect(x + 1900, y + -1600, 125, 25);
|
||||||
|
// // spawn.mapRect(x + 900, y + -1875, 325, 25);
|
||||||
|
// // spawn.mapRect(x + 1375, y + -1875, 350, 25);
|
||||||
|
|
||||||
|
// // spawn.mapRect(x + 675, y + -2725, 50, 650);
|
||||||
|
// spawn.mapRect(x + 1900, y + -1675, 125, 25);
|
||||||
|
// spawn.mapRect(x + 1700, y + -1400, 325, 25);
|
||||||
|
// spawn.mapRect(x + -50, y + -1400, 325, 25);
|
||||||
|
|
||||||
|
|
||||||
|
// spawn.mapRect(x + -25, y + -700, 500, 25);
|
||||||
|
// spawn.mapRect(x + 675, y + -700, 600, 25);
|
||||||
|
// spawn.mapRect(x + 1475, y + -700, 500, 25);
|
||||||
|
|
||||||
|
// spawn.mapRect(x + 475, y + -1025, 200, 25);
|
||||||
|
// spawn.mapRect(x + 1275, y + -1025, 200, 25);
|
||||||
|
// spawn.mapRect(x + 475, y + -300, 200, 25);
|
||||||
|
// spawn.mapRect(x + 1275, y + -300, 200, 25);
|
||||||
|
|
||||||
|
|
||||||
|
// for (let i = 0, numberOfMapElementsAdded = map.length - mapStartingLength; i < numberOfMapElementsAdded; i++) addMapToLevelInProgress(map[map.length - 1 - i])
|
||||||
|
// simulation.draw.setPaths() //update map graphics
|
||||||
|
// //mobs go here
|
||||||
|
// powerUps.directSpawn(x + 50, y - 1525, "ammo");
|
||||||
|
// powerUps.directSpawn(x + 1950, y - 1525, "ammo");
|
||||||
|
// spawn.hopMomBoss(x + 550, y + -2325)
|
||||||
|
// for (let i = 0; i < 20; ++i) spawn.hopBullet(x + 50 + 1900 * Math.random(), y + -2325)
|
||||||
|
// // spawn.hopper(x + 1500, y + -775);
|
||||||
|
// // spawn.hopper(x + 525, y + -775);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
// },
|
||||||
|
(x = offset.x, y = offset.y) => { //hopBoss2
|
||||||
|
const button = level.button(x + 935, y + 0)
|
||||||
|
button.isUp = true
|
||||||
|
// spawn.mapVertex(x + 5, y + -1318, "0 0 0 -250 125 -250"); //left ledges
|
||||||
|
// spawn.mapVertex(x + 1995, y + -1318, "0 0 0 -250 -125 -250"); // right ledges
|
||||||
|
doCustomTopLayer.push(
|
||||||
|
() => {
|
||||||
|
button.draw();
|
||||||
|
if (button.isUp) {
|
||||||
|
button.query();
|
||||||
|
if (!button.isUp) {
|
||||||
|
const mapStartingLength = map.length //track this so you know how many you added when running addMapToLevelInProgress
|
||||||
|
addMapToLevelInProgress = (who) => { //adds new map elements to the level while the level is already running //don't forget to run simulation.draw.setPaths() after you all the the elements so they show up visually
|
||||||
|
who.collisionFilter.category = cat.map;
|
||||||
|
who.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet;
|
||||||
|
Matter.Body.setStatic(who, true); //make static
|
||||||
|
Composite.add(engine.world, who); //add to world
|
||||||
|
}
|
||||||
|
//map elements go here
|
||||||
|
spawn.mapRect(x + 150, y + -1400, 750, 50);
|
||||||
|
spawn.mapRect(x + 1100, y + -1400, 750, 50);
|
||||||
|
spawn.mapRect(x + 1825, y + -1050, 200, 50);
|
||||||
|
spawn.mapRect(x + -25, y + -1050, 200, 50);
|
||||||
|
spawn.mapRect(x + 1825, y + -325, 200, 50);
|
||||||
|
spawn.mapRect(x + -25, y + -325, 200, 50);
|
||||||
|
spawn.mapRect(x + 275, y + -700, 525, 50);
|
||||||
|
spawn.mapRect(x + 1200, y + -700, 525, 50);
|
||||||
|
spawn.mapRect(x + -25, y + -1400, 125, 1125); //side walls
|
||||||
|
spawn.mapRect(x + 1900, y + -1400, 150, 1125);
|
||||||
|
spawn.mapRect(x + 1900, y + -2700, 125, 1000);
|
||||||
|
spawn.mapRect(x + -50, y + -2725, 150, 1025);
|
||||||
|
spawn.mapRect(x + -25, y + -1750, 450, 50);
|
||||||
|
spawn.mapRect(x + 1575, y + -1750, 450, 50);
|
||||||
|
spawn.mapRect(x + 525, y + -1750, 950, 50);
|
||||||
|
for (let i = 0, numberOfMapElementsAdded = map.length - mapStartingLength; i < numberOfMapElementsAdded; i++) addMapToLevelInProgress(map[map.length - 1 - i])
|
||||||
|
simulation.draw.setPaths() //update map graphics
|
||||||
|
//mobs go here
|
||||||
|
powerUps.directSpawn(x + 50, y - 1525, "ammo");
|
||||||
|
powerUps.directSpawn(x + 1950, y - 1525, "ammo");
|
||||||
|
spawn.hopMomBoss(x + 800, y + -2200)
|
||||||
|
for (let i = 0; i < 10; ++i) spawn.hopBullet(x + 150 + 750 * Math.random(), y + -1600)
|
||||||
|
for (let i = 0; i < 10; ++i) spawn.hopBullet(x + 1100 + 750 * Math.random(), y + -1600)
|
||||||
|
spawn.hopper(x + 1500, y + -775);
|
||||||
|
spawn.hopper(x + 525, y + -775);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
(x = offset.x, y = offset.y) => {
|
(x = offset.x, y = offset.y) => {
|
||||||
// const toggle = level.toggle(x + 950, y + 0, false, true) // toggle(x, y, isOn = false, isLockOn = false) {
|
// const toggle = level.toggle(x + 950, y + 0, false, true) // toggle(x, y, isOn = false, isLockOn = false) {
|
||||||
// toggle.isAddedElements = false
|
// toggle.isAddedElements = false
|
||||||
|
|
||||||
const button = level.button(x + 950, y + 0)
|
const button = level.button(x + 935, y + 0)
|
||||||
button.isUp = true
|
button.isUp = true
|
||||||
|
|
||||||
|
|
||||||
@@ -2310,7 +2414,7 @@ const level = {
|
|||||||
(x = offset.x, y = offset.y) => {
|
(x = offset.x, y = offset.y) => {
|
||||||
// const toggle = level.toggle(x + 950, y + 0, false, true) // toggle(x, y, isOn = false, isLockOn = false) {
|
// const toggle = level.toggle(x + 950, y + 0, false, true) // toggle(x, y, isOn = false, isLockOn = false) {
|
||||||
// toggle.isAddedElements = false
|
// toggle.isAddedElements = false
|
||||||
const button = level.button(x + 950, y + 0)
|
const button = level.button(x + 935, y + 0)
|
||||||
button.isUp = true
|
button.isUp = true
|
||||||
//left ledges
|
//left ledges
|
||||||
spawn.mapVertex(x + 5, y + -1868, "0 0 0 -250 125 -250");
|
spawn.mapVertex(x + 5, y + -1868, "0 0 0 -250 125 -250");
|
||||||
@@ -2412,7 +2516,7 @@ const level = {
|
|||||||
empty = emptyOptions[Math.floor(Math.random() * emptyOptions.length)];
|
empty = emptyOptions[Math.floor(Math.random() * emptyOptions.length)];
|
||||||
loot = lootOptions[Math.floor(Math.random() * lootOptions.length)];
|
loot = lootOptions[Math.floor(Math.random() * lootOptions.length)];
|
||||||
upDown = upDownOptions[Math.floor(Math.random() * upDownOptions.length)];
|
upDown = upDownOptions[Math.floor(Math.random() * upDownOptions.length)];
|
||||||
// upDown = upDownOptions[1] //controls what level spawns for map designing building //********************************* DO !NOT! RUN THIS LINE IN THE FINAL VERSION ***************************************
|
// upDown = upDownOptions[0] //controls what level spawns for map designing building //********************************* DO !NOT! RUN THIS LINE IN THE FINAL VERSION ***************************************
|
||||||
//3x2: 4 short rooms (3000x1500), 1 double tall room (3000x3000)
|
//3x2: 4 short rooms (3000x1500), 1 double tall room (3000x3000)
|
||||||
//rooms
|
//rooms
|
||||||
let rooms = ["exit", "loot", "enter", "empty"]
|
let rooms = ["exit", "loot", "enter", "empty"]
|
||||||
@@ -2661,7 +2765,7 @@ const level = {
|
|||||||
document.body.style.backgroundColor = "#ddd";
|
document.body.style.backgroundColor = "#ddd";
|
||||||
spawn.mapRect(-950, 0, 8200, 800); //ground
|
spawn.mapRect(-950, 0, 8200, 800); //ground
|
||||||
spawn.mapRect(-950, -1200, 800, 1400); //left wall
|
spawn.mapRect(-950, -1200, 800, 1400); //left wall
|
||||||
spawn.mapRect(-950, -1800, 8200, 800); //roof
|
// spawn.mapRect(-950, -1800, 8200, 800); //roof
|
||||||
spawn.mapRect(-250, -400, 1000, 600); // shelf
|
spawn.mapRect(-250, -400, 1000, 600); // shelf
|
||||||
spawn.mapRect(-250, -1200, 1000, 550); // shelf roof
|
spawn.mapRect(-250, -1200, 1000, 550); // shelf roof
|
||||||
// for (let i = 0; i < 10; ++i) powerUps.spawn(550, -800, "ammo", false);
|
// for (let i = 0; i < 10; ++i) powerUps.spawn(550, -800, "ammo", false);
|
||||||
@@ -2968,10 +3072,10 @@ const level = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
level.setPosToSpawn(0, -250); //normal spawn
|
level.setPosToSpawn(0, -250); //normal spawn
|
||||||
spawn.mapRect(5500, -330 + 20, 100, 20); //spawn this because the real exit is in the wrong spot
|
|
||||||
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
|
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
|
||||||
level.exit.x = 550000;
|
spawn.mapRect(5500, -330 + 20, 100, 20); //spawn this because the real exit is in the wrong spot
|
||||||
level.exit.y = -330;
|
level.exit.x = 0;
|
||||||
|
level.exit.y = -8000;
|
||||||
|
|
||||||
level.defaultZoom = 2500
|
level.defaultZoom = 2500
|
||||||
simulation.zoomTransition(level.defaultZoom)
|
simulation.zoomTransition(level.defaultZoom)
|
||||||
@@ -7892,6 +7996,7 @@ const level = {
|
|||||||
|
|
||||||
spawn.bodyRect(-2100, 2050, 290, 30) //Portal platform
|
spawn.bodyRect(-2100, 2050, 290, 30) //Portal platform
|
||||||
let b = body[body.length - 1];
|
let b = body[body.length - 1];
|
||||||
|
b.isNotHoldable = true
|
||||||
cons[cons.length] = Constraint.create({
|
cons[cons.length] = Constraint.create({
|
||||||
pointA: {
|
pointA: {
|
||||||
x: -1820,
|
x: -1820,
|
||||||
|
|||||||
143
js/player.js
143
js/player.js
@@ -1658,6 +1658,9 @@ const m = {
|
|||||||
// description: "<strong>attract</strong> power ups from <strong>far away</strong><br><strong>deflecting</strong> doesn't drain <strong class='color-f'>energy</strong><br>thrown <strong class='color-block'>blocks</strong> have",
|
// description: "<strong>attract</strong> power ups from <strong>far away</strong><br><strong>deflecting</strong> doesn't drain <strong class='color-f'>energy</strong><br>thrown <strong class='color-block'>blocks</strong> have",
|
||||||
// description: "gain <strong class='color-f'>energy</strong> when <strong>blocking</strong><br>no <strong>recoil</strong> when <strong>blocking</strong>",
|
// description: "gain <strong class='color-f'>energy</strong> when <strong>blocking</strong><br>no <strong>recoil</strong> when <strong>blocking</strong>",
|
||||||
effect: () => {
|
effect: () => {
|
||||||
|
m.fieldMeterColor = "#48f" //"#0c5"
|
||||||
|
m.eyeFillColor = m.fieldMeterColor
|
||||||
|
|
||||||
m.fieldShieldingScale = 0;
|
m.fieldShieldingScale = 0;
|
||||||
m.fieldBlockCD = 3;
|
m.fieldBlockCD = 3;
|
||||||
m.grabPowerUpRange2 = 10000000
|
m.grabPowerUpRange2 = 10000000
|
||||||
@@ -1724,9 +1727,8 @@ const m = {
|
|||||||
ctx.strokeStyle = "#f0f";
|
ctx.strokeStyle = "#f0f";
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
} else if (isFree) {
|
} else if (isFree) {
|
||||||
//when blocking draw this graphic
|
ctx.lineWidth = 2; //when blocking draw this graphic
|
||||||
ctx.fillStyle = "rgba(110,170,200," + (0.2 + 0.4 * Math.random()) + ")";
|
ctx.fillStyle = `rgba(110,150,220, ${0.2 + 0.4 * Math.random()})`
|
||||||
ctx.lineWidth = 2;
|
|
||||||
ctx.strokeStyle = "#000";
|
ctx.strokeStyle = "#000";
|
||||||
const len = mob[i].vertices.length - 1;
|
const len = mob[i].vertices.length - 1;
|
||||||
const mag = mob[i].radius
|
const mag = mob[i].radius
|
||||||
@@ -1739,11 +1741,11 @@ const m = {
|
|||||||
ctx.fill();
|
ctx.fill();
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
} else {
|
} else {
|
||||||
//when blocking draw this graphic
|
|
||||||
const eye = 15;
|
const eye = 15; //when blocking draw this graphic
|
||||||
const len = mob[i].vertices.length - 1;
|
const len = mob[i].vertices.length - 1;
|
||||||
ctx.fillStyle = "rgba(110,170,200," + (0.2 + 0.4 * Math.random()) + ")";
|
|
||||||
ctx.lineWidth = 1;
|
ctx.lineWidth = 1;
|
||||||
|
ctx.fillStyle = `rgba(110,150,220, ${0.2 + 0.4 * Math.random()})`
|
||||||
ctx.strokeStyle = "#000";
|
ctx.strokeStyle = "#000";
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.moveTo(m.fieldPosition.x + eye * Math.cos(m.fieldAngle), m.fieldPosition.y + eye * Math.sin(m.fieldAngle));
|
ctx.moveTo(m.fieldPosition.x + eye * Math.cos(m.fieldAngle), m.fieldPosition.y + eye * Math.sin(m.fieldAngle));
|
||||||
@@ -1800,11 +1802,11 @@ const m = {
|
|||||||
m.fieldAngle = m.angle
|
m.fieldAngle = m.angle
|
||||||
//draw field attached to player
|
//draw field attached to player
|
||||||
if (m.holdingTarget) {
|
if (m.holdingTarget) {
|
||||||
ctx.fillStyle = "rgba(110,170,200," + (0.06 + 0.03 * Math.random()) + ")";
|
ctx.fillStyle = `rgba(110,150,220, ${0.06 + 0.03 * Math.random()})`
|
||||||
ctx.strokeStyle = "rgba(110, 200, 235, " + (0.35 + 0.05 * Math.random()) + ")"
|
ctx.strokeStyle = `rgba(110,150,220, ${0.35 + 0.05 * Math.random()})`
|
||||||
} else {
|
} else {
|
||||||
ctx.fillStyle = "rgba(110,170,200," + (0.27 + 0.2 * Math.random() - 0.1 * wave) + ")";
|
ctx.fillStyle = `rgba(110,150,220, ${0.27 + 0.2 * Math.random() - 0.1 * wave})`
|
||||||
ctx.strokeStyle = "rgba(110, 200, 235, " + (0.4 + 0.5 * Math.random()) + ")"
|
ctx.strokeStyle = `rgba(110,150,220, ${0.4 + 0.5 * Math.random()})`
|
||||||
}
|
}
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(m.pos.x, m.pos.y, m.fieldRange, m.angle - Math.PI * m.fieldArc, m.angle + Math.PI * m.fieldArc, false);
|
ctx.arc(m.pos.x, m.pos.y, m.fieldRange, m.angle - Math.PI * m.fieldArc, m.angle + Math.PI * m.fieldArc, false);
|
||||||
@@ -1828,8 +1830,8 @@ const m = {
|
|||||||
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)
|
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 (!input.field) { //&& tech.isFieldFree
|
if (!input.field) { //&& tech.isFieldFree
|
||||||
//draw field free of player
|
//draw field free of player
|
||||||
ctx.fillStyle = "rgba(110,170,200," + (0.27 + 0.2 * Math.random() - 0.1 * wave) + ")";
|
ctx.fillStyle = `rgba(110,150,220, ${0.27 + 0.2 * Math.random() - 0.1 * wave})`
|
||||||
ctx.strokeStyle = "rgba(110, 200, 235, " + (0.4 + 0.5 * Math.random()) + ")"
|
ctx.strokeStyle = `rgba(110,180,255, ${0.4 + 0.5 * Math.random()})`
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(m.fieldPosition.x, m.fieldPosition.y, m.fieldRange, m.fieldAngle - Math.PI * m.fieldArc, m.fieldAngle + Math.PI * m.fieldArc, false);
|
ctx.arc(m.fieldPosition.x, m.fieldPosition.y, m.fieldRange, m.fieldAngle - Math.PI * m.fieldArc, m.fieldAngle + Math.PI * m.fieldArc, false);
|
||||||
ctx.lineWidth = 2.5 - 1.5 * wave;
|
ctx.lineWidth = 2.5 - 1.5 * wave;
|
||||||
@@ -1842,7 +1844,8 @@ const m = {
|
|||||||
m.perfectPush(true);
|
m.perfectPush(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.drawFieldMeter()
|
// m.drawFieldMeter()
|
||||||
|
m.drawFieldMeter("rgba(0,0,0,0.2)")
|
||||||
if (tech.isPerfectBrake) { //cap mob speed around player
|
if (tech.isPerfectBrake) { //cap mob speed around player
|
||||||
const range = 200 + 140 * wave + 150 * m.energy
|
const range = 200 + 140 * wave + 150 * m.energy
|
||||||
for (let i = 0; i < mob.length; i++) {
|
for (let i = 0; i < mob.length; i++) {
|
||||||
@@ -2018,17 +2021,19 @@ const m = {
|
|||||||
description: "excess <strong class='color-f'>energy</strong> used to build <strong>drones</strong><br>use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs<br>generate <strong>12</strong> <strong class='color-f'>energy</strong> per second",
|
description: "excess <strong class='color-f'>energy</strong> used to build <strong>drones</strong><br>use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs<br>generate <strong>12</strong> <strong class='color-f'>energy</strong> per second",
|
||||||
//<strong>double</strong> your default <strong class='color-f'>energy</strong> regeneration
|
//<strong>double</strong> your default <strong class='color-f'>energy</strong> regeneration
|
||||||
effect: () => {
|
effect: () => {
|
||||||
// m.fieldMeterColor = "#0c5"
|
m.fieldMeterColor = "#ff0"
|
||||||
// m.eyeFillColor = m.fieldMeterColor
|
m.eyeFillColor = m.fieldMeterColor
|
||||||
m.hold = function() {
|
m.hold = function() {
|
||||||
if (m.energy > m.maxEnergy - 0.02 && m.fieldCDcycle < m.cycle && !input.field && bullet.length < 300 && (m.cycle % 2)) {
|
if (m.energy > m.maxEnergy - 0.02 && m.fieldCDcycle < m.cycle && !input.field && bullet.length < 300 && (m.cycle % 2)) {
|
||||||
// if (tech.isBotField) {
|
|
||||||
// b.randomBot(this.position, false)
|
|
||||||
// bullet[bullet.length - 1].endCycle = simulation.cycle + 840 //14 seconds
|
|
||||||
// m.energy -= 0.35
|
|
||||||
// } else
|
|
||||||
if (tech.isSporeField) {
|
if (tech.isSporeField) {
|
||||||
if (tech.isSporeWorm) {
|
if (tech.isSporeFlea) {
|
||||||
|
const drain = 0.16 + (Math.max(bullet.length, 130) - 130) * 0.02
|
||||||
|
if (m.energy > drain) {
|
||||||
|
m.energy -= drain
|
||||||
|
const speed = m.crouch ? 20 + 8 * Math.random() : 10 + 3 * Math.random()
|
||||||
|
b.flea({ x: m.pos.x + 35 * Math.cos(m.angle), y: m.pos.y + 35 * Math.sin(m.angle) }, { x: speed * Math.cos(m.angle), y: speed * Math.sin(m.angle) })
|
||||||
|
}
|
||||||
|
} else if (tech.isSporeWorm) {
|
||||||
const drain = 0.16 + (Math.max(bullet.length, 130) - 130) * 0.02
|
const drain = 0.16 + (Math.max(bullet.length, 130) - 130) * 0.02
|
||||||
if (m.energy > drain) {
|
if (m.energy > drain) {
|
||||||
m.energy -= drain
|
m.energy -= drain
|
||||||
@@ -2260,7 +2265,7 @@ const m = {
|
|||||||
const damageRadius = circleRadiusScale * this.circleRadius
|
const damageRadius = circleRadiusScale * this.circleRadius
|
||||||
const dischargeRange = 150 + 1600 * tech.plasmaDischarge + 1.3 * damageRadius
|
const dischargeRange = 150 + 1600 * tech.plasmaDischarge + 1.3 * damageRadius
|
||||||
for (let i = 0, len = mob.length; i < len; i++) {
|
for (let i = 0, len = mob.length; i < len; i++) {
|
||||||
if (mob[i].alive && (!mob[i].isBadTarget || mob[i].isMobBullet)) {
|
if (mob[i].alive && (!mob[i].isBadTarget || mob[i].isMobBullet) && !mob[i].isInvulnerable) {
|
||||||
const sub = Vector.magnitude(Vector.sub(this.position, mob[i].position))
|
const sub = Vector.magnitude(Vector.sub(this.position, mob[i].position))
|
||||||
if (sub < damageRadius + mob[i].radius) {
|
if (sub < damageRadius + mob[i].radius) {
|
||||||
// if (!this.isAttached && !mob[i].isMobBullet) this.isPopping = true
|
// if (!this.isAttached && !mob[i].isMobBullet) this.isPopping = true
|
||||||
@@ -2530,11 +2535,43 @@ const m = {
|
|||||||
// description: "use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 1px;'>stop time</strong><br>while time is stopped you can <strong>move</strong> and <strong>fire</strong><br>and <strong>collisions</strong> do <strong>50%</strong> less <strong class='color-defense'>harm</strong>",
|
// description: "use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 1px;'>stop time</strong><br>while time is stopped you can <strong>move</strong> and <strong>fire</strong><br>and <strong>collisions</strong> do <strong>50%</strong> less <strong class='color-defense'>harm</strong>",
|
||||||
description: "use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 2px;'>stop time</strong><br><strong>+25%</strong> movement, jumping, and <strong><em>fire rate</em></strong><br>generate <strong>18</strong> <strong class='color-f'>energy</strong> per second",
|
description: "use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 2px;'>stop time</strong><br><strong>+25%</strong> movement, jumping, and <strong><em>fire rate</em></strong><br>generate <strong>18</strong> <strong class='color-f'>energy</strong> per second",
|
||||||
set() {
|
set() {
|
||||||
|
// m.fieldMeterColor = "#0fc"
|
||||||
|
// m.fieldMeterColor = "#ff0"
|
||||||
|
m.fieldMeterColor = "#3fe"
|
||||||
|
m.eyeFillColor = m.fieldMeterColor
|
||||||
|
|
||||||
m.fieldFireRate = 0.75
|
m.fieldFireRate = 0.75
|
||||||
b.setFireCD();
|
b.setFireCD();
|
||||||
m.fieldFx = 1.2
|
m.fieldFx = 1.2
|
||||||
m.fieldJump = 1.09
|
m.fieldJump = 1.09
|
||||||
m.setMovement();
|
m.setMovement();
|
||||||
|
|
||||||
|
const timeStop = () => {
|
||||||
|
m.immuneCycle = m.cycle + 10; //immune to harm while time is stopped, this also disables regen
|
||||||
|
//draw field everywhere
|
||||||
|
ctx.globalCompositeOperation = "saturation"
|
||||||
|
ctx.fillStyle = "#ccc";
|
||||||
|
ctx.fillRect(-100000, -100000, 200000, 200000)
|
||||||
|
ctx.globalCompositeOperation = "source-over"
|
||||||
|
//stop time
|
||||||
|
m.isBodiesAsleep = true;
|
||||||
|
|
||||||
|
function sleep(who) {
|
||||||
|
for (let i = 0, len = who.length; i < len; ++i) {
|
||||||
|
if (!who[i].isSleeping) {
|
||||||
|
who[i].storeVelocity = who[i].velocity
|
||||||
|
who[i].storeAngularVelocity = who[i].angularVelocity
|
||||||
|
}
|
||||||
|
Matter.Sleeping.set(who[i], true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sleep(mob);
|
||||||
|
sleep(body);
|
||||||
|
sleep(bullet);
|
||||||
|
|
||||||
|
simulation.cycle--; //pause all functions that depend on game cycle increasing
|
||||||
|
}
|
||||||
|
|
||||||
if (tech.isRewindField) {
|
if (tech.isRewindField) {
|
||||||
this.rewindCount = 0
|
this.rewindCount = 0
|
||||||
m.grabPowerUpRange2 = 300000
|
m.grabPowerUpRange2 = 300000
|
||||||
@@ -2562,6 +2599,7 @@ const m = {
|
|||||||
m.drawHold(m.holdingTarget);
|
m.drawHold(m.holdingTarget);
|
||||||
m.holding();
|
m.holding();
|
||||||
m.throwBlock();
|
m.throwBlock();
|
||||||
|
m.wakeCheck();
|
||||||
} else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
|
} else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
|
||||||
m.grabPowerUp();
|
m.grabPowerUp();
|
||||||
if (this.rewindCount === 0) m.lookForPickUp();
|
if (this.rewindCount === 0) m.lookForPickUp();
|
||||||
@@ -2612,12 +2650,18 @@ const m = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m.wakeCheck();
|
||||||
} else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
|
} else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
|
||||||
m.pickUp();
|
m.pickUp();
|
||||||
this.rewindCount = 0;
|
this.rewindCount = 0;
|
||||||
|
m.wakeCheck();
|
||||||
|
} else if (tech.isTimeStop && player.speed < 1 && m.onGround && !input.fire) {
|
||||||
|
timeStop();
|
||||||
|
this.rewindCount = 0;
|
||||||
} else {
|
} 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)
|
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)
|
||||||
this.rewindCount = 0;
|
this.rewindCount = 0;
|
||||||
|
m.wakeCheck();
|
||||||
}
|
}
|
||||||
if (m.energy < m.maxEnergy) m.regenEnergy(); //extra energy regen
|
if (m.energy < m.maxEnergy) m.regenEnergy(); //extra energy regen
|
||||||
m.drawFieldMeter() // this calls m.regenEnergy(); also
|
m.drawFieldMeter() // this calls m.regenEnergy(); also
|
||||||
@@ -2637,37 +2681,30 @@ const m = {
|
|||||||
m.lookForPickUp();
|
m.lookForPickUp();
|
||||||
if (m.energy > m.drain) {
|
if (m.energy > m.drain) {
|
||||||
m.energy -= m.drain;
|
m.energy -= m.drain;
|
||||||
if (m.energy < m.drain) {
|
if (m.energy < m.drain) { //out of energy
|
||||||
m.fieldCDcycle = m.cycle + 120;
|
m.fieldCDcycle = m.cycle + 120;
|
||||||
m.energy = 0;
|
m.energy = 0;
|
||||||
m.wakeCheck();
|
m.wakeCheck();
|
||||||
}
|
}
|
||||||
m.immuneCycle = m.cycle + 10; //immune to harm while time is stopped, this also disables regen
|
timeStop();
|
||||||
//draw field everywhere
|
|
||||||
ctx.globalCompositeOperation = "saturation"
|
|
||||||
ctx.fillStyle = "#ccc";
|
|
||||||
ctx.fillRect(-100000, -100000, 200000, 200000)
|
|
||||||
ctx.globalCompositeOperation = "source-over"
|
|
||||||
//stop time
|
|
||||||
m.isBodiesAsleep = true;
|
|
||||||
|
|
||||||
function sleep(who) {
|
|
||||||
for (let i = 0, len = who.length; i < len; ++i) {
|
|
||||||
if (!who[i].isSleeping) {
|
|
||||||
who[i].storeVelocity = who[i].velocity
|
|
||||||
who[i].storeAngularVelocity = who[i].angularVelocity
|
|
||||||
}
|
|
||||||
Matter.Sleeping.set(who[i], true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sleep(mob);
|
|
||||||
sleep(body);
|
|
||||||
sleep(bullet);
|
|
||||||
|
|
||||||
simulation.cycle--; //pause all functions that depend on game cycle increasing
|
|
||||||
} else { //holding, but field button is released
|
} else { //holding, but field button is released
|
||||||
m.wakeCheck();
|
m.wakeCheck();
|
||||||
}
|
}
|
||||||
|
} else if (tech.isTimeStop && player.speed < 1 && m.onGround && m.fireCDcycle < m.cycle && !input.fire) {
|
||||||
|
timeStop();
|
||||||
|
//makes things move at 1/5 time rate, but has an annoying flicker for mob graphics, and other minor bugs
|
||||||
|
// if (!(m.cycle % 4)) {
|
||||||
|
// // requestAnimationFrame(() => {
|
||||||
|
// m.wakeCheck();
|
||||||
|
// // simulation.timePlayerSkip(1)
|
||||||
|
// // }); //wrapping in animation frame prevents errors, probably
|
||||||
|
// ctx.globalCompositeOperation = "saturation"
|
||||||
|
// ctx.fillStyle = "#ccc";
|
||||||
|
// ctx.fillRect(-100000, -100000, 200000, 200000)
|
||||||
|
// ctx.globalCompositeOperation = "source-over"
|
||||||
|
// } else {
|
||||||
|
// timeStop();
|
||||||
|
// }
|
||||||
} else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
|
} else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
|
||||||
m.wakeCheck();
|
m.wakeCheck();
|
||||||
m.pickUp();
|
m.pickUp();
|
||||||
@@ -2682,6 +2719,11 @@ const m = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
effect() {
|
effect() {
|
||||||
|
if (tech.isTimeStop) {
|
||||||
|
m.fieldHarmReduction = 0.66; //33% reduction
|
||||||
|
} else {
|
||||||
|
m.fieldHarmReduction = 1;
|
||||||
|
}
|
||||||
this.set();
|
this.set();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2750,7 +2792,6 @@ const m = {
|
|||||||
} else {
|
} 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)
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
//not shooting (or using field) enable cloak
|
//not shooting (or using field) enable cloak
|
||||||
if (m.energy < 0.05 && m.fireCDcycle < m.cycle && !input.fire) m.fireCDcycle = m.cycle
|
if (m.energy < 0.05 && m.fireCDcycle < m.cycle && !input.fire) m.fireCDcycle = m.cycle
|
||||||
if (m.fireCDcycle + 30 < m.cycle && !input.fire) { //automatically cloak if not firing
|
if (m.fireCDcycle + 30 < m.cycle && !input.fire) { //automatically cloak if not firing
|
||||||
@@ -2992,6 +3033,9 @@ const m = {
|
|||||||
//field <strong>radius</strong> decreases out of <strong>line of sight</strong>
|
//field <strong>radius</strong> decreases out of <strong>line of sight</strong>
|
||||||
description: "use <strong class='color-f'>energy</strong> to guide <strong class='color-block'>blocks</strong><br><strong>unlock</strong> <strong class='color-m'>tech</strong> from other <strong class='color-f'>fields</strong><br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second",
|
description: "use <strong class='color-f'>energy</strong> to guide <strong class='color-block'>blocks</strong><br><strong>unlock</strong> <strong class='color-m'>tech</strong> from other <strong class='color-f'>fields</strong><br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second",
|
||||||
effect: () => {
|
effect: () => {
|
||||||
|
m.fieldMeterColor = "#333"
|
||||||
|
m.eyeFillColor = m.fieldMeterColor
|
||||||
|
|
||||||
m.fieldPhase = 0;
|
m.fieldPhase = 0;
|
||||||
m.fieldPosition = {
|
m.fieldPosition = {
|
||||||
x: simulation.mouseInGame.x,
|
x: simulation.mouseInGame.x,
|
||||||
@@ -3179,7 +3223,7 @@ const m = {
|
|||||||
m.fieldOn = false
|
m.fieldOn = false
|
||||||
m.fieldRadius = 0
|
m.fieldRadius = 0
|
||||||
}
|
}
|
||||||
m.drawFieldMeter()
|
m.drawFieldMeter("rgba(0,0,0,0.2)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3189,6 +3233,9 @@ const m = {
|
|||||||
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong>+4%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
|
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong>+4%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
|
||||||
drain: 0,
|
drain: 0,
|
||||||
effect: function() {
|
effect: function() {
|
||||||
|
m.fieldMeterColor = "#bbf" //"#0c5"
|
||||||
|
m.eyeFillColor = m.fieldMeterColor
|
||||||
|
|
||||||
m.duplicateChance = 0.04
|
m.duplicateChance = 0.04
|
||||||
m.fieldRange = 0
|
m.fieldRange = 0
|
||||||
powerUps.setDupChance(); //needed after adjusting duplication chance
|
powerUps.setDupChance(); //needed after adjusting duplication chance
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ const powerUps = {
|
|||||||
},
|
},
|
||||||
endDraft(type, isCanceled = false) { //type should be a gun, tech, or field
|
endDraft(type, isCanceled = false) { //type should be a gun, tech, or field
|
||||||
if (isCanceled) {
|
if (isCanceled) {
|
||||||
if (tech.isCancelTech && Math.random() < 0.96) {
|
if (tech.isCancelTech && Math.random() < 0.94) {
|
||||||
// powerUps.research.use('tech')
|
// powerUps.research.use('tech')
|
||||||
powerUps[type].effect();
|
powerUps[type].effect();
|
||||||
return
|
return
|
||||||
@@ -396,9 +396,6 @@ const powerUps = {
|
|||||||
}
|
}
|
||||||
}, delay);
|
}, delay);
|
||||||
}
|
}
|
||||||
// for (let i = 0, len = tech.tech.length; i < len; i++) {
|
|
||||||
// if (tech.tech[i].name === "bot fabrication") tech.tech[i].description = `if you collect ${powerUps.orb.research(2 + Math.floor(0.2 * b.totalBots()))}use them to build a<br>random <strong class='color-bot'>bot</strong> <em>(+1 cost every 5 bots)</em>`
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
if (tech.isDeathAvoid && document.getElementById("tech-anthropic")) {
|
if (tech.isDeathAvoid && document.getElementById("tech-anthropic")) {
|
||||||
document.getElementById("tech-anthropic").innerHTML = `-${powerUps.research.count}`
|
document.getElementById("tech-anthropic").innerHTML = `-${powerUps.research.count}`
|
||||||
|
|||||||
@@ -120,6 +120,44 @@ const simulation = {
|
|||||||
}
|
}
|
||||||
simulation.isTimeSkipping = false;
|
simulation.isTimeSkipping = false;
|
||||||
},
|
},
|
||||||
|
// timeMobSkip() {
|
||||||
|
// simulation.gravity();
|
||||||
|
// Engine.update(engine, simulation.delta);
|
||||||
|
// simulation.wipe();
|
||||||
|
// simulation.textLog();
|
||||||
|
// if (m.onGround) {
|
||||||
|
// m.groundControl()
|
||||||
|
// } else {
|
||||||
|
// m.airControl()
|
||||||
|
// }
|
||||||
|
// m.move();
|
||||||
|
// m.look();
|
||||||
|
// simulation.camera();
|
||||||
|
// level.custom();
|
||||||
|
// powerUps.do();
|
||||||
|
// mobs.draw();
|
||||||
|
// simulation.draw.cons();
|
||||||
|
// simulation.draw.body();
|
||||||
|
// if (!m.isBodiesAsleep) {
|
||||||
|
// simulation.checks();
|
||||||
|
// // mobs.loop();
|
||||||
|
// }
|
||||||
|
// mobs.healthBar();
|
||||||
|
// m.draw();
|
||||||
|
// m.hold();
|
||||||
|
// // v.draw(); //working on visibility work in progress
|
||||||
|
// level.customTopLayer();
|
||||||
|
// simulation.draw.drawMapPath();
|
||||||
|
// b.fire();
|
||||||
|
// b.bulletRemove();
|
||||||
|
// b.bulletDraw();
|
||||||
|
// if (!m.isBodiesAsleep) b.bulletDo();
|
||||||
|
// simulation.drawCircle();
|
||||||
|
// // simulation.clip();
|
||||||
|
// ctx.restore();
|
||||||
|
// simulation.drawCursor();
|
||||||
|
// // simulation.pixelGraphics();
|
||||||
|
// },
|
||||||
mouse: {
|
mouse: {
|
||||||
x: canvas.width / 2,
|
x: canvas.width / 2,
|
||||||
y: canvas.height / 2
|
y: canvas.height / 2
|
||||||
@@ -857,6 +895,7 @@ const simulation = {
|
|||||||
let droneCount = 0
|
let droneCount = 0
|
||||||
let sporeCount = 0
|
let sporeCount = 0
|
||||||
let wormCount = 0
|
let wormCount = 0
|
||||||
|
let fleaCount = 0
|
||||||
let deliveryCount = 0
|
let deliveryCount = 0
|
||||||
for (let i = 0; i < bullet.length; ++i) {
|
for (let i = 0; i < bullet.length; ++i) {
|
||||||
if (bullet[i].isDrone) {
|
if (bullet[i].isDrone) {
|
||||||
@@ -866,6 +905,8 @@ const simulation = {
|
|||||||
sporeCount++
|
sporeCount++
|
||||||
} else if (bullet[i].wormSize) {
|
} else if (bullet[i].wormSize) {
|
||||||
wormCount++
|
wormCount++
|
||||||
|
} else if (bullet[i].isFlea) {
|
||||||
|
fleaCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -920,6 +961,21 @@ const simulation = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
requestAnimationFrame(respawnWorms);
|
requestAnimationFrame(respawnWorms);
|
||||||
|
|
||||||
|
//respawn fleas in animation frame
|
||||||
|
let respawnFleas = () => {
|
||||||
|
if (fleaCount > 0) {
|
||||||
|
requestAnimationFrame(respawnFleas);
|
||||||
|
if (!simulation.paused && !simulation.isChoosing) {
|
||||||
|
fleaCount--
|
||||||
|
const where = { x: level.enter.x + 50, y: level.enter.y - 60 }
|
||||||
|
const speed = 6 + 3 * Math.random()
|
||||||
|
const angle = 2 * Math.PI * Math.random()
|
||||||
|
b.flea({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 120 * (Math.random() - 0.5) }, { x: speed * Math.cos(angle), y: speed * Math.sin(angle) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
requestAnimationFrame(respawnFleas);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tech.isQuantumEraser) {
|
if (tech.isQuantumEraser) {
|
||||||
|
|||||||
226
js/spawn.js
226
js/spawn.js
@@ -1,7 +1,7 @@
|
|||||||
//main object for spawning things in a level
|
//main object for spawning things in a level
|
||||||
const spawn = {
|
const spawn = {
|
||||||
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "growBossCulture"],
|
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "growBossCulture"],
|
||||||
// other bosses: suckerBoss, laserBoss, tetherBoss, bounceBoss, sprayBoss, mineBoss //these need a particular level to work so they are not included in the random pool
|
// other bosses: suckerBoss, laserBoss, tetherBoss, bounceBoss, sprayBoss, mineBoss, hopMomBoss //these need a particular level to work so they are not included in the random pool
|
||||||
randomBossList: [
|
randomBossList: [
|
||||||
"orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
|
"orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
|
||||||
"powerUpBoss", "powerUpBossBaby", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss",
|
"powerUpBoss", "powerUpBossBaby", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss",
|
||||||
@@ -51,13 +51,13 @@ const spawn = {
|
|||||||
for (let i = 0, len = mob.length; i < len; i++) {
|
for (let i = 0, len = mob.length; i < len; i++) {
|
||||||
if (mob[i].isDropPowerUp && mob[i].alive) { //&& !mob[i].isBoss
|
if (mob[i].isDropPowerUp && mob[i].alive) { //&& !mob[i].isBoss
|
||||||
if (mob[i].isFinalBoss) {
|
if (mob[i].isFinalBoss) {
|
||||||
mob[i].health = 0.66
|
tech.quantumEraserCount = 0;
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
tech.isQuantumEraserDuplication = true
|
tech.isQuantumEraserDuplication = true
|
||||||
mob[i].death()
|
mob[i].death()
|
||||||
tech.isQuantumEraserDuplication = false
|
tech.isQuantumEraserDuplication = false
|
||||||
}
|
}
|
||||||
|
|
||||||
//graphics
|
//graphics
|
||||||
const color = 'rgba(255,255,255, 0.8)'
|
const color = 'rgba(255,255,255, 0.8)'
|
||||||
simulation.drawList.push({
|
simulation.drawList.push({
|
||||||
@@ -81,7 +81,6 @@ const spawn = {
|
|||||||
color: color, //"rgb(0,0,0)",
|
color: color, //"rgb(0,0,0)",
|
||||||
time: 120
|
time: 120
|
||||||
});
|
});
|
||||||
|
|
||||||
tech.quantumEraserCount--
|
tech.quantumEraserCount--
|
||||||
simulation.makeTextLog(`<span class='color-var'>tech</span>.quantumEraserCount <span class='color-symbol'>=</span> ${tech.quantumEraserCount}`)
|
simulation.makeTextLog(`<span class='color-var'>tech</span>.quantumEraserCount <span class='color-symbol'>=</span> ${tech.quantumEraserCount}`)
|
||||||
if (tech.quantumEraserCount < 1) break
|
if (tech.quantumEraserCount < 1) break
|
||||||
@@ -1580,99 +1579,166 @@ const spawn = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
hopBoss(x, y, radius = 90) {
|
hopBullet(x, y, radius = 10 + Math.ceil(Math.random() * 8)) {
|
||||||
mobs.spawn(x, y, 5, radius, "rgb(0,200,180)");
|
mobs.spawn(x, y, 5, radius, "rgb(0,200,180)");
|
||||||
let me = mob[mob.length - 1];
|
let me = mob[mob.length - 1];
|
||||||
me.isBoss = true;
|
me.stroke = "transparent";
|
||||||
|
me.leaveBody = false;
|
||||||
|
me.isDropPowerUp = false;
|
||||||
|
// me.isBadTarget = true;
|
||||||
|
me.isMobBullet = true;
|
||||||
|
me.showHealthBar = false;
|
||||||
|
me.timeLeft = 1500 + Math.floor(600 * Math.random());
|
||||||
|
|
||||||
me.g = 0.005; //required if using this.gravity
|
me.isRandomMove = Math.random() < 0.3 //most chase player, some don't
|
||||||
|
me.accelMag = 0.01; //jump height
|
||||||
|
me.g = 0.0015; //required if using this.gravity
|
||||||
me.frictionAir = 0.01;
|
me.frictionAir = 0.01;
|
||||||
me.friction = 1
|
me.friction = 1
|
||||||
me.frictionStatic = 1
|
me.frictionStatic = 1
|
||||||
me.restitution = 0;
|
me.restitution = 0;
|
||||||
me.accelMag = 0.07;
|
me.delay = 130 + 60 * simulation.CDScale;
|
||||||
me.delay = 120 * simulation.CDScale;
|
// Matter.Body.rotate(me, Math.random() * Math.PI);
|
||||||
me.randomHopFrequency = 200
|
me.collisionFilter.category = cat.mobBullet;
|
||||||
me.randomHopCD = simulation.cycle + me.randomHopFrequency;
|
me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
|
||||||
// me.memory = 420;
|
me.onHit = function() {
|
||||||
me.isInAir = false
|
this.explode(this.mass * 2);
|
||||||
Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger
|
};
|
||||||
|
me.do = function() {
|
||||||
|
this.gravity();
|
||||||
|
this.checkStatus();
|
||||||
|
if (this.cd < simulation.cycle && (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length)) {
|
||||||
|
this.cd = simulation.cycle + this.delay;
|
||||||
|
if (this.isRandomMove || Math.random() < 0.2) {
|
||||||
|
this.force.x += (0.01 + 0.03 * Math.random()) * this.mass * (Math.random() < 0.5 ? 1 : -1); //random move
|
||||||
|
} else {
|
||||||
|
this.force.x += (0.01 + 0.03 * Math.random()) * this.mass * (player.position.x > this.position.x ? 1 : -1); //chase player
|
||||||
|
}
|
||||||
|
this.force.y -= (0.04 + 0.04 * Math.random()) * this.mass
|
||||||
|
}
|
||||||
|
this.timeLimit();
|
||||||
|
};
|
||||||
|
},
|
||||||
|
hopMomBoss(x, y, radius = 120) {
|
||||||
|
mobs.spawn(x, y, 5, radius, "rgb(0,200,180)");
|
||||||
|
let me = mob[mob.length - 1];
|
||||||
|
me.isBoss = true;
|
||||||
|
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||||
|
me.accelMag = 0.05; //jump height
|
||||||
|
me.g = 0.003; //required if using this.gravity
|
||||||
|
me.frictionAir = 0.01;
|
||||||
|
me.friction = 1
|
||||||
|
me.frictionStatic = 1
|
||||||
|
me.restitution = 0;
|
||||||
|
me.delay = 100 + 40 * simulation.CDScale;
|
||||||
|
Matter.Body.rotate(me, Math.random() * Math.PI);
|
||||||
spawn.shield(me, x, y, 1);
|
spawn.shield(me, x, y, 1);
|
||||||
spawn.spawnOrbitals(me, radius + 60, 1)
|
|
||||||
me.onDeath = function() {
|
me.onDeath = function() {
|
||||||
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
||||||
|
// for (let i = 0, len = 3 + 0.1 * simulation.difficulty; i < len; ++i) spawn.hopBullet(this.position.x + 100 * (Math.random() - 0.5), this.position.y + 100 * (Math.random() - 0.5))
|
||||||
};
|
};
|
||||||
me.lastSpeed = me.speed
|
|
||||||
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
|
||||||
me.do = function() {
|
me.do = function() {
|
||||||
// this.armor();
|
|
||||||
this.gravity();
|
this.gravity();
|
||||||
this.seePlayerCheck();
|
this.seePlayerCheck();
|
||||||
this.checkStatus();
|
this.checkStatus();
|
||||||
if (this.seePlayer.recall) {
|
if (this.cd < simulation.cycle && (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length)) {
|
||||||
const deltaSpeed = this.lastSpeed - this.speed
|
this.cd = simulation.cycle + this.delay;
|
||||||
this.lastSpeed = this.speed
|
//spawn hopBullets after each jump
|
||||||
if (deltaSpeed > 13 && this.speed < 5) { //if the player slows down greatly in one cycle
|
for (let i = 0, len = 1 + 0.05 * simulation.difficulty; i < len; ++i) spawn.hopBullet(this.position.x + 100 * (Math.random() - 0.5), this.position.y + 100 * (Math.random() - 0.5))
|
||||||
//damage and push player away, push away blocks
|
|
||||||
const range = 800 //Math.min(800, 50 * deltaSpeed)
|
|
||||||
for (let i = body.length - 1; i > -1; i--) {
|
|
||||||
if (!body[i].isNotHoldable) {
|
|
||||||
sub = Vector.sub(body[i].position, this.position);
|
|
||||||
dist = Vector.magnitude(sub);
|
|
||||||
if (dist < range) {
|
|
||||||
knock = Vector.mult(Vector.normalise(sub), Math.min(20, 50 * body[i].mass / dist));
|
|
||||||
body[i].force.x += knock.x;
|
|
||||||
body[i].force.y += knock.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
simulation.drawList.push({ //draw radius
|
this.force.x += (0.02 + 0.06 * Math.random()) * this.mass * (player.position.x > this.position.x ? 1 : -1);
|
||||||
x: this.position.x,
|
this.force.y -= (0.08 + 0.08 * Math.random()) * this.mass
|
||||||
y: this.position.y,
|
|
||||||
radius: range,
|
|
||||||
color: "rgba(0,200,180,0.6)",
|
|
||||||
time: 4
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isInAir) {
|
|
||||||
if (this.velocity.y > -0.01 && Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length) { //not moving up, and has hit the map or a body
|
|
||||||
this.isInAir = false //landing
|
|
||||||
this.cd = simulation.cycle + this.delay
|
|
||||||
|
|
||||||
}
|
|
||||||
} else { //on ground
|
|
||||||
if (this.cd < simulation.cycle && (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length)) { //jump
|
|
||||||
this.isInAir = true
|
|
||||||
const forceMag = (this.accelMag + this.accelMag * Math.random()) * this.mass;
|
|
||||||
const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
|
|
||||||
this.force.x += forceMag * Math.cos(angle);
|
|
||||||
this.force.y += forceMag * Math.sin(angle) - (Math.random() * 0.05 + 0.04) * this.mass; //antigravity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (this.cd < simulation.cycle && (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length)) {
|
|
||||||
// this.cd = simulation.cycle + this.delay;
|
|
||||||
// const forceMag = (this.accelMag + this.accelMag * Math.random()) * this.mass;
|
|
||||||
// const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
|
|
||||||
// this.force.x += forceMag * Math.cos(angle);
|
|
||||||
// this.force.y += forceMag * Math.sin(angle) - (Math.random() * 0.05 + 0.04) * this.mass; //antigravity
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
//randomly hob if not aware of player
|
|
||||||
if (this.randomHopCD < simulation.cycle && (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length)) {
|
|
||||||
this.randomHopCD = simulation.cycle + this.randomHopFrequency;
|
|
||||||
//slowly change randomHopFrequency after each hop
|
|
||||||
this.randomHopFrequency = Math.max(100, this.randomHopFrequency + 200 * (0.5 - Math.random()));
|
|
||||||
const forceMag = (this.accelMag + this.accelMag * Math.random()) * this.mass * (0.5 + Math.random() * 0.2);
|
|
||||||
const angle = -Math.PI / 2 + (Math.random() - 0.5) * Math.PI;
|
|
||||||
this.force.x += forceMag * Math.cos(angle);
|
|
||||||
this.force.y += forceMag * Math.sin(angle) - (0.1 + 0.08 * Math.random()) * this.mass; //antigravity
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
// hopBoss(x, y, radius = 90) {
|
||||||
|
// mobs.spawn(x, y, 5, radius, "rgb(0,200,180)");
|
||||||
|
// let me = mob[mob.length - 1];
|
||||||
|
// me.isBoss = true;
|
||||||
|
// me.g = 0.005; //required if using this.gravity
|
||||||
|
// me.frictionAir = 0.01;
|
||||||
|
// me.friction = 1
|
||||||
|
// me.frictionStatic = 1
|
||||||
|
// me.restitution = 0;
|
||||||
|
// me.accelMag = 0.07;
|
||||||
|
// me.delay = 120 * simulation.CDScale;
|
||||||
|
// me.randomHopFrequency = 200
|
||||||
|
// me.randomHopCD = simulation.cycle + me.randomHopFrequency;
|
||||||
|
// // me.memory = 420;
|
||||||
|
// me.isInAir = false
|
||||||
|
// Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger
|
||||||
|
// spawn.shield(me, x, y, 1);
|
||||||
|
// spawn.spawnOrbitals(me, radius + 60, 1)
|
||||||
|
// me.onDeath = function() {
|
||||||
|
// powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
||||||
|
// };
|
||||||
|
// me.lastSpeed = me.speed
|
||||||
|
// me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||||
|
// me.do = function() {
|
||||||
|
// // this.armor();
|
||||||
|
// this.gravity();
|
||||||
|
// this.seePlayerCheck();
|
||||||
|
// this.checkStatus();
|
||||||
|
// if (this.seePlayer.recall) {
|
||||||
|
// const deltaSpeed = this.lastSpeed - this.speed
|
||||||
|
// this.lastSpeed = this.speed
|
||||||
|
// if (deltaSpeed > 13 && this.speed < 5) { //if the player slows down greatly in one cycle
|
||||||
|
// //damage and push player away, push away blocks
|
||||||
|
// const range = 800 //Math.min(800, 50 * deltaSpeed)
|
||||||
|
// for (let i = body.length - 1; i > -1; i--) {
|
||||||
|
// if (!body[i].isNotHoldable) {
|
||||||
|
// sub = Vector.sub(body[i].position, this.position);
|
||||||
|
// dist = Vector.magnitude(sub);
|
||||||
|
// if (dist < range) {
|
||||||
|
// knock = Vector.mult(Vector.normalise(sub), Math.min(20, 50 * body[i].mass / dist));
|
||||||
|
// body[i].force.x += knock.x;
|
||||||
|
// body[i].force.y += knock.y;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// simulation.drawList.push({ //draw radius
|
||||||
|
// x: this.position.x,
|
||||||
|
// y: this.position.y,
|
||||||
|
// radius: range,
|
||||||
|
// color: "rgba(0,200,180,0.6)",
|
||||||
|
// time: 4
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// if (this.isInAir) {
|
||||||
|
// if (this.velocity.y > -0.01 && Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length) { //not moving up, and has hit the map or a body
|
||||||
|
// this.isInAir = false //landing
|
||||||
|
// this.cd = simulation.cycle + this.delay
|
||||||
|
// }
|
||||||
|
// } else { //on ground
|
||||||
|
// if (this.cd < simulation.cycle && (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length)) { //jump
|
||||||
|
// this.isInAir = true
|
||||||
|
// const forceMag = (this.accelMag + this.accelMag * Math.random()) * this.mass;
|
||||||
|
// const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
|
||||||
|
// this.force.x += forceMag * Math.cos(angle);
|
||||||
|
// this.force.y += forceMag * Math.sin(angle) - (Math.random() * 0.05 + 0.04) * this.mass; //antigravity
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // if (this.cd < simulation.cycle && (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length)) {
|
||||||
|
// // this.cd = simulation.cycle + this.delay;
|
||||||
|
// // const forceMag = (this.accelMag + this.accelMag * Math.random()) * this.mass;
|
||||||
|
// // const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
|
||||||
|
// // this.force.x += forceMag * Math.cos(angle);
|
||||||
|
// // this.force.y += forceMag * Math.sin(angle) - (Math.random() * 0.05 + 0.04) * this.mass; //antigravity
|
||||||
|
// // }
|
||||||
|
// } else {
|
||||||
|
// //randomly hob if not aware of player
|
||||||
|
// if (this.randomHopCD < simulation.cycle && (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length)) {
|
||||||
|
// this.randomHopCD = simulation.cycle + this.randomHopFrequency;
|
||||||
|
// //slowly change randomHopFrequency after each hop
|
||||||
|
// this.randomHopFrequency = Math.max(100, this.randomHopFrequency + 200 * (0.5 - Math.random()));
|
||||||
|
// const forceMag = (this.accelMag + this.accelMag * Math.random()) * this.mass * (0.5 + Math.random() * 0.2);
|
||||||
|
// const angle = -Math.PI / 2 + (Math.random() - 0.5) * Math.PI;
|
||||||
|
// this.force.x += forceMag * Math.cos(angle);
|
||||||
|
// this.force.y += forceMag * Math.sin(angle) - (0.1 + 0.08 * Math.random()) * this.mass; //antigravity
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// },
|
||||||
spinner(x, y, radius = 30 + Math.ceil(Math.random() * 35)) {
|
spinner(x, y, radius = 30 + Math.ceil(Math.random() * 35)) {
|
||||||
mobs.spawn(x, y, 5, radius, "#000000");
|
mobs.spawn(x, y, 5, radius, "#000000");
|
||||||
let me = mob[mob.length - 1];
|
let me = mob[mob.length - 1];
|
||||||
@@ -5118,7 +5184,7 @@ const spawn = {
|
|||||||
let me = mob[mob.length - 1];
|
let me = mob[mob.length - 1];
|
||||||
me.stroke = "transparent";
|
me.stroke = "transparent";
|
||||||
me.onHit = function() {
|
me.onHit = function() {
|
||||||
this.explode(this.mass * 20);
|
this.explode(this.mass);
|
||||||
};
|
};
|
||||||
Matter.Body.setDensity(me, 0.00004); //normal is 0.001
|
Matter.Body.setDensity(me, 0.00004); //normal is 0.001
|
||||||
|
|
||||||
@@ -5135,7 +5201,7 @@ const spawn = {
|
|||||||
//damage player if in range
|
//damage player if in range
|
||||||
if (Vector.magnitude(Vector.sub(player.position, this.position)) < pulseRadius && m.immuneCycle < m.cycle) {
|
if (Vector.magnitude(Vector.sub(player.position, this.position)) < pulseRadius && m.immuneCycle < m.cycle) {
|
||||||
m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
|
m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
|
||||||
m.damage(0.02 * simulation.dmgScale);
|
m.damage(0.015 * simulation.dmgScale);
|
||||||
}
|
}
|
||||||
simulation.drawList.push({ //add dmg to draw queue
|
simulation.drawList.push({ //add dmg to draw queue
|
||||||
x: this.position.x,
|
x: this.position.x,
|
||||||
|
|||||||
139
js/tech.js
139
js/tech.js
@@ -256,7 +256,7 @@ const tech = {
|
|||||||
return dmg * tech.slowFire * tech.aimDamage
|
return dmg * tech.slowFire * tech.aimDamage
|
||||||
},
|
},
|
||||||
duplicationChance() {
|
duplicationChance() {
|
||||||
return Math.max(0, (tech.isPowerUpsVanish ? 0.12 : 0) + (tech.isStimulatedEmission ? 0.15 : 0) + tech.cancelCount * 0.045 + tech.duplicateChance + 0.05 * tech.isExtraGunField + m.duplicateChance + tech.fieldDuplicate + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0) + tech.isQuantumEraserDuplication * (1 - 0.01 * (simulation.difficultyMode ** 2)))
|
return Math.max(0, (tech.isPowerUpsVanish ? 0.12 : 0) + (tech.isStimulatedEmission ? 0.15 : 0) + tech.cancelCount * 0.045 + tech.duplicateChance + 0.05 * tech.isExtraGunField + m.duplicateChance + tech.fieldDuplicate + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0) + tech.isQuantumEraserDuplication * (1 - 0.016 * (simulation.difficultyMode ** 2)))
|
||||||
},
|
},
|
||||||
isScaleMobsWithDuplication: false,
|
isScaleMobsWithDuplication: false,
|
||||||
maxDuplicationEvent() {
|
maxDuplicationEvent() {
|
||||||
@@ -2977,7 +2977,7 @@ const tech = {
|
|||||||
effect() {
|
effect() {
|
||||||
tech.isBrainstorm = true
|
tech.isBrainstorm = true
|
||||||
tech.isBrainstormActive = false
|
tech.isBrainstormActive = false
|
||||||
tech.brainStormDelay = 145 - simulation.difficultyMode * 10
|
tech.brainStormDelay = 150 - simulation.difficultyMode * 7
|
||||||
},
|
},
|
||||||
remove() {
|
remove() {
|
||||||
tech.isBrainstorm = false
|
tech.isBrainstorm = false
|
||||||
@@ -3319,7 +3319,7 @@ const tech = {
|
|||||||
{
|
{
|
||||||
name: "options exchange",
|
name: "options exchange",
|
||||||
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Option_(finance)' class="link">options exchange</a>`,
|
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Option_(finance)' class="link">options exchange</a>`,
|
||||||
description: `clicking <strong style = 'font-size:150%;'>×</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong> has a <strong>96%</strong><br>chance to randomize <strong>choices</strong> and not <strong>cancel</strong>`,
|
description: `clicking <strong style = 'font-size:150%;'>×</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong> has a <strong>94%</strong><br>chance to randomize <strong>choices</strong> and not <strong>cancel</strong>`,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 1,
|
frequency: 1,
|
||||||
@@ -5205,7 +5205,7 @@ const tech = {
|
|||||||
frequency: 2,
|
frequency: 2,
|
||||||
frequencyDefault: 2,
|
frequencyDefault: 2,
|
||||||
allowed() {
|
allowed() {
|
||||||
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isSporeWorm
|
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isSporeWorm || tech.isSporeFlea
|
||||||
},
|
},
|
||||||
requires: "spores",
|
requires: "spores",
|
||||||
effect() {
|
effect() {
|
||||||
@@ -5225,7 +5225,7 @@ const tech = {
|
|||||||
frequency: 2,
|
frequency: 2,
|
||||||
frequencyDefault: 2,
|
frequencyDefault: 2,
|
||||||
allowed() {
|
allowed() {
|
||||||
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isSporeWorm
|
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isSporeWorm || tech.isSporeFlea
|
||||||
},
|
},
|
||||||
requires: "spores",
|
requires: "spores",
|
||||||
effect() {
|
effect() {
|
||||||
@@ -5263,7 +5263,7 @@ const tech = {
|
|||||||
frequency: 2,
|
frequency: 2,
|
||||||
frequencyDefault: 2,
|
frequencyDefault: 2,
|
||||||
allowed() {
|
allowed() {
|
||||||
return (tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField) && !tech.isEnergyHealth || tech.isSporeWorm
|
return (tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField) && !tech.isEnergyHealth || tech.isSporeWorm || tech.isSporeFlea
|
||||||
},
|
},
|
||||||
requires: "spores, not mass-energy",
|
requires: "spores, not mass-energy",
|
||||||
effect() {
|
effect() {
|
||||||
@@ -5273,26 +5273,55 @@ const tech = {
|
|||||||
tech.isMutualism = false
|
tech.isMutualism = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// name: "worm-shot",
|
name: "fleas",
|
||||||
// link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Worm' class="link">worm-shot</a>`,
|
description: "<strong class='color-p' style='letter-spacing: 2px;'>sporangium</strong> hatch <strong class='color-p' style='letter-spacing: -0.8px;'>fleas</strong><br><strong class='color-p' style='letter-spacing: 2px;'>spore</strong> <strong class='color-m'>tech</strong> applies to <strong class='color-p' style='letter-spacing: -0.8px;'>fleas</strong>",
|
||||||
// description: "<strong>shotgun</strong> hatches <strong>3-4</strong> mob seeking <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong><br><em>worms benefit from spore technology</em>", //<br><strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> seek out nearby mobs
|
isGunTech: true,
|
||||||
// isGunTech: true,
|
maxCount: 1,
|
||||||
// maxCount: 1,
|
count: 0,
|
||||||
// count: 0,
|
frequency: 3,
|
||||||
// frequency: 2,
|
frequencyDefault: 3,
|
||||||
// frequencyDefault: 2,
|
allowed() {
|
||||||
// allowed() {
|
return (tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField) && !tech.isSporeWorm
|
||||||
// return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isRivets && !tech.isIceShot && !tech.isFoamShot && !tech.isNeedles
|
},
|
||||||
// },
|
requires: "spores, not worms",
|
||||||
// requires: "shotgun, not incendiary, nail-shot, rivets, foam-shot, ice-shot, needles",
|
effect() {
|
||||||
// effect() {
|
tech.isSporeFlea = true
|
||||||
// tech.isWormShot = true;
|
},
|
||||||
// },
|
remove() {
|
||||||
// remove() {
|
tech.isSporeFlea = false
|
||||||
// tech.isWormShot = false;
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// ammoBonus: 8,
|
||||||
|
// effect() {
|
||||||
|
// tech.isRailGun = true;
|
||||||
|
// for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||||
|
// if (b.guns[i].name === "harpoon") {
|
||||||
|
// b.guns[i].chooseFireMethod()
|
||||||
|
// b.guns[i].ammoPack = this.ammoBonus;
|
||||||
|
// b.guns[i].ammo = b.guns[i].ammo * this.ammoBonus;
|
||||||
|
// simulation.updateGunHUD();
|
||||||
|
// break
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
|
// remove() {
|
||||||
|
// if (tech.isRailGun) {
|
||||||
|
// tech.isRailGun = false;
|
||||||
|
// for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||||
|
// if (b.guns[i].name === "harpoon") {
|
||||||
|
// b.guns[i].chooseFireMethod()
|
||||||
|
// b.guns[i].ammoPack = 0.6;
|
||||||
|
// b.guns[i].ammo = Math.ceil(b.guns[i].ammo / this.ammoBonus);
|
||||||
|
// simulation.updateGunHUD();
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "nematodes",
|
name: "nematodes",
|
||||||
description: "<strong>shotgun</strong> and <strong class='color-p' style='letter-spacing: 2px;'>sporangium</strong> hatch <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong><br><strong class='color-p' style='letter-spacing: 2px;'>spore</strong> <strong class='color-m'>tech</strong> applies to <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong>",
|
description: "<strong>shotgun</strong> and <strong class='color-p' style='letter-spacing: 2px;'>sporangium</strong> hatch <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong><br><strong class='color-p' style='letter-spacing: 2px;'>spore</strong> <strong class='color-m'>tech</strong> applies to <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong>",
|
||||||
@@ -5302,9 +5331,9 @@ const tech = {
|
|||||||
frequency: 3,
|
frequency: 3,
|
||||||
frequencyDefault: 3,
|
frequencyDefault: 3,
|
||||||
allowed() {
|
allowed() {
|
||||||
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || (tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isRivets && !tech.isIceShot && !tech.isFoamShot && !tech.isNeedles && !tech.isNailShot)
|
return (tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || (tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isRivets && !tech.isIceShot && !tech.isFoamShot && !tech.isNeedles && !tech.isNailShot)) && !tech.isSporeFlea
|
||||||
},
|
},
|
||||||
requires: "spores",
|
requires: "spores, not fleas",
|
||||||
effect() {
|
effect() {
|
||||||
tech.isSporeWorm = true
|
tech.isSporeWorm = true
|
||||||
},
|
},
|
||||||
@@ -5333,7 +5362,7 @@ const tech = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "path integration",
|
name: "path integration",
|
||||||
description: "<strong>drones</strong>, <strong class='color-p' style='letter-spacing: 2px;'>spores</strong>, and <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong><br>travel with you through <strong>levels</strong>",
|
description: "<strong>drones</strong>, <strong class='color-p' style='letter-spacing: 2px;'>spores</strong>, <strong class='color-p' style='letter-spacing: -0.8px;'>fleas</strong>, and <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong><br>travel with you through <strong>levels</strong>",
|
||||||
isGunTech: true,
|
isGunTech: true,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -5342,7 +5371,7 @@ const tech = {
|
|||||||
allowed() {
|
allowed() {
|
||||||
return (tech.isSporeFollow && (tech.haveGunCheck("spores") || (tech.haveGunCheck("shotgun") && tech.isSporeWorm))) || tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isMissileField || tech.isIceField))
|
return (tech.isSporeFollow && (tech.haveGunCheck("spores") || (tech.haveGunCheck("shotgun") && tech.isSporeWorm))) || tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isMissileField || tech.isIceField))
|
||||||
},
|
},
|
||||||
requires: "spores, worms, diplochory, drones",
|
requires: "spores, worms, flagella, drones",
|
||||||
effect() {
|
effect() {
|
||||||
tech.isDronesTravel = true
|
tech.isDronesTravel = true
|
||||||
},
|
},
|
||||||
@@ -5353,7 +5382,7 @@ const tech = {
|
|||||||
{
|
{
|
||||||
name: "anti-shear topology",
|
name: "anti-shear topology",
|
||||||
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Topology' class="link">anti-shear topology</a>`,
|
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Topology' class="link">anti-shear topology</a>`,
|
||||||
description: "<strong>+30%</strong> projectile <strong>duration</strong><br><em style = 'font-size: 83%'>drone, spore, worm, missile, foam, wave, neutron, ice</em>",
|
description: "<strong>+30%</strong> projectile <strong>duration</strong><br><em style = 'font-size: 83%'>drone spore worm flea missile foam wave neutron ice</em>",
|
||||||
isGunTech: true,
|
isGunTech: true,
|
||||||
maxCount: 3,
|
maxCount: 3,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -5362,7 +5391,7 @@ const tech = {
|
|||||||
allowed() {
|
allowed() {
|
||||||
return m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || tech.haveGunCheck("spores") || tech.haveGunCheck("drones") || tech.haveGunCheck("missiles") || tech.haveGunCheck("foam") || tech.haveGunCheck("matter wave") || tech.isNeutronBomb || tech.isIceField || tech.isIceShot || tech.relayIce || tech.isNeedleIce || tech.blockingIce > 1 || tech.isSporeWorm || tech.isFoamBotUpgrade || tech.isFoamBall
|
return m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || tech.haveGunCheck("spores") || tech.haveGunCheck("drones") || tech.haveGunCheck("missiles") || tech.haveGunCheck("foam") || tech.haveGunCheck("matter wave") || tech.isNeutronBomb || tech.isIceField || tech.isIceShot || tech.relayIce || tech.isNeedleIce || tech.blockingIce > 1 || tech.isSporeWorm || tech.isFoamBotUpgrade || tech.isFoamBall
|
||||||
},
|
},
|
||||||
requires: "drones, spores, missiles, foam, matter wave, neutron bomb, ice IX",
|
requires: "drones, spores, missiles, foam, matter wave, neutron bomb, ice IX, flea",
|
||||||
effect() {
|
effect() {
|
||||||
tech.isBulletsLastLonger += 0.3
|
tech.isBulletsLastLonger += 0.3
|
||||||
},
|
},
|
||||||
@@ -5662,14 +5691,14 @@ const tech = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "necrophage",
|
name: "necrophage",
|
||||||
description: "if <strong>foam</strong> or <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> <strong>kill</strong> their target<br>grow 3 <strong>copies</strong>",
|
description: "if <strong>foam</strong>, <strong class='color-p' style='letter-spacing: -0.8px;'>fleas</strong>, or <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> <strong>kill</strong> their target<br>grow 3 <strong>copies</strong>",
|
||||||
isGunTech: true,
|
isGunTech: true,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 2,
|
frequency: 2,
|
||||||
frequencyDefault: 2,
|
frequencyDefault: 2,
|
||||||
allowed() {
|
allowed() {
|
||||||
return tech.haveGunCheck("foam") || tech.isFoamBall || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isSporeWorm
|
return tech.haveGunCheck("foam") || tech.isFoamBall || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isSporeWorm || tech.isSporeFlea
|
||||||
},
|
},
|
||||||
requires: "foam, worms",
|
requires: "foam, worms",
|
||||||
effect() {
|
effect() {
|
||||||
@@ -5818,7 +5847,7 @@ const tech = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "railgun",
|
name: "railgun",
|
||||||
description: `<strong>+50%</strong> <strong>harpoon</strong> density, but they don't <strong>retract</strong><br><strong>+800%</strong> harpoon <strong class='color-ammo'>ammo</strong> per ${powerUps.orb.ammo(1)}`,
|
description: `<strong>+50%</strong> <strong>harpoon</strong> density, but they don't <strong>retract</strong><br><strong>+900%</strong> harpoon <strong class='color-ammo'>ammo</strong> per ${powerUps.orb.ammo(1)}`,
|
||||||
isGunTech: true,
|
isGunTech: true,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -5828,7 +5857,7 @@ const tech = {
|
|||||||
return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.isHarpoonPowerUp && !tech.isGrapple
|
return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.isHarpoonPowerUp && !tech.isGrapple
|
||||||
},
|
},
|
||||||
requires: "harpoon, not UHMWPE, induction furnace, grappling hook",
|
requires: "harpoon, not UHMWPE, induction furnace, grappling hook",
|
||||||
ammoBonus: 8,
|
ammoBonus: 9,
|
||||||
effect() {
|
effect() {
|
||||||
tech.isRailGun = true;
|
tech.isRailGun = true;
|
||||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||||
@@ -6109,7 +6138,7 @@ const tech = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "laser diode",
|
name: "laser diode",
|
||||||
description: "<strong>+30%</strong> <strong class='color-laser'>laser</strong> <strong class='color-f'>energy</strong> efficiency<br><em>affects laser-gun, laser-bot, laser-mines, pulse</em>",
|
description: "<strong>+33%</strong> <strong class='color-laser'>laser</strong> <strong class='color-f'>energy</strong> efficiency",
|
||||||
isGunTech: true,
|
isGunTech: true,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -6120,7 +6149,7 @@ const tech = {
|
|||||||
},
|
},
|
||||||
requires: "laser, not free-electron",
|
requires: "laser, not free-electron",
|
||||||
effect() {
|
effect() {
|
||||||
tech.isLaserDiode = 0.70; //100%-37%
|
tech.isLaserDiode = 0.66; //100%-37%
|
||||||
tech.laserColor = "rgb(0, 11, 255)"
|
tech.laserColor = "rgb(0, 11, 255)"
|
||||||
tech.laserColorAlpha = "rgba(0, 11, 255,0.5)"
|
tech.laserColorAlpha = "rgba(0, 11, 255,0.5)"
|
||||||
},
|
},
|
||||||
@@ -6177,7 +6206,7 @@ const tech = {
|
|||||||
{
|
{
|
||||||
name: "iridescence",
|
name: "iridescence",
|
||||||
// description: "if a <strong class='color-laser'>laser</strong> hits a mob at a low angle of illumination<br><strong>+66%</strong> <strong class='color-laser'>laser</strong> <strong class='color-d'>damage</strong>",
|
// description: "if a <strong class='color-laser'>laser</strong> hits a mob at a low angle of illumination<br><strong>+66%</strong> <strong class='color-laser'>laser</strong> <strong class='color-d'>damage</strong>",
|
||||||
description: "if mobs are struck near their <strong>center</strong><br><strong>+88%</strong> <strong class='color-laser'>laser</strong> <strong class='color-d'>damage</strong>",
|
description: "if <strong class='color-laser'>laser</strong> beams hit mobs near their <strong>center</strong><br><strong>+88%</strong> <strong class='color-laser'>laser</strong> <strong class='color-d'>damage</strong>",
|
||||||
isGunTech: true,
|
isGunTech: true,
|
||||||
maxCount: 3,
|
maxCount: 3,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -6196,7 +6225,7 @@ const tech = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "lens",
|
name: "lens",
|
||||||
description: "if directed through a revolving <strong>+<span style='font-size: 125%;'>π</span> / 4</strong> circular arc<br><strong>+150%</strong> <strong class='color-laser'>laser</strong> gun <strong class='color-d'>damage</strong>",
|
description: "<strong>+150%</strong> <strong class='color-laser'>laser</strong> gun <strong class='color-d'>damage</strong> if it passes<br>through a revolving <strong>+90°</strong> arc circular lens", //<span style='font-size: 125%;'>π</span> / 2</strong>
|
||||||
isGunTech: true,
|
isGunTech: true,
|
||||||
maxCount: 3,
|
maxCount: 3,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -6255,7 +6284,7 @@ const tech = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "diffraction grating",
|
name: "diffraction grating",
|
||||||
description: `<strong>+1</strong> <strong class='color-laser'>laser</strong> gun beam`,
|
description: `<strong>+1</strong> diverging <strong class='color-laser'>laser</strong> gun beam`,
|
||||||
isGunTech: true,
|
isGunTech: true,
|
||||||
maxCount: 9,
|
maxCount: 9,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -6384,7 +6413,7 @@ const tech = {
|
|||||||
frequency: 2,
|
frequency: 2,
|
||||||
frequencyDefault: 2,
|
frequencyDefault: 2,
|
||||||
allowed() {
|
allowed() {
|
||||||
return tech.isPulseLaser && !tech.beamSplitter
|
return tech.haveGunCheck("laser") && tech.isPulseLaser && !tech.beamSplitter
|
||||||
},
|
},
|
||||||
requires: "laser gun, pulse, not diffraction grating",
|
requires: "laser gun, pulse, not diffraction grating",
|
||||||
effect() {
|
effect() {
|
||||||
@@ -7090,7 +7119,7 @@ const tech = {
|
|||||||
frequency: 2,
|
frequency: 2,
|
||||||
frequencyDefault: 2,
|
frequencyDefault: 2,
|
||||||
allowed() {
|
allowed() {
|
||||||
return tech.isExtruder
|
return m.fieldUpgrades[m.fieldMode].name === "plasma torch" && tech.isExtruder
|
||||||
},
|
},
|
||||||
requires: "extruder",
|
requires: "extruder",
|
||||||
effect() {
|
effect() {
|
||||||
@@ -7146,8 +7175,8 @@ const tech = {
|
|||||||
isFieldTech: true,
|
isFieldTech: true,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 2,
|
frequency: 1,
|
||||||
frequencyDefault: 2,
|
frequencyDefault: 1,
|
||||||
allowed() {
|
allowed() {
|
||||||
return m.fieldUpgrades[m.fieldMode].name === "time dilation" && !m.isShipMode && !tech.isRewindAvoidDeath && !tech.isEnergyHealth && !tech.isTimeSkip
|
return m.fieldUpgrades[m.fieldMode].name === "time dilation" && !m.isShipMode && !tech.isRewindAvoidDeath && !tech.isEnergyHealth && !tech.isTimeSkip
|
||||||
},
|
},
|
||||||
@@ -7162,6 +7191,27 @@ const tech = {
|
|||||||
if (this.count) m.fieldUpgrades[m.fieldMode].set()
|
if (this.count) m.fieldUpgrades[m.fieldMode].set()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "frame-dragging", //"non-inertial frame",
|
||||||
|
description: "when not <strong>moving</strong> time dilation <strong style='letter-spacing: 2px;'>stops time</strong><br><strong>+33%</strong> <strong class='color-defense'>defense</strong>",
|
||||||
|
isFieldTech: true,
|
||||||
|
maxCount: 1,
|
||||||
|
count: 0,
|
||||||
|
frequency: 1,
|
||||||
|
frequencyDefault: 1,
|
||||||
|
allowed() {
|
||||||
|
return m.fieldUpgrades[m.fieldMode].name === "time dilation"
|
||||||
|
},
|
||||||
|
requires: "time dilation",
|
||||||
|
effect() {
|
||||||
|
tech.isTimeStop = true;
|
||||||
|
m.fieldHarmReduction = 0.66; //33% reduction
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
tech.isTimeStop = false;
|
||||||
|
if (m.fieldUpgrades[m.fieldMode].name === "time dilation") m.fieldHarmReduction = 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Lorentz transformation",
|
name: "Lorentz transformation",
|
||||||
description: `use ${powerUps.orb.research(3)}<br><strong>+50%</strong> <strong>movement</strong>, <strong>jumping</strong>, and <strong><em>fire rate</em></strong>`,
|
description: `use ${powerUps.orb.research(3)}<br><strong>+50%</strong> <strong>movement</strong>, <strong>jumping</strong>, and <strong><em>fire rate</em></strong>`,
|
||||||
@@ -7235,7 +7285,7 @@ const tech = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "quantum eraser",
|
name: "quantum eraser",
|
||||||
descriptionFunction() { return `<span style = 'font-size:90%;'>for each mob left <strong>alive</strong> after you exit a <strong>level</strong><br><strong>kill</strong> a mob as they spawn at <strong>${100-simulation.difficultyMode**2}%</strong> <strong class='color-dup'>duplication</strong></span>` },
|
descriptionFunction() { return `<span style = 'font-size:90%;'>for each mob left <strong>alive</strong> after you exit a <strong>level</strong><br><strong>kill</strong> a mob as they spawn at <strong>+${100-1.6*simulation.difficultyMode**2}%</strong> <strong class='color-dup'>duplication</strong></span>` },
|
||||||
|
|
||||||
description: `<span style = 'font-size:90%;'>for each mob left <strong>alive</strong> after you exit a <strong>level</strong><br><strong>kill</strong> a mob as they spawn at <strong>100%</strong> <strong class='color-dup'>duplication</strong></span>`,
|
description: `<span style = 'font-size:90%;'>for each mob left <strong>alive</strong> after you exit a <strong>level</strong><br><strong>kill</strong> a mob as they spawn at <strong>100%</strong> <strong class='color-dup'>duplication</strong></span>`,
|
||||||
isFieldTech: true,
|
isFieldTech: true,
|
||||||
@@ -10403,6 +10453,7 @@ const tech = {
|
|||||||
isFastTime: null,
|
isFastTime: null,
|
||||||
isAnthropicTech: null,
|
isAnthropicTech: null,
|
||||||
isSporeWorm: null,
|
isSporeWorm: null,
|
||||||
|
isSporeFlea: null,
|
||||||
isFoamShot: null,
|
isFoamShot: null,
|
||||||
isIceShot: null,
|
isIceShot: null,
|
||||||
isBlockRestitution: null,
|
isBlockRestitution: null,
|
||||||
|
|||||||
63
todo.txt
63
todo.txt
@@ -1,32 +1,46 @@
|
|||||||
******************************************************** NEXT PATCH **************************************************
|
******************************************************** NEXT PATCH **************************************************
|
||||||
|
|
||||||
tech: iridescence - laser does 100% damage to mobs hit near their center
|
tech: fleas - replace spores with little hoppers
|
||||||
tech: lens - laser does extra damage if you fire through a lens that revolves around you
|
|
||||||
tech: arc length - increase the size of the lens
|
|
||||||
|
|
||||||
virtual particles costs 4->6 research for 11% duplication
|
frame-dragging - time dilation field stops time when you aren't moving or firing, +33% defense
|
||||||
quantum eraser has less duplication chance at higher difficulty modes
|
the odds of finding this tech is low because I find it kinda annoying, but maybe you will like it
|
||||||
community map temple updates
|
|
||||||
|
molecular assembler field energy meter is yellow
|
||||||
|
wormhole is lavender
|
||||||
|
perfect diamagnetism is blue
|
||||||
|
time dilation is green blue
|
||||||
|
pilot wave is black
|
||||||
|
|
||||||
|
new room in labs: hopBossMom
|
||||||
|
harpoon now auto targets by default, but disabled when crouched
|
||||||
|
pulse + neocognitron auto targeting also disabled when crouched
|
||||||
|
|
||||||
bug fixes
|
bug fixes
|
||||||
|
|
||||||
*********************************************************** TODO *****************************************************
|
*********************************************************** TODO *****************************************************
|
||||||
|
|
||||||
give laser gun _____ if you fire in an angle range
|
fleas
|
||||||
draw angle range as a slowly rotation circle arc around player
|
add very short (2 cycle) delay after each landing -> hop
|
||||||
effect:
|
zero velocity while on short delay? try it?
|
||||||
bonus damage
|
flea tech:
|
||||||
extra beams
|
add a delay to flea jumping also +dmg
|
||||||
extra reflections
|
reduce lifespan after hitting mob, like drones
|
||||||
|
but add in a long cooldown after a hit
|
||||||
|
mid flight attraction towards nearby mobs?
|
||||||
|
if close to mob and line of sight: set isAttached flag = true
|
||||||
|
draw a line to mob, attraction
|
||||||
|
reset isAttached to false after: 1-2s or distance gets too big
|
||||||
|
tech for shotgun?
|
||||||
|
|
||||||
laser tech: critical hits do _______ damage?
|
anti-shear topology apply to grenades too? and other less useful bullets
|
||||||
name? polarized light, iridescence
|
then open up tech requirements
|
||||||
|
|
||||||
hopBossMom
|
menagerie: sporangium release a variety of things
|
||||||
spawns lots of small hopBullets
|
spores, worms, hoppers, drones, iceIX?, foam?, missiles?
|
||||||
drops eggs, that hatch into hopBullets
|
benefit: they release more stuff than normal
|
||||||
like sporangium
|
|
||||||
normally runs away from player, but goes closer to drop eggs
|
swim through slime
|
||||||
|
hold up to float while in slime?
|
||||||
|
|
||||||
level element: exploding barrels
|
level element: exploding barrels
|
||||||
|
|
||||||
@@ -34,22 +48,12 @@ improve mob invincible graphic
|
|||||||
opacity oscillates from 100% to 0%?
|
opacity oscillates from 100% to 0%?
|
||||||
make different from stun
|
make different from stun
|
||||||
|
|
||||||
junk tech give strange CSS to a keyword
|
|
||||||
@keyframes bounce-munch {
|
|
||||||
0% {vertical-align: -40px;}
|
|
||||||
100% {vertical-align: 40px;}
|
|
||||||
}
|
|
||||||
|
|
||||||
make plasma ball power up and block pick up still work when you have no no energy
|
make plasma ball power up and block pick up still work when you have no no energy
|
||||||
make a unique CD var for plasma ball?
|
make a unique CD var for plasma ball?
|
||||||
|
|
||||||
wormhole tech: entropic gravity - gain defense for each research
|
wormhole tech: entropic gravity - gain defense for each research
|
||||||
requires wormhole or negative mass field or pilot wave
|
requires wormhole or negative mass field or pilot wave
|
||||||
|
|
||||||
shrapnel: a new bullet type: a very small bullet with no targeting that has a high gravity arc
|
|
||||||
maybe 1 bounce or no bounce before it ends on map or mob collision
|
|
||||||
often spawns in groups
|
|
||||||
|
|
||||||
testChamber2
|
testChamber2
|
||||||
mechanics
|
mechanics
|
||||||
companion cube
|
companion cube
|
||||||
@@ -184,6 +188,7 @@ tech expansion: should also make other fields do things
|
|||||||
perfect diamagnetism moves forward when you hold down the shield
|
perfect diamagnetism moves forward when you hold down the shield
|
||||||
it's great, but maybe annoying?
|
it's great, but maybe annoying?
|
||||||
maybe only with crouch?
|
maybe only with crouch?
|
||||||
|
perfect diamagnetism just replace Messier effect
|
||||||
time dilation drains 1/2 as much energy when paused
|
time dilation drains 1/2 as much energy when paused
|
||||||
grow plasma torch as you hold it down
|
grow plasma torch as you hold it down
|
||||||
negative mass effects much more space
|
negative mass effects much more space
|
||||||
|
|||||||
Reference in New Issue
Block a user