worm-shot, ice-shot, needle-shot, foam-shot

shotgun techs:
  (I haven't done enough testing so let me know if these different shotgun modes aren't balanced)
  worm shot
  ice-IX shot
  foam shot
  needle shot

foam lasts much longer on shielded mobs
  overall foam damage is reduced about 8%

attacks that drain energy don't work when the player is immune to harm
  slime, radiation fields, black holes
energy regen that consumes something (ammo, blocks, power ups) now works when immune to harm
  but passive energy regen is still stopped while you are immune to harm

pilot wave field can no longer hit intangible mobs with blocks
  it was too annoying that you can't use blocks to move around so I reverted it back
This commit is contained in:
landgreen
2021-07-25 05:53:27 -07:00
parent a57639987a
commit 271791703f
10 changed files with 394 additions and 262 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -329,7 +329,7 @@ const b = {
if (Vector.magnitude(Vector.sub(where, player.position)) < radius) { if (Vector.magnitude(Vector.sub(where, player.position)) < radius) {
const DRAIN = (tech.isExplosionHarm ? 0.5 : 0.25) * (tech.isRadioactiveResistance ? 0.25 : 1) const DRAIN = (tech.isExplosionHarm ? 0.5 : 0.25) * (tech.isRadioactiveResistance ? 0.25 : 1)
// * (tech.isImmuneExplosion ? Math.min(1, Math.max(1 - m.energy * 0.7, 0)) : 1) // * (tech.isImmuneExplosion ? Math.min(1, Math.max(1 - m.energy * 0.7, 0)) : 1)
m.energy -= DRAIN if (m.immuneCycle < m.cycle) m.energy -= DRAIN
if (m.energy < 0) { if (m.energy < 0) {
m.energy = 0 m.energy = 0
m.damage(0.03 * (tech.isRadioactiveResistance ? 0.25 : 1)); m.damage(0.03 * (tech.isRadioactiveResistance ? 0.25 : 1));
@@ -1036,7 +1036,7 @@ const b = {
if (Vector.magnitude(Vector.sub(player.position, this.position)) < this.damageRadius) { if (Vector.magnitude(Vector.sub(player.position, this.position)) < this.damageRadius) {
const DRAIN = tech.isRadioactiveResistance ? 0.0025 * 0.25 : 0.0025 const DRAIN = tech.isRadioactiveResistance ? 0.0025 * 0.25 : 0.0025
if (m.energy > DRAIN) { if (m.energy > DRAIN) {
m.energy -= DRAIN if (m.immuneCycle < m.cycle) m.energy -= DRAIN
} else { } else {
m.energy = 0; m.energy = 0;
m.damage(tech.isRadioactiveResistance ? 0.00016 * 0.25 : 0.00016) //0.00015 m.damage(tech.isRadioactiveResistance ? 0.00016 * 0.25 : 0.00016) //0.00015
@@ -1861,7 +1861,7 @@ const b = {
}, },
onEnd() { onEnd() {
if (tech.isMutualism && this.isMutualismActive && !tech.isEnergyHealth) { if (tech.isMutualism && this.isMutualismActive && !tech.isEnergyHealth) {
m.health += 0.005 m.health += 0.005 + 0.005 * tech.isSporeWorm
if (m.health > m.maxHealth) m.health = m.maxHealth; if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth(); m.displayHealth();
} }
@@ -1919,7 +1919,7 @@ const b = {
}); });
World.add(engine.world, bullet[bIndex]); //add bullet to world World.add(engine.world, bullet[bIndex]); //add bullet to world
if (tech.isMutualism && m.health > 0.02) { if (tech.isMutualism && m.health > 0.02) {
m.health -= 0.005 m.health -= 0.005 - 0.005 * tech.isSporeWorm
m.displayHealth(); m.displayHealth();
bullet[bIndex].isMutualismActive = true bullet[bIndex].isMutualismActive = true
} }
@@ -1957,7 +1957,7 @@ const b = {
}, },
onEnd() { onEnd() {
if (tech.isMutualism && this.isMutualismActive && !tech.isEnergyHealth) { if (tech.isMutualism && this.isMutualismActive && !tech.isEnergyHealth) {
m.health += 0.005 m.health += 0.005 + 0.005 * tech.isSporeWorm
if (m.health > m.maxHealth) m.health = m.maxHealth; if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth(); m.displayHealth();
} }
@@ -2040,7 +2040,7 @@ const b = {
World.add(engine.world, bullet[bIndex]); //add bullet to world World.add(engine.world, bullet[bIndex]); //add bullet to world
if (tech.isMutualism && m.health > 0.02) { if (tech.isMutualism && m.health > 0.02) {
m.health -= 0.005 m.health -= 0.005 - 0.005 * tech.isSporeWorm
m.displayHealth(); m.displayHealth();
bullet[bIndex].isMutualismActive = true bullet[bIndex].isMutualismActive = true
} }
@@ -2048,17 +2048,18 @@ const b = {
}, },
iceIX(speed = 0, dir = m.angle + Math.PI * 2 * Math.random(), where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }) { iceIX(speed = 0, dir = m.angle + Math.PI * 2 * Math.random(), where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }) {
const me = bullet.length; const me = bullet.length;
const THRUST = 0.004 const THRUST = 0.0006
const RADIUS = 18 const RADIUS = 18
const SCALE = 1 - 0.08 / tech.isBulletsLastLonger
bullet[me] = Bodies.polygon(where.x, where.y, 3, RADIUS, { bullet[me] = Bodies.polygon(where.x, where.y, 3, RADIUS, {
angle: dir - Math.PI, angle: dir - Math.PI,
inertia: Infinity, inertia: Infinity,
friction: 0, friction: 0,
frictionAir: 0.10, frictionAir: 0.023,
restitution: 0.3, restitution: 0.9,
dmg: 0.42, //damage done in addition to the damage from momentum dmg: 0.5, //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 + 140 * tech.isBulletsLastLonger, endCycle: simulation.cycle + 150 * tech.isBulletsLastLonger + Math.floor(25 * Math.random()),
classType: "bullet", classType: "bullet",
collisionFilter: { collisionFilter: {
category: cat.bullet, category: cat.bullet,
@@ -2071,13 +2072,8 @@ const b = {
mobs.statusSlow(who, 180) mobs.statusSlow(who, 180)
this.endCycle = simulation.cycle this.endCycle = simulation.cycle
// if (tech.isHeavyWater) mobs.statusDoT(who, 0.15, 300) // if (tech.isHeavyWater) mobs.statusDoT(who, 0.15, 300)
if (m.immuneCycle < m.cycle && tech.iceEnergy && !who.shield && !who.isShielded && who.isDropPowerUp && who.alive && m.immuneCycle < m.cycle) { if (tech.iceEnergy && !who.shield && !who.isShielded && who.isDropPowerUp && who.alive && m.immuneCycle < m.cycle) {
setTimeout(function() { setTimeout(() => { if (!who.alive) m.energy += tech.iceEnergy * 0.8 }, 10);
if (!who.alive) {
m.energy += tech.iceEnergy * 0.8
// m.addHealth(tech.iceEnergy * 0.04)
}
}, 10);
} }
}, },
onEnd() {}, onEnd() {},
@@ -2085,8 +2081,7 @@ const b = {
// this.force.y += this.mass * 0.0002; // this.force.y += this.mass * 0.0002;
//find mob targets //find mob targets
if (!(simulation.cycle % this.lookFrequency)) { if (!(simulation.cycle % this.lookFrequency)) {
const scale = 1 - 0.08 / tech.isBulletsLastLonger //0.9 * tech.isBulletsLastLonger; Matter.Body.scale(this, SCALE, SCALE);
Matter.Body.scale(this, scale, scale);
this.lockedOn = null; this.lockedOn = null;
let closeDist = Infinity; let closeDist = Infinity;
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
@@ -2380,7 +2375,7 @@ const b = {
if (Vector.magnitude(Vector.sub(player.position, this.position)) < this.radioRadius) { if (Vector.magnitude(Vector.sub(player.position, this.position)) < this.radioRadius) {
const DRAIN = tech.isRadioactiveResistance ? 0.0023 * 0.25 : 0.0023 const DRAIN = tech.isRadioactiveResistance ? 0.0023 * 0.25 : 0.0023
if (m.energy > DRAIN) { if (m.energy > DRAIN) {
m.energy -= DRAIN if (m.immuneCycle < m.cycle) m.energy -= DRAIN
} else { } else {
m.energy = 0; m.energy = 0;
m.damage(tech.isRadioactiveResistance ? 0.00015 * 0.25 : 0.00015) //0.00015 m.damage(tech.isRadioactiveResistance ? 0.00015 * 0.25 : 0.00015) //0.00015
@@ -2543,14 +2538,11 @@ const b = {
// radius *= Math.sqrt(tech.bulletSize) // radius *= Math.sqrt(tech.bulletSize)
const me = bullet.length; const me = bullet.length;
bullet[me] = Bodies.polygon(position.x, position.y, 20, radius, { bullet[me] = Bodies.polygon(position.x, position.y, 20, radius, {
// angle: 0,
density: 0.000001, // 0.001 is normal density density: 0.000001, // 0.001 is normal density
inertia: Infinity, inertia: Infinity,
frictionAir: 0.003, frictionAir: 0.003,
// friction: 0.2,
// restitution: 0.2,
dmg: 0, //damage on impact dmg: 0, //damage on impact
damage: (tech.isFastFoam ? 0.048 : 0.012) * (tech.isFoamTeleport ? 1.66 : 1), //damage done over time damage: (tech.isFastFoam ? 0.044 : 0.011) * (tech.isFoamTeleport ? 1.66 : 1), //damage done over time
scale: 1 - 0.006 / tech.isBulletsLastLonger * (tech.isFastFoam ? 1.6 : 1), scale: 1 - 0.006 / tech.isBulletsLastLonger * (tech.isFastFoam ? 1.6 : 1),
classType: "bullet", classType: "bullet",
collisionFilter: { collisionFilter: {
@@ -2610,9 +2602,6 @@ const b = {
this.radius *= this.scale; this.radius *= this.scale;
if (this.radius < 8) this.endCycle = 0; if (this.radius < 8) this.endCycle = 0;
} }
if (this.target && this.target.alive) { //if stuck to a target if (this.target && this.target.alive) { //if stuck to a target
const rotate = Vector.rotate(this.targetRelativePosition, this.target.angle) //add in the mob's new angle to the relative position vector const rotate = Vector.rotate(this.targetRelativePosition, this.target.angle) //add in the mob's new angle to the relative position vector
if (this.target.isVerticesChange) { if (this.target.isVerticesChange) {
@@ -2622,12 +2611,10 @@ const b = {
} }
Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.9)) Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.9))
Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9); Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9);
// Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9) // Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9)
if (this.target.isShielded) { if (this.target.isShielded) {
this.target.damage(b.dmgScale * this.damage, true); //shield damage bypass this.target.damage(b.dmgScale * this.damage, true); //shield damage bypass
//shrink if mob is shielded const SCALE = 1 - 0.004 / tech.isBulletsLastLonger //shrink if mob is shielded
const SCALE = 1 - 0.01 / tech.isBulletsLastLonger
Matter.Body.scale(this, SCALE, SCALE); Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE; this.radius *= SCALE;
} else { } else {
@@ -2641,9 +2628,7 @@ const b = {
let targets = [] let targets = []
for (let i = 0, len = mob.length; i < len; i++) { for (let i = 0, len = mob.length; i < len; i++) {
const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)); const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
if (dist < 1000000) { if (dist < 1000000) targets.push(mob[i])
targets.push(mob[i])
}
} }
const radius = Math.min(this.radius * 0.5, 10) const radius = Math.min(this.radius * 0.5, 10)
const len = bullet.length < 100 ? 2 : 1 const len = bullet.length < 100 ? 2 : 1
@@ -2682,7 +2667,6 @@ const b = {
this.radius *= SCALE; this.radius *= SCALE;
} else { } else {
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) {
@@ -2768,6 +2752,71 @@ const b = {
}; };
bullet[me].do = function() {}; bullet[me].do = function() {};
}, },
needle(angle = m.angle) {
const me = bullet.length;
bullet[me] = Bodies.rectangle(m.pos.x + 40 * Math.cos(m.angle), m.pos.y + 40 * Math.sin(m.angle), 75, 0.75, b.fireAttributes(angle));
bullet[me].collisionFilter.mask = tech.isNeedleShieldPierce ? cat.body : cat.body | cat.mobShield
Matter.Body.setDensity(bullet[me], 0.00001); //0.001 is normal
bullet[me].endCycle = simulation.cycle + 180;
bullet[me].immuneList = []
bullet[me].do = function() {
const whom = Matter.Query.collides(this, mob)
if (whom.length && this.speed > 20) { //if touching a mob
for (let i = 0, len = whom.length; i < len; i++) {
who = whom[i].bodyA
if (who && who.mob) {
let immune = false
for (let i = 0; i < this.immuneList.length; i++) { //check if this needle has hit this mob already
if (this.immuneList[i] === who.id) {
immune = true
break
}
}
if (!immune) {
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.975) {
b.explosion(this.position, 220 + 50 * Math.random()); //makes bullet do explosive damage at end
}
this.immuneList.push(who.id) //remember that this needle has hit this mob once already
who.foundPlayer();
if (tech.isNailRadiation) {
mobs.statusDoT(who, tech.isFastRadiation ? 12 : 3, tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
} else {
let dmg = b.dmgScale * 5.5
if (tech.isCrit && who.isStunned) dmg *= 4
who.damage(dmg, tech.isNeedleShieldPierce);
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: Math.log(2 * dmg + 1.1) * 40,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
}
}
}
}
} else if (Matter.Query.collides(this, map).length) { //stick in walls
this.collisionFilter.mask = 0;
Matter.Body.setAngularVelocity(this, 0)
Matter.Body.setVelocity(this, {
x: 0,
y: 0
});
this.do = function() {
if (!Matter.Query.collides(this, map).length) this.force.y += this.mass * 0.001;
}
} else if (this.speed < 30) {
this.force.y += this.mass * 0.001; //no gravity until it slows down to improve aiming
}
};
const SPEED = 90
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + SPEED * Math.cos(angle),
y: m.Vy / 2 + SPEED * Math.sin(angle)
});
// Matter.Body.setDensity(bullet[me], 0.00001);
World.add(engine.world, bullet[me]); //add bullet to world
},
// ************************************************************************************************** // **************************************************************************************************
// ************************************************************************************************** // **************************************************************************************************
// ******************************** Bots ********************************************* // ******************************** Bots *********************************************
@@ -3629,91 +3678,19 @@ const b = {
this.baseFire(m.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (m.crouch ? 1.35 : 3.2) / CD) this.baseFire(m.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (m.crouch ? 1.35 : 3.2) / CD)
}, },
fireNeedles() { fireNeedles() {
function makeNeedle(angle = m.angle) {
const me = bullet.length;
bullet[me] = Bodies.rectangle(m.pos.x + 40 * Math.cos(m.angle), m.pos.y + 40 * Math.sin(m.angle), 75, 0.75, b.fireAttributes(angle));
bullet[me].collisionFilter.mask = tech.isNeedleShieldPierce ? cat.body : cat.body | cat.mobShield
Matter.Body.setDensity(bullet[me], 0.00001); //0.001 is normal
bullet[me].endCycle = simulation.cycle + 180;
bullet[me].immuneList = []
bullet[me].do = function() {
const whom = Matter.Query.collides(this, mob)
if (whom.length && this.speed > 20) { //if touching a mob
for (let i = 0, len = whom.length; i < len; i++) {
who = whom[i].bodyA
if (who && who.mob) {
let immune = false
for (let i = 0; i < this.immuneList.length; i++) { //check if this needle has hit this mob already
if (this.immuneList[i] === who.id) {
immune = true
break
}
}
if (!immune) {
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.975) {
b.explosion(this.position, 220 + 50 * Math.random()); //makes bullet do explosive damage at end
}
this.immuneList.push(who.id) //remember that this needle has hit this mob once already
who.foundPlayer();
if (tech.isNailRadiation) {
mobs.statusDoT(who, tech.isFastRadiation ? 12 : 3, tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
} else {
let dmg = b.dmgScale * 5.5
if (tech.isCrit && who.isStunned) dmg *= 4
who.damage(dmg, tech.isNeedleShieldPierce);
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: Math.log(2 * dmg + 1.1) * 40,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
}
}
}
}
} else if (Matter.Query.collides(this, map).length) { //stick in walls
this.collisionFilter.mask = 0;
Matter.Body.setAngularVelocity(this, 0)
Matter.Body.setVelocity(this, {
x: 0,
y: 0
});
this.do = function() {
if (!Matter.Query.collides(this, map).length) this.force.y += this.mass * 0.001;
}
} else if (this.speed < 30) {
this.force.y += this.mass * 0.001; //no gravity until it slows down to improve aiming
}
};
const SPEED = 90
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + SPEED * Math.cos(angle),
y: m.Vy / 2 + SPEED * Math.sin(angle)
});
// Matter.Body.setDensity(bullet[me], 0.00001);
World.add(engine.world, bullet[me]); //add bullet to world
}
if (m.crouch) { if (m.crouch) {
m.fireCDcycle = m.cycle + 45 * b.fireCDscale; // cool down m.fireCDcycle = m.cycle + 45 * b.fireCDscale; // cool down
makeNeedle() b.needle()
for (let i = 1; i < 4; i++) { //4 total needles for (let i = 1; i < 4; i++) { //4 total needles
setTimeout(() => { if (!simulation.paused) makeNeedle() }, 60 * i); setTimeout(() => { if (!simulation.paused) b.needle() }, 60 * i);
} }
} else { } else {
m.fireCDcycle = m.cycle + 25 * b.fireCDscale; // cool down m.fireCDcycle = m.cycle + 25 * b.fireCDscale; // cool down
makeNeedle() b.needle()
for (let i = 1; i < 3; i++) { //3 total needles for (let i = 1; i < 3; i++) { //3 total needles
setTimeout(() => { if (!simulation.paused) makeNeedle() }, 60 * i); setTimeout(() => { if (!simulation.paused) b.needle() }, 60 * i);
} }
} }
// const spread = (m.crouch ? 0.013 : 0.06)
// makeNeedle(m.angle + spread)
// makeNeedle()
// makeNeedle(m.angle - spread)
}, },
fireRivets() { fireRivets() {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 25 : 17) * b.fireCDscale); // cool down m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 25 : 17) * b.fireCDscale); // cool down
@@ -3806,11 +3783,11 @@ const b = {
let knock, spread let knock, spread
if (m.crouch) { if (m.crouch) {
spread = 0.65 spread = 0.65
m.fireCDcycle = m.cycle + Math.floor(55 * b.fireCDscale); // cool down m.fireCDcycle = m.cycle + Math.floor(55 * b.fireCDscale) // cool down
if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(58 * b.fireCDscale)) m.immuneCycle = m.cycle + Math.floor(58 * b.fireCDscale); //player is immune to damage for 30 cycles if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(58 * b.fireCDscale)) m.immuneCycle = m.cycle + Math.floor(58 * b.fireCDscale); //player is immune to damage for 30 cycles
knock = 0.01 knock = 0.01
} else { } else {
m.fireCDcycle = m.cycle + Math.floor(45 * b.fireCDscale); // cool down m.fireCDcycle = m.cycle + Math.floor(45 * b.fireCDscale) // cool down
if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(47 * b.fireCDscale)) m.immuneCycle = m.cycle + Math.floor(47 * b.fireCDscale); //player is immune to damage for 30 cycles if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(47 * b.fireCDscale)) m.immuneCycle = m.cycle + Math.floor(47 * b.fireCDscale); //player is immune to damage for 30 cycles
spread = 1.3 spread = 1.3
knock = 0.1 knock = 0.1
@@ -3900,7 +3877,7 @@ const b = {
y: speed * Math.sin(dirOff) y: speed * Math.sin(dirOff)
}); });
bullet[me].onEnd = function() { bullet[me].onEnd = function() {
b.explosion(this.position, 150 * (tech.isShotgunReversed ? 1.6 : 1) + (Math.random() - 0.5) * 40); //makes bullet do explosive damage at end b.explosion(this.position, 160 * (tech.isShotgunReversed ? 1.6 : 1) + (Math.random() - 0.5) * 40); //makes bullet do explosive damage at end
} }
bullet[me].beforeDmg = function() { bullet[me].beforeDmg = function() {
this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion
@@ -3910,7 +3887,7 @@ const b = {
} }
} else if (tech.isNailShot) { } else if (tech.isNailShot) {
spread *= 0.65 spread *= 0.65
const dmg = 1.4 * (tech.isShotgunReversed ? 1.6 : 1) const dmg = 2 * (tech.isShotgunReversed ? 1.6 : 1)
if (m.crouch) { if (m.crouch) {
for (let i = 0; i < 17; i++) { for (let i = 0; i < 17; i++) {
speed = 38 + 15 * Math.random() speed = 38 + 15 * Math.random()
@@ -3938,6 +3915,49 @@ const b = {
}, dmg) }, dmg)
} }
} }
} else if (tech.isWormShot) {
const unit = {
x: Math.cos(m.angle),
y: Math.sin(m.angle)
}
const where = {
x: m.pos.x + 35 * unit.x,
y: m.pos.y + 35 * unit.y
}
for (let i = 0, len = 3 * (tech.isShotgunReversed ? 1.6 : 1) + Math.random(); i < len; i++) {
b.worm(where)
const SPEED = 14 + 6 * Math.random() + 20 * m.crouch;
Matter.Body.setVelocity(bullet[bullet.length - 1], {
x: SPEED * unit.x,
y: SPEED * unit.y
});
}
} else if (tech.isIceShot) {
const spread = (m.crouch ? 0.6 : 1.6)
for (let i = 0, len = 16 * (tech.isShotgunReversed ? 1.6 : 1); i < len; i++) {
// iceIX(speed = 0, dir = m.angle + Math.PI * 2 * Math.random(), where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }) {
b.iceIX(14 + 30 * Math.random(), m.angle + spread * (Math.random() - 0.5))
}
} else if (tech.isFoamShot) {
const spread = (m.crouch ? 0.35 : 0.7)
const where = {
x: m.pos.x + 25 * Math.cos(m.angle),
y: m.pos.y + 25 * Math.sin(m.angle)
}
const number = 14 * (tech.isShotgunReversed ? 1.6 : 1)
for (let i = 0; i < number; i++) {
const SPEED = 25 + 12 * Math.random();
const angle = m.angle + spread * (Math.random() - 0.5)
b.foam(where, { x: SPEED * Math.cos(angle), y: SPEED * Math.sin(angle) }, 5 + 8 * Math.random())
}
} else if (tech.isNeedleShot) {
const number = 12 * (tech.isShotgunReversed ? 1.6 : 1)
const spread = (m.crouch ? 0.04 : 0.08)
let angle = m.angle - (number - 1) * spread * 0.5
for (let i = 0; i < number; i++) {
b.needle(angle)
angle += spread
}
} else { } else {
const side = 22 const side = 22
for (let i = 0; i < 17; i++) { for (let i = 0; i < 17; i++) {
@@ -4843,7 +4863,7 @@ const b = {
if (tech.isCapacitor) { if (tech.isCapacitor) {
if ((m.energy > 0.16 || tech.isRailEnergyGain)) { //&& m.immuneCycle < m.cycle if ((m.energy > 0.16 || tech.isRailEnergyGain)) { //&& m.immuneCycle < m.cycle
if (m.immuneCycle < m.cycle) m.energy += 0.16 * (tech.isRailEnergyGain ? 6 : -1) m.energy += 0.16 * (tech.isRailEnergyGain ? 4.5 : -1)
m.fireCDcycle = m.cycle + Math.floor(30 * b.fireCDscale); m.fireCDcycle = m.cycle + Math.floor(30 * b.fireCDscale);
const me = bullet.length; const me = bullet.length;
bullet[me] = Bodies.rectangle(m.pos.x + 50 * Math.cos(m.angle), m.pos.y + 50 * Math.sin(m.angle), 60, 14, { bullet[me] = Bodies.rectangle(m.pos.x + 50 * Math.cos(m.angle), m.pos.y + 50 * Math.sin(m.angle), 60, 14, {
@@ -4970,7 +4990,7 @@ const b = {
bullet[me].charge = 0; bullet[me].charge = 0;
bullet[me].do = function() { bullet[me].do = function() {
if (m.energy < 0.005 && !tech.isRailEnergyGain) { if (m.energy < 0.005 && !tech.isRailEnergyGain) {
if (m.immuneCycle < m.cycle) m.energy += 0.05 + this.charge * 0.3 m.energy += 0.05 + this.charge * 0.2
m.fireCDcycle = m.cycle + 120; // cool down if out of energy m.fireCDcycle = m.cycle + 120; // cool down if out of energy
this.endCycle = 0; this.endCycle = 0;
return return
@@ -5019,7 +5039,7 @@ const b = {
let smoothRate = 0.98 * (m.crouch ? 0.99 : 1) * (0.98 + 0.02 * b.fireCDscale) //small b.fireCDscale = faster shots, b.fireCDscale=1 = normal shot, big b.fireCDscale = slower chot let smoothRate = 0.98 * (m.crouch ? 0.99 : 1) * (0.98 + 0.02 * b.fireCDscale) //small b.fireCDscale = faster shots, b.fireCDscale=1 = normal shot, big b.fireCDscale = slower chot
this.charge = this.charge * smoothRate + 1 * (1 - smoothRate) this.charge = this.charge * smoothRate + 1 * (1 - smoothRate)
if (tech.isRailEnergyGain) { if (tech.isRailEnergyGain) {
if (m.immuneCycle < m.cycle) m.energy += (this.charge - previousCharge) * 2 //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen m.energy += (this.charge - previousCharge) * 1.5 //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen
} else { } else {
m.energy -= (this.charge - previousCharge) * 0.33 //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen m.energy -= (this.charge - previousCharge) * 0.33 //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen
} }

View File

@@ -12,10 +12,15 @@ const level = {
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.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(60) //30 is near max on hard //60 is near max on why // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// m.setField("wormhole") // m.setField("wormhole")
// b.giveGuns("spores") // b.giveGuns("shotgun")
// b.giveGuns("foam")
// tech.isNeedleShot = true
// tech.isIceShot = true
// tech.isFoamShot = true
// tech.isWormShot = true
// tech.giveTech("CPT reversal") // tech.giveTech("CPT reversal")
// tech.giveTech("causality bombs") // tech.giveTech("causality bombs")
// b.giveGuns("wave beam") // b.giveGuns("wave beam")
@@ -966,12 +971,14 @@ const level = {
ctx.fillRect(this.min.x, this.min.y + offset, this.width, this.height - offset) ctx.fillRect(this.min.x, this.min.y + offset, this.width, this.height - offset)
if (this.height > 0 && Matter.Query.region([player], this).length) { if (this.height > 0 && Matter.Query.region([player], this).length) {
const DRAIN = 0.002 * (tech.isRadioactiveResistance ? 0.25 : 1) + m.fieldRegen if (m.immuneCycle < m.cycle) {
if (m.energy > DRAIN) { const DRAIN = 0.002 * (tech.isRadioactiveResistance ? 0.25 : 1) + m.fieldRegen
m.energy -= DRAIN if (m.energy > DRAIN) {
m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1) * 0.03) //still take 2% damage while you have energy m.energy -= DRAIN
} else { m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1) * 0.03) //still take 2% damage while you have energy
m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1)) } else {
m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1))
}
} }
//float //float
if (player.velocity.y > 5) player.force.y -= 0.95 * player.mass * simulation.g if (player.velocity.y > 5) player.force.y -= 0.95 * player.mass * simulation.g
@@ -1621,8 +1628,10 @@ const level = {
ctx.lineWidth = 2; ctx.lineWidth = 2;
if (Vector.magnitudeSquared(Vector.sub(m.pos, powerUp1.position)) < 90000) { //zone radius is 300 if (Vector.magnitudeSquared(Vector.sub(m.pos, powerUp1.position)) < 90000) { //zone radius is 300
//damage player and drain energy //damage player and drain energy
if (m.immuneCycle < m.cycle) m.damage(0.01); if (m.immuneCycle < m.cycle) {
if (m.energy > 0.1) m.energy -= 0.02 m.damage(0.01);
if (m.energy > 0.1) m.energy -= 0.02
}
//draw electricity going towards player //draw electricity going towards player
const unit = Vector.normalise(Vector.sub(m.pos, powerUp1.position)) const unit = Vector.normalise(Vector.sub(m.pos, powerUp1.position))
let xElec = powerUp1.position.x + 40 * unit.x; let xElec = powerUp1.position.x + 40 * unit.x;
@@ -2256,10 +2265,10 @@ const level = {
spawn.mapRect(6700, -1800, 800, 2600); //right wall spawn.mapRect(6700, -1800, 800, 2600); //right wall
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
// spawn.starter(1900, -500, 200) //big boy spawn.starter(1900, -500, 200) //big boy
spawn.growBossCulture(1900, -500) // spawn.growBossCulture(1900, -500)
// spawn.pulsarBoss(1900, -500) // spawn.snakeBoss(1900, -500)
// spawn.shieldingBoss(1900, -500) // spawn.shieldingBoss(1900, -500)
// spawn.grenadierBoss(1900, -500) // spawn.grenadierBoss(1900, -500)

View File

@@ -417,8 +417,10 @@ const mobs = {
ctx.setLineDash([125 * Math.random(), 125 * Math.random()]); ctx.setLineDash([125 * Math.random(), 125 * Math.random()]);
// ctx.lineDashOffset = 6*(simulation.cycle % 215); // ctx.lineDashOffset = 6*(simulation.cycle % 215);
if (this.distanceToPlayer() < this.laserRange) { if (this.distanceToPlayer() < this.laserRange) {
if (m.immuneCycle < m.cycle) m.damage(0.0003 * simulation.dmgScale); if (m.immuneCycle < m.cycle) {
if (m.energy > 0.1) m.energy -= 0.003 m.damage(0.0003 * simulation.dmgScale);
if (m.energy > 0.1) m.energy -= 0.003
}
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(this.position.x, this.position.y); ctx.moveTo(this.position.x, this.position.y);
ctx.lineTo(m.pos.x, m.pos.y); ctx.lineTo(m.pos.x, m.pos.y);

View File

@@ -635,7 +635,7 @@ const m = {
} }
if (tech.isEnergyHealth) { if (tech.isEnergyHealth) {
m.energy -= dmg * 1.15; m.energy -= dmg * 1.1;
if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage
if (tech.isDeathAvoid && powerUps.research.count && !tech.isDeathAvoidedThisLevel) { if (tech.isDeathAvoid && powerUps.research.count && !tech.isDeathAvoidedThisLevel) {
tech.isDeathAvoidedThisLevel = true tech.isDeathAvoidedThisLevel = true
@@ -2443,7 +2443,9 @@ const m = {
const unit = Vector.mult(Vector.normalise(sub), body[i].mass * tech.pilotForce * Vector.magnitude(sub)) const unit = Vector.mult(Vector.normalise(sub), body[i].mass * tech.pilotForce * Vector.magnitude(sub))
body[i].force.x += unit.x body[i].force.x += unit.x
body[i].force.y += unit.y - body[i].mass * simulation.g //remove gravity effects body[i].force.y += unit.y - body[i].mass * simulation.g //remove gravity effects
if (body[i].collisionFilter.category !== cat.bullet) body[i].collisionFilter.category = cat.bullet; // if (body[i].collisionFilter.category !== cat.bullet) {
// body[i].collisionFilter.category = cat.bullet;
// }
} else { } else {
m.fieldCDcycle = m.cycle + 120; m.fieldCDcycle = m.cycle + 120;
m.fieldOn = false m.fieldOn = false
@@ -2602,7 +2604,7 @@ const m = {
Matter.World.remove(engine.world, body[i]); Matter.World.remove(engine.world, body[i]);
body.splice(i, 1); body.splice(i, 1);
m.fieldRange *= 0.8 m.fieldRange *= 0.8
if (tech.isWormholeEnergy && m.immuneCycle < m.cycle) m.energy += 0.63 if (tech.isWormholeEnergy) m.energy += 0.63
if (tech.isWormSpores) { //pandimensionalspermia if (tech.isWormSpores) { //pandimensionalspermia
for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) { for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) {
if (tech.isSporeWorm) { if (tech.isSporeWorm) {

View File

@@ -676,7 +676,7 @@ const powerUps = {
onPickUp(who) { onPickUp(who) {
powerUps.research.currentRerollCount = 0 powerUps.research.currentRerollCount = 0
if (tech.isTechDamage && who.name === "tech") m.damage(0.11) if (tech.isTechDamage && who.name === "tech") m.damage(0.11)
if (tech.isMassEnergy && m.immuneCycle < m.cycle) m.energy += 2; if (tech.isMassEnergy) m.energy += 2;
if (tech.isMineDrop) { if (tech.isMineDrop) {
if (tech.isLaserMine) { if (tech.isLaserMine) {
b.laserMine(who.position) b.laserMine(who.position)

View File

@@ -696,7 +696,7 @@ const simulation = {
if (tech.isMutualism && !tech.isEnergyHealth) { if (tech.isMutualism && !tech.isEnergyHealth) {
for (let i = 0; i < bullet.length; i++) { for (let i = 0; i < bullet.length; i++) {
if (bullet[i].isMutualismActive) { if (bullet[i].isMutualismActive) {
m.health += 0.005 m.health += 0.005 + 0.005 * tech.isSporeWorm
if (m.health > m.maxHealth) m.health = m.maxHealth; if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth(); m.displayHealth();
} }

View File

@@ -188,7 +188,7 @@ const spawn = {
if (m.immuneCycle < m.cycle && Vector.magnitude(Vector.sub(player.position, this.position)) < this.radius) { if (m.immuneCycle < m.cycle && Vector.magnitude(Vector.sub(player.position, this.position)) < this.radius) {
const DRAIN = tech.isRadioactiveResistance ? 0.07 * 0.25 : 0.07 const DRAIN = tech.isRadioactiveResistance ? 0.07 * 0.25 : 0.07
if (m.energy > DRAIN) { if (m.energy > DRAIN) {
m.energy -= DRAIN if (m.immuneCycle < m.cycle) m.energy -= DRAIN
} else { } else {
m.energy = 0; m.energy = 0;
m.damage((tech.isRadioactiveResistance ? 0.007 * 0.25 : 0.007) * simulation.dmgScale) m.damage((tech.isRadioactiveResistance ? 0.007 * 0.25 : 0.007) * simulation.dmgScale)
@@ -504,9 +504,9 @@ const spawn = {
ctx.fill(); ctx.fill();
//when player is inside event horizon //when player is inside event horizon
if (Vector.magnitude(Vector.sub(this.position, player.position)) < eventHorizon) { if (Vector.magnitude(Vector.sub(this.position, player.position)) < eventHorizon) {
if (m.energy > 0) m.energy -= 0.01 if (m.immuneCycle < m.cycle) {
if (m.energy < 0.15 && m.immuneCycle < m.cycle) { if (m.energy > 0) m.energy -= 0.01
m.damage(0.0004 * simulation.dmgScale); if (m.energy < 0.15 && m.immuneCycle < m.cycle) m.damage(0.0004 * simulation.dmgScale);
} }
const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x); const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x);
player.force.x -= 0.0017 * Math.cos(angle) * player.mass * (m.onGround ? 1.7 : 1); player.force.x -= 0.0017 * Math.cos(angle) * player.mass * (m.onGround ? 1.7 : 1);
@@ -704,7 +704,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
// console.log(`mass=${me.mass}, radius = ${radius}`) // console.log(`mass=${me.mass}, radius = ${radius}`)
me.accelMag = 0.0002 me.accelMag = 0.0002
me.repulsionRange = 100000; //squared me.repulsionRange = 100000 + radius * radius; //squared
// me.memory = 120; // me.memory = 120;
me.seeAtDistance2 = 2000000 //1400 vision range me.seeAtDistance2 = 2000000 //1400 vision range
Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback
@@ -1338,9 +1338,9 @@ const spawn = {
//when player is inside event horizon //when player is inside event horizon
if (Vector.magnitude(Vector.sub(this.position, player.position)) < eventHorizon) { if (Vector.magnitude(Vector.sub(this.position, player.position)) < eventHorizon) {
if (m.energy > 0) m.energy -= 0.004 if (m.immuneCycle < m.cycle) {
if (m.energy < 0.1 && m.immuneCycle < m.cycle) { if (m.energy > 0) m.energy -= 0.004
m.damage(0.00015 * simulation.dmgScale); if (m.energy < 0.1) m.damage(0.00015 * simulation.dmgScale);
} }
const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x); const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x);
player.force.x -= 0.00125 * player.mass * Math.cos(angle) * (m.onGround ? 1.8 : 1); player.force.x -= 0.00125 * player.mass * Math.cos(angle) * (m.onGround ? 1.8 : 1);
@@ -1447,9 +1447,9 @@ const spawn = {
ctx.fill(); ctx.fill();
//when player is inside event horizon //when player is inside event horizon
if (Vector.magnitude(Vector.sub(this.position, player.position)) < eventHorizon) { if (Vector.magnitude(Vector.sub(this.position, player.position)) < eventHorizon) {
if (m.energy > 0) m.energy -= 0.006 if (m.immuneCycle < m.cycle) {
if (m.energy < 0.1 && m.immuneCycle < m.cycle) { if (m.energy > 0) m.energy -= 0.006
m.damage(0.0002 * simulation.dmgScale); if (m.energy < 0.1) m.damage(0.0002 * simulation.dmgScale);
} }
const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x); const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x);
player.force.x -= 0.0013 * Math.cos(angle) * player.mass * (m.onGround ? 1.7 : 1); player.force.x -= 0.0013 * Math.cos(angle) * player.mass * (m.onGround ? 1.7 : 1);
@@ -1703,10 +1703,12 @@ const spawn = {
ctx.setLineDash([125 * Math.random(), 125 * Math.random()]); //the dashed effect is not set back to normal, because it looks neat for how the player is drawn ctx.setLineDash([125 * Math.random(), 125 * Math.random()]); //the dashed effect is not set back to normal, because it looks neat for how the player is drawn
// ctx.lineDashOffset = 6*(simulation.cycle % 215); // ctx.lineDashOffset = 6*(simulation.cycle % 215);
if (this.distanceToPlayer() < this.laserRange) { if (this.distanceToPlayer() < this.laserRange) {
if (m.energy > 0.002) { if (m.immuneCycle < m.cycle) {
m.energy -= 0.0035 if (m.energy > 0.002) {
} else if (m.immuneCycle < m.cycle) { m.energy -= 0.0035
m.damage(0.0003 * simulation.dmgScale) } else {
m.damage(0.0003 * simulation.dmgScale)
}
} }
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(eye.x, eye.y); ctx.moveTo(eye.x, eye.y);
@@ -3551,7 +3553,8 @@ const spawn = {
}; };
}, },
snakeBoss(x, y, radius = 75) { //snake boss with a laser head snakeBoss(x, y, radius = 75) { //snake boss with a laser head
mobs.spawn(x, y, 8, radius, "rgb(55,170,170)"); const color1 = "#f27"
mobs.spawn(x, y, 8, radius, color1); //"rgb(55,170,170)"
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25; me.damageReduction = 0.25;
@@ -3579,6 +3582,14 @@ const spawn = {
//snake tail //snake tail
const nodes = Math.min(8 + Math.ceil(0.5 * simulation.difficulty), 40) const nodes = Math.min(8 + Math.ceil(0.5 * simulation.difficulty), 40)
spawn.lineGroup(x + 105, y, "snakeBody", nodes); spawn.lineGroup(x + 105, y, "snakeBody", nodes);
for (let i = mob.length - 1, len = i - nodes; i > len; i--) { //set alternating colors
if (i % 2) {
mob[i].fill = "#333"
} else {
mob[i].fill = color1
}
}
//constraint with first 3 mobs in line //constraint with first 3 mobs in line
consBB[consBB.length] = Constraint.create({ consBB[consBB.length] = Constraint.create({
bodyA: mob[mob.length - nodes], bodyA: mob[mob.length - nodes],
@@ -3598,7 +3609,7 @@ const spawn = {
stiffness: 0.05 stiffness: 0.05
}); });
World.add(engine.world, consBB[consBB.length - 1]); World.add(engine.world, consBB[consBB.length - 1]);
spawn.shield(me, x, y, 1); // spawn.shield(me, x, y, 1);
}, },
snakeBody(x, y, radius = 10) { snakeBody(x, y, radius = 10) {
mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)"); mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)");
@@ -3610,6 +3621,8 @@ const spawn = {
me.collisionFilter.mask = cat.bullet | cat.player | cat.mob //| cat.body me.collisionFilter.mask = cat.bullet | cat.player | cat.mob //| cat.body
me.accelMag = 0.0004 * simulation.accelScale; me.accelMag = 0.0004 * simulation.accelScale;
me.leaveBody = false; me.leaveBody = false;
me.showHealthBar = false;
// Matter.Body.setDensity(me, 0.00004); //normal is 0.001
me.frictionAir = 0.02; me.frictionAir = 0.02;
me.isSnakeTail = true; me.isSnakeTail = true;
me.stroke = "transparent" me.stroke = "transparent"

View File

@@ -682,7 +682,7 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" || tech.haveGunCheck("spores") || tech.haveGunCheck("drones") || tech.haveGunCheck("missiles") || tech.haveGunCheck("foam") || tech.haveGunCheck("wave beam") || tech.isNeutronBomb || tech.isIceField || tech.relayIce || tech.blockingIce > 1 return m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" || tech.haveGunCheck("spores") || tech.haveGunCheck("drones") || tech.haveGunCheck("missiles") || tech.haveGunCheck("foam") || tech.haveGunCheck("wave beam") || tech.isNeutronBomb || tech.isIceField || tech.isIceShot || tech.relayIce || tech.blockingIce > 1
}, },
requires: "drones, spores, missiles, foam, wave beam, neutron bomb, ice IX", requires: "drones, spores, missiles, foam, wave beam, neutron bomb, ice IX",
effect() { effect() {
@@ -865,9 +865,9 @@
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return ((m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isDroneRadioactive) || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot return ((m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isDroneRadioactive) || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot
}, },
requires: "super balls, shotgun, drones, not irradiated drones", requires: "super balls, basic or slug shotgun, drones, not irradiated drones",
effect() { effect() {
tech.isIncendiary = true tech.isIncendiary = true
}, },
@@ -1812,7 +1812,7 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return (tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField || tech.relayIce || tech.blockingIce > 1) && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.nailsDeathMob return (tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField || tech.isIceShot || tech.relayIce || tech.blockingIce > 1) && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.nailsDeathMob
}, },
requires: "a localized freeze effect, no other mob death tech", requires: "a localized freeze effect, no other mob death tech",
effect() { effect() {
@@ -1830,7 +1830,7 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.isIceField || tech.relayIce || tech.blockingIce || tech.iceIXOnDeath return tech.isIceField || tech.relayIce || tech.blockingIce || tech.iceIXOnDeath || tech.isIceShot
}, },
requires: "ice IX", requires: "ice IX",
effect() { effect() {
@@ -1848,7 +1848,7 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField || tech.relayIce || tech.blockingIce > 1 || tech.iceIXOnDeath return tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField || tech.relayIce || tech.blockingIce > 1 || tech.iceIXOnDeath || tech.isIceShot
}, },
requires: "a localized freeze effect", requires: "a localized freeze effect",
effect() { effect() {
@@ -1866,7 +1866,7 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.isStunField || tech.isExplosionStun || tech.oneSuperBall || tech.isHarmFreeze || tech.isIceField || tech.relayIce || tech.isIceCrystals || tech.isSporeFreeze || tech.isAoESlow || tech.isFreezeMobs || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isWormholeDamage || tech.blockingIce > 1 || tech.iceIXOnDeath return tech.isStunField || tech.isExplosionStun || tech.oneSuperBall || tech.isHarmFreeze || tech.isIceField || tech.relayIce || tech.isIceCrystals || tech.isSporeFreeze || tech.isAoESlow || tech.isFreezeMobs || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isWormholeDamage || tech.blockingIce > 1 || tech.iceIXOnDeath || tech.isIceShot
}, },
requires: "a freezing or stunning effect", requires: "a freezing or stunning effect",
effect() { effect() {
@@ -3461,9 +3461,9 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.isNeedles && !tech.isNailRadiation return (tech.isNeedles || tech.isNeedleShot) && !tech.isNailRadiation
}, },
requires: "needle gun, not irradiated nails", requires: "needle gun, needle-shot, not irradiated nails",
effect() { effect() {
tech.isNeedleShieldPierce = true tech.isNeedleShieldPierce = true
}, },
@@ -3729,44 +3729,6 @@
} }
} }
}, },
{
name: "nailshot",
description: "the <strong>shotgun</strong> fires a burst of <strong>nails</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isSlugShot
},
requires: "shotgun, not slug, incendiary",
effect() {
tech.isNailShot = true;
},
remove() {
tech.isNailShot = false;
}
},
{
name: "shotgun slug",
description: "the <strong>shotgun</strong> fires 1 large <strong>bullet</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("shotgun") && !tech.isNailShot
},
requires: "shotgun, not nailshot",
effect() {
tech.isSlugShot = true;
},
remove() {
tech.isSlugShot = false;
}
},
{ {
name: "Newton's 3rd law", name: "Newton's 3rd law",
description: "<strong>shotgun</strong> <strong>recoil</strong> is increased<br>decrease <strong>shotgun</strong> <strong><em>delay</em></strong> after firing by <strong>66%</strong>", description: "<strong>shotgun</strong> <strong>recoil</strong> is increased<br>decrease <strong>shotgun</strong> <strong><em>delay</em></strong> after firing by <strong>66%</strong>",
@@ -3805,6 +3767,120 @@
tech.isShotgunReversed = false; tech.isShotgunReversed = false;
} }
}, },
{
name: "shotgun slug",
description: "the <strong>shotgun</strong> fires a huge dense <strong>bullet</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot
},
requires: "shotgun, not nail-shot, foam-shot, worm-shot, ice-shot",
effect() {
tech.isSlugShot = true;
},
remove() {
tech.isSlugShot = false;
}
},
{
name: "nail-shot",
description: "the <strong>shotgun</strong> fires a burst of <strong>nails</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isSlugShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot
},
requires: "shotgun, not incendiary, slug, foam-shot, worm-shot, ice-shot",
effect() {
tech.isNailShot = true;
},
remove() {
tech.isNailShot = false;
}
},
{
name: "worm-shot",
description: "the <strong>shotgun</strong> fires <strong>3-4</strong> <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong>", //<br><strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> seek out nearby mobs
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isSlugShot && !tech.isIceShot && !tech.isFoamShot && !tech.isNeedleShot
},
requires: "shotgun, not incendiary, nail-shot, slug, foam-shot, ice-shot",
effect() {
tech.isWormShot = true;
},
remove() {
tech.isWormShot = false;
}
},
{
name: "foam-shot",
description: "the <strong>shotgun</strong> fires <strong>14</strong> <strong>foam</strong> bubbles",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isSlugShot && !tech.isIceShot && !tech.isWormShot && !tech.isNeedleShot
},
requires: "shotgun, not incendiary, nail-shot, slug, worm-shot, ice-shot",
effect() {
tech.isFoamShot = true;
},
remove() {
tech.isFoamShot = false;
}
},
{
name: "ice-shot",
description: "the <strong>shotgun</strong> fires <strong>16</strong> <strong class='color-s'>ice IX</strong> crystals",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isSlugShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot
},
requires: "shotgun, not incendiary, nail-shot, slug, foam-shot, worm-shot",
effect() {
tech.isIceShot = true;
},
remove() {
tech.isIceShot = false;
}
},
{
name: "needle-shot",
description: "the <strong>shotgun</strong> fires <strong>12</strong> mob piercing <strong>needles</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isSlugShot && !tech.isFoamShot && !tech.isWormShot && !tech.isIceShot
},
requires: "shotgun, not incendiary, nail-shot, slug, foam-shot, worm-shot, ice-shot",
effect() {
tech.isNeedleShot = true;
},
remove() {
tech.isNeedleShot = false;
}
},
{ {
name: "super duper", name: "super duper",
description: "fire <strong>1</strong> additional <strong>super ball</strong>", description: "fire <strong>1</strong> additional <strong>super ball</strong>",
@@ -4318,9 +4394,9 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isWormShot
}, },
requires: "spores", requires: "spores or worms",
effect() { effect() {
tech.isSporeFreeze = true tech.isSporeFreeze = true
}, },
@@ -4337,9 +4413,9 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isWormShot
}, },
requires: "spores", requires: "spores or worms",
effect() { effect() {
tech.isSporeFollow = true tech.isSporeFollow = true
}, },
@@ -4347,6 +4423,25 @@
tech.isSporeFollow = false tech.isSporeFollow = false
} }
}, },
{
name: "mutualism",
description: "increase <strong class='color-p' style='letter-spacing: 2px;'>spore</strong> <strong class='color-d'>damage</strong> by <strong>150%</strong><br><strong class='color-p' style='letter-spacing: 2px;'>spores</strong> borrow <strong>0.5</strong> <strong class='color-h'>health</strong> until they <strong>die</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return (tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField) && !tech.isEnergyHealth || tech.isWormShot
},
requires: "spores, worms, not mass-energy",
effect() {
tech.isMutualism = true
},
remove() {
tech.isMutualism = false
}
},
{ {
name: "nematodes", name: "nematodes",
description: "<strong class='color-p' style='letter-spacing: 2px;'>spores</strong> develop into <strong>1/2</strong> as many <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong><br><strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> do <strong>200%</strong> more <strong class='color-d'>damage</strong>", description: "<strong class='color-p' style='letter-spacing: 2px;'>spores</strong> develop into <strong>1/2</strong> as many <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong><br><strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> do <strong>200%</strong> more <strong class='color-d'>damage</strong>",
@@ -4366,25 +4461,6 @@
tech.isSporeWorm = false tech.isSporeWorm = false
} }
}, },
{
name: "mutualism",
description: "increase <strong class='color-p' style='letter-spacing: 2px;'>spore</strong> <strong class='color-d'>damage</strong> by <strong>150%</strong><br><strong class='color-p' style='letter-spacing: 2px;'>spores</strong> borrow <strong>0.5</strong> <strong class='color-h'>health</strong> until they <strong>die</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return (tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField) && !tech.isEnergyHealth
},
requires: "spores, not mass-energy",
effect() {
tech.isMutualism = true
},
remove() {
tech.isMutualism = false
}
},
{ {
name: "reduced tolerances", name: "reduced tolerances",
description: "increase <strong>drone</strong> <strong class='color-g'>ammo</strong>/<strong class='color-f'>efficiency</strong> by <strong>66%</strong><br>reduce the average <strong>drone</strong> lifetime by <strong>40%</strong>", description: "increase <strong>drone</strong> <strong class='color-g'>ammo</strong>/<strong class='color-f'>efficiency</strong> by <strong>66%</strong><br>reduce the average <strong>drone</strong> lifetime by <strong>40%</strong>",
@@ -4543,6 +4619,25 @@
tech.droneRadioDamage = 1 tech.droneRadioDamage = 1
} }
}, },
{
name: "electrostatic induction",
description: "<strong>foam</strong> bubbles are electrically charged<br>causing <strong>attraction</strong> to nearby <strong>mobs</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return !tech.isFoamTeleport && (tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot)
},
requires: "foam, not uncertainty",
effect() {
tech.isFoamAttract = true
},
remove() {
tech.isFoamAttract = false
}
},
{ {
name: "uncertainty principle", name: "uncertainty principle",
description: "<strong>foam</strong> bubbles randomly change <strong>position</strong><br>increase <strong>foam</strong> <strong class='color-d'>damage</strong> per second by <strong>66%</strong>", description: "<strong>foam</strong> bubbles randomly change <strong>position</strong><br>increase <strong>foam</strong> <strong class='color-d'>damage</strong> per second by <strong>66%</strong>",
@@ -4552,7 +4647,7 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return !tech.isFoamAttract && (tech.haveGunCheck("foam") || tech.foamBotCount > 1) return !tech.isFoamAttract && (tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot)
}, },
requires: "foam, not electrostatic induction", requires: "foam, not electrostatic induction",
effect() { effect() {
@@ -4571,7 +4666,7 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("foam") || tech.foamBotCount > 1 return tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot
}, },
requires: "foam", requires: "foam",
effect() { effect() {
@@ -4590,7 +4685,7 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("foam") || tech.foamBotCount > 1 return tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot
}, },
requires: "foam", requires: "foam",
effect() { effect() {
@@ -4640,25 +4735,6 @@
tech.isAmmoFoamSize = false; tech.isAmmoFoamSize = false;
} }
}, },
{
name: "electrostatic induction",
description: "<strong>foam</strong> bubbles are electrically charged<br>causing <strong>attraction</strong> to nearby <strong>mobs</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return !tech.isFoamTeleport && (tech.haveGunCheck("foam") || tech.foamBotCount > 1)
},
requires: "foam, not uncertainty",
effect() {
tech.isFoamAttract = true
},
remove() {
tech.isFoamAttract = false
}
},
{ {
name: "half-wave rectifier", name: "half-wave rectifier",
description: "charging the <strong>rail gun</strong> gives you <strong class='color-f'>energy</strong><br><em>instead of draining it</em>", description: "charging the <strong>rail gun</strong> gives you <strong class='color-f'>energy</strong><br><em>instead of draining it</em>",
@@ -7553,6 +7629,10 @@
isFieldHarmReduction: null, isFieldHarmReduction: null,
isFastTime: null, isFastTime: null,
isDroneTeleport: null, isDroneTeleport: null,
isAnthropicTech: null,
isSporeWorm: null, isSporeWorm: null,
isAnthropicTech: null isWormShot: null,
isFoamShot: null,
isIceShot: null,
isNeedleShot: null
} }

View File

@@ -1,25 +1,31 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** NEXT PATCH ********************************************************
tech: weak anthropic principle - after anthropic principle prevents your death, gain 50% duplication for that level
anthropic principle now correctly gives 6 seconds of harm immunity after preventing your death
almost all energy regen is disabled while immune to harm shotgun techs:
you aren't immune very often so you may not notice, but it will limit some builds that let you get almost constant immunity (I haven't done enough testing so let me know if these different shotgun modes aren't balanced)
Pauli exclusion gives 1 s of harm immunity (was .75 s) worm shot
CPT reversal requires 10% less energy (min energy is 60% to activate) ice-IX shot
CPT grenades gives many more bombs foam shot
CPT bots gives many more bots needle shot
growBoss balance: a bit smaller and slower, and a extra high chance to drop a random power up when you kill one foam lasts much longer on shielded mobs
sneaker mobs are a bit slower, and have much lower health overall foam damage is reduced about 8%
starter mobs are no longer aggressive
gun tech will now only show up for your active gun attacks that drain energy don't work when the player is immune to harm
set CSS max width of the update element to match other elements slime, radiation fields, black holes
energy regen that consumes something (ammo, blocks, power ups) now works when immune to harm
but passive energy regen is still stopped while you are immune to harm
pilot wave field can no longer hit intangible mobs with blocks
it was too annoying that you can't use blocks to move around so I reverted it back
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
snake boss tail should shrink in size
CPT reversal should drain less energy? mob that grows or gets a shield when player is near
and charges when player is near
charge triggers an escape mode
mob wonders and drops eggs that hatch into seekers if no player around
pink seeker boss is cool as heck, make an alt version of it pink seeker boss is cool as heck, make an alt version of it