radioisotope generator
tech - radioisotope generator - drones have the effect of neutron bomb, but you get less ammo bug fix - reduced tolerances now properly gives extra ammo water shielding now protects you from all radioactivity, but only gives 75% protection (drones, neutron bomb, radioactive explosions, and even slime) final boss has more durability in it's final phase final boss no longers gets knocked around as much from explosions level.warehouse predraw lighting for performance bug fix on sewers where slime was doing too much harm
This commit is contained in:
299
js/bullet.js
299
js/bullet.js
@@ -326,11 +326,12 @@ const b = {
|
||||
|
||||
//player damage
|
||||
if (Vector.magnitude(Vector.sub(where, player.position)) < radius) {
|
||||
const drain = (tech.isExplosionHarm ? 0.5 : 0.25) * (tech.isImmuneExplosion ? Math.min(1, Math.max(1 - m.energy * 0.7, 0)) : 1)
|
||||
m.energy -= drain
|
||||
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)
|
||||
m.energy -= DRAIN
|
||||
if (m.energy < 0) {
|
||||
m.energy = 0
|
||||
m.damage(0.03);
|
||||
m.damage(0.03 * (tech.isRadioactiveResistance ? 0.25 : 1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -922,11 +923,10 @@ const b = {
|
||||
bullet[me].restitution = 0;
|
||||
bullet[me].minDmgSpeed = 0;
|
||||
bullet[me].damageRadius = 100;
|
||||
bullet[me].maxDamageRadius = 450 + 130 * tech.isNeutronSlow + 130 * tech.isNeutronImmune //+ 150 * Math.random()
|
||||
bullet[me].radiusDecay = (0.81 + 0.15 * tech.isNeutronSlow + 0.15 * tech.isNeutronImmune) / tech.isBulletsLastLonger
|
||||
bullet[me].maxDamageRadius = 450 + 130 * tech.isNeutronSlow //+ 150 * Math.random()
|
||||
bullet[me].radiusDecay = (0.81 + 0.15 * tech.isNeutronSlow) / tech.isBulletsLastLonger
|
||||
bullet[me].stuckTo = null;
|
||||
bullet[me].stuckToRelativePosition = null;
|
||||
bullet[me].vacuumSlow = 0.97;
|
||||
|
||||
if (tech.isRPG) {
|
||||
const SCALE = 2
|
||||
@@ -1030,27 +1030,27 @@ const b = {
|
||||
this.endCycle = 0;
|
||||
} else {
|
||||
//aoe damage to player
|
||||
if (!tech.isNeutronImmune && Vector.magnitude(Vector.sub(player.position, this.position)) < this.damageRadius) {
|
||||
const DRAIN = 0.0023
|
||||
if (Vector.magnitude(Vector.sub(player.position, this.position)) < this.damageRadius) {
|
||||
const DRAIN = tech.isRadioactiveResistance ? 0.0025 * 0.25 : 0.0025
|
||||
if (m.energy > DRAIN) {
|
||||
m.energy -= DRAIN
|
||||
} else {
|
||||
m.energy = 0;
|
||||
m.damage(0.00015)
|
||||
m.damage(tech.isRadioactiveResistance ? 0.00016 * 0.25 : 0.00016) //0.00015
|
||||
}
|
||||
}
|
||||
//aoe damage to mobs
|
||||
for (let i = 0, len = mob.length; i < len; i++) {
|
||||
if (Vector.magnitude(Vector.sub(mob[i].position, this.position)) < this.damageRadius) {
|
||||
let dmg = b.dmgScale * 0.082
|
||||
let dmg = b.dmgScale * 0.09
|
||||
if (Matter.Query.ray(map, mob[i].position, this.position).length > 0) dmg *= 0.25 //reduce damage if a wall is in the way
|
||||
if (mob[i].shield) dmg *= 4 //x5 to make up for the /5 that shields normally take
|
||||
mob[i].damage(dmg);
|
||||
mob[i].locatePlayer();
|
||||
if (tech.isNeutronSlow) {
|
||||
Matter.Body.setVelocity(mob[i], {
|
||||
x: mob[i].velocity.x * this.vacuumSlow,
|
||||
y: mob[i].velocity.y * this.vacuumSlow
|
||||
x: mob[i].velocity.x * 0.97,
|
||||
y: mob[i].velocity.y * 0.97
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1062,22 +1062,21 @@ const b = {
|
||||
ctx.fill();
|
||||
ctx.globalCompositeOperation = "source-over"
|
||||
if (tech.isNeutronSlow) {
|
||||
const that = this
|
||||
|
||||
function slow(who, radius = that.explodeRad * 3.2) {
|
||||
let slow = (who, radius = this.explodeRad * 3.2) => {
|
||||
for (i = 0, len = who.length; i < len; i++) {
|
||||
const sub = Vector.sub(that.position, who[i].position);
|
||||
const sub = Vector.sub(this.position, who[i].position);
|
||||
const dist = Vector.magnitude(sub);
|
||||
if (dist < radius) {
|
||||
Matter.Body.setVelocity(who[i], {
|
||||
x: who[i].velocity.x * that.vacuumSlow,
|
||||
y: who[i].velocity.y * that.vacuumSlow
|
||||
x: who[i].velocity.x * 0.975,
|
||||
y: who[i].velocity.y * 0.975
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
slow(body, this.damageRadius)
|
||||
if (!tech.isNeutronImmune) slow([player], this.damageRadius)
|
||||
slow([player], this.damageRadius)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2210,6 +2209,242 @@ const b = {
|
||||
y: speed * Math.sin(dir)
|
||||
});
|
||||
},
|
||||
droneRadioactive(where = { x: m.pos.x + 30 * Math.cos(m.angle) + 20 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 20 * (Math.random() - 0.5) }, speed = 1) {
|
||||
const me = bullet.length;
|
||||
const THRUST = tech.isFastDrones ? 0.002 : 0.0012
|
||||
const dir = m.angle + 0.4 * (Math.random() - 0.5);
|
||||
const RADIUS = (4 + 1 * Math.random())
|
||||
bullet[me] = Bodies.polygon(where.x, where.y, 8, RADIUS, {
|
||||
angle: dir,
|
||||
inertia: Infinity,
|
||||
friction: 0.05,
|
||||
frictionAir: 0,
|
||||
restitution: 1,
|
||||
dmg: 0.24, //damage done in addition to the damage from momentum
|
||||
lookFrequency: 120 + Math.floor(23 * Math.random()),
|
||||
endCycle: simulation.cycle + Math.floor((900 + 400 * Math.random()) * tech.isBulletsLastLonger) + 140 + RADIUS * 5,
|
||||
classType: "bullet",
|
||||
collisionFilter: {
|
||||
category: cat.bullet,
|
||||
mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield //self collide
|
||||
},
|
||||
minDmgSpeed: 0,
|
||||
lockedOn: null,
|
||||
isFollowMouse: true,
|
||||
deathCycles: 110 + RADIUS * 5,
|
||||
isImproved: false,
|
||||
radioRadius: 0,
|
||||
maxRadioRadius: 400 + Math.floor(75 * Math.random()) + 80 * tech.isNeutronSlow,
|
||||
beforeDmg(who) {
|
||||
const unit = Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), -20) //move away from target after hitting
|
||||
Matter.Body.setVelocity(this, {
|
||||
x: unit.x,
|
||||
y: unit.y
|
||||
});
|
||||
this.lockedOn = null
|
||||
if (this.endCycle > simulation.cycle + this.deathCycles) {
|
||||
this.endCycle -= 60
|
||||
if (simulation.cycle + this.deathCycles > this.endCycle) this.endCycle = simulation.cycle + this.deathCycles
|
||||
}
|
||||
},
|
||||
onEnd() {
|
||||
if (tech.isDroneRespawn) {
|
||||
const who = b.guns[b.activeGun]
|
||||
if (who.name === "drones" && who.ammo > 0 && mob.length) {
|
||||
b.droneRadioactive({ x: this.position.x, y: this.position.y }, 0)
|
||||
if (Math.random() < 0.33) {
|
||||
b.guns[b.activeGun].ammo--;
|
||||
simulation.updateGunHUD();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
do() {
|
||||
//radioactive zone
|
||||
this.radioRadius = this.radioRadius * 0.993 + 0.007 * this.maxRadioRadius //smooth radius towards max
|
||||
//aoe damage to player
|
||||
if (Vector.magnitude(Vector.sub(player.position, this.position)) < this.radioRadius) {
|
||||
const DRAIN = tech.isRadioactiveResistance ? 0.0023 * 0.25 : 0.0023
|
||||
if (m.energy > DRAIN) {
|
||||
m.energy -= DRAIN
|
||||
} else {
|
||||
m.energy = 0;
|
||||
m.damage(tech.isRadioactiveResistance ? 0.00015 * 0.25 : 0.00015) //0.00015
|
||||
}
|
||||
}
|
||||
//aoe damage to mobs
|
||||
for (let i = 0, len = mob.length; i < len; i++) {
|
||||
if (Vector.magnitude(Vector.sub(mob[i].position, this.position)) < this.radioRadius) {
|
||||
let dmg = b.dmgScale * 0.035 //neutron bombs dmg = 0.09
|
||||
if (Matter.Query.ray(map, mob[i].position, this.position).length > 0) dmg *= 0.25 //reduce damage if a wall is in the way
|
||||
if (mob[i].shield) dmg *= 4 //x5 to make up for the /5 that shields normally take
|
||||
mob[i].damage(dmg);
|
||||
mob[i].locatePlayer();
|
||||
if (tech.isNeutronSlow) {
|
||||
Matter.Body.setVelocity(mob[i], {
|
||||
x: mob[i].velocity.x * 0.97,
|
||||
y: mob[i].velocity.y * 0.97
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
//draw
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.position.x, this.position.y, this.radioRadius, 0, 2 * Math.PI);
|
||||
ctx.globalCompositeOperation = "lighter"
|
||||
ctx.fillStyle = `rgba(25,139,170,${0.1+0.05*Math.random()})`;
|
||||
ctx.fill();
|
||||
ctx.globalCompositeOperation = "source-over"
|
||||
|
||||
if (tech.isNeutronSlow) {
|
||||
const slow = (who, radius = this.radioRadius * 3.2) => {
|
||||
for (i = 0, len = who.length; i < len; i++) {
|
||||
const sub = Vector.sub(this.position, who[i].position);
|
||||
const dist = Vector.magnitude(sub);
|
||||
if (dist < radius) {
|
||||
Matter.Body.setVelocity(who[i], {
|
||||
x: who[i].velocity.x * 0.975,
|
||||
y: who[i].velocity.y * 0.975
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
slow(body, this.radioRadius)
|
||||
slow([player], this.radioRadius)
|
||||
}
|
||||
|
||||
|
||||
//normal drone actions
|
||||
if (simulation.cycle + this.deathCycles > this.endCycle) { //fall shrink and die
|
||||
this.force.y += this.mass * 0.0012;
|
||||
this.restitution = 0.2;
|
||||
const scale = 0.995;
|
||||
Matter.Body.scale(this, scale, scale);
|
||||
this.maxRadioRadius = 0
|
||||
this.radioRadius = this.radioRadius * 0.98 //let radioactivity decrease
|
||||
} else {
|
||||
this.force.y += this.mass * 0.0002; //gravity
|
||||
|
||||
if (!(simulation.cycle % this.lookFrequency)) {
|
||||
//find mob targets
|
||||
this.lockedOn = null;
|
||||
let closeDist = Infinity;
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (
|
||||
!mob[i].isBadTarget &&
|
||||
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
|
||||
Matter.Query.ray(body, this.position, mob[i].position).length === 0
|
||||
) {
|
||||
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]
|
||||
}
|
||||
}
|
||||
}
|
||||
//power ups
|
||||
if (!this.isImproved && !simulation.isChoosing && !tech.isExtraMaxEnergy) {
|
||||
if (this.lockedOn) {
|
||||
//grab, but don't lock onto nearby power up
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||
if (
|
||||
(powerUp[i].name !== "heal" || m.health < 0.9 * m.maxHealth || tech.isDroneGrab) &&
|
||||
(powerUp[i].name !== "field" || !tech.isDeterminism) &&
|
||||
Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000
|
||||
) {
|
||||
//draw pickup for a single cycle
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(this.position.x, this.position.y);
|
||||
ctx.lineTo(powerUp[i].position.x, powerUp[i].position.y);
|
||||
ctx.strokeStyle = "#000"
|
||||
ctx.lineWidth = 4
|
||||
ctx.stroke();
|
||||
//pick up nearby power ups
|
||||
powerUps.onPickUp(powerUp[i]);
|
||||
powerUp[i].effect();
|
||||
Matter.World.remove(engine.world, powerUp[i]);
|
||||
powerUp.splice(i, 1);
|
||||
if (tech.isDroneGrab) {
|
||||
this.isImproved = true;
|
||||
const SCALE = 2.25
|
||||
Matter.Body.scale(this, SCALE, SCALE);
|
||||
this.lookFrequency = 30 + Math.floor(11 * Math.random());
|
||||
this.endCycle += 1000 * tech.isBulletsLastLonger
|
||||
this.maxRadioRadius *= 1.25
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//look for power ups to lock onto
|
||||
let closeDist = Infinity;
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||
if (
|
||||
(powerUp[i].name !== "heal" || m.health < 0.9 * m.maxHealth || tech.isDroneGrab) &&
|
||||
(powerUp[i].name !== "field" || !tech.isDeterminism)
|
||||
) {
|
||||
if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) {
|
||||
//draw pickup for a single cycle
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(this.position.x, this.position.y);
|
||||
ctx.lineTo(powerUp[i].position.x, powerUp[i].position.y);
|
||||
ctx.strokeStyle = "#000"
|
||||
ctx.lineWidth = 4
|
||||
ctx.stroke();
|
||||
//pick up nearby power ups
|
||||
powerUps.onPickUp(powerUp[i]);
|
||||
powerUp[i].effect();
|
||||
Matter.World.remove(engine.world, powerUp[i]);
|
||||
powerUp.splice(i, 1);
|
||||
if (tech.isDroneGrab) {
|
||||
this.isImproved = true;
|
||||
const SCALE = 2.25
|
||||
Matter.Body.scale(this, SCALE, SCALE);
|
||||
this.lookFrequency = 30 + Math.floor(11 * Math.random());
|
||||
this.endCycle += 1000 * tech.isBulletsLastLonger
|
||||
this.maxRadioRadius *= 1.25
|
||||
}
|
||||
break;
|
||||
}
|
||||
//look for power ups to lock onto
|
||||
if (
|
||||
Matter.Query.ray(map, this.position, powerUp[i].position).length === 0 &&
|
||||
Matter.Query.ray(body, this.position, powerUp[i].position).length === 0
|
||||
) {
|
||||
const TARGET_VECTOR = Vector.sub(this.position, powerUp[i].position)
|
||||
const DIST = Vector.magnitude(TARGET_VECTOR);
|
||||
if (DIST < closeDist) {
|
||||
closeDist = DIST;
|
||||
this.lockedOn = powerUp[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.lockedOn) { //accelerate towards mobs
|
||||
this.force = Vector.mult(Vector.normalise(Vector.sub(this.position, this.lockedOn.position)), -this.mass * THRUST)
|
||||
} else { //accelerate towards mouse
|
||||
this.force = Vector.mult(Vector.normalise(Vector.sub(this.position, simulation.mouseInGame)), -this.mass * THRUST)
|
||||
}
|
||||
// speed cap instead of friction to give more agility
|
||||
if (this.speed > 6) {
|
||||
Matter.Body.setVelocity(this, {
|
||||
x: this.velocity.x * 0.97,
|
||||
y: this.velocity.y * 0.97
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
World.add(engine.world, bullet[me]); //add bullet to world
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: speed * Math.cos(dir),
|
||||
y: speed * Math.sin(dir)
|
||||
});
|
||||
},
|
||||
foam(position, velocity, radius) {
|
||||
// radius *= Math.sqrt(tech.bulletSize)
|
||||
const me = bullet.length;
|
||||
@@ -3323,7 +3558,7 @@ const b = {
|
||||
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
|
||||
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
|
||||
@@ -3356,18 +3591,18 @@ const b = {
|
||||
x: m.Vx / 2 + SPEED * Math.cos(angle),
|
||||
y: m.Vy / 2 + SPEED * Math.sin(angle)
|
||||
});
|
||||
Matter.Body.setDensity(bullet[me], 0.00001);
|
||||
// Matter.Body.setDensity(bullet[me], 0.00001);
|
||||
World.add(engine.world, bullet[me]); //add bullet to world
|
||||
}
|
||||
|
||||
if (m.crouch) {
|
||||
m.fireCDcycle = m.cycle + 50 * b.fireCD; // cool down
|
||||
m.fireCDcycle = m.cycle + 45 * b.fireCD; // cool down
|
||||
makeNeedle()
|
||||
for (let i = 1; i < 4; i++) { //4 total needles
|
||||
setTimeout(() => { if (!simulation.paused) makeNeedle() }, 60 * i);
|
||||
}
|
||||
} else {
|
||||
m.fireCDcycle = m.cycle + 30 * b.fireCD; // cool down
|
||||
m.fireCDcycle = m.cycle + 25 * b.fireCD; // cool down
|
||||
makeNeedle()
|
||||
for (let i = 1; i < 3; i++) { //3 total needles
|
||||
setTimeout(() => { if (!simulation.paused) makeNeedle() }, 60 * i);
|
||||
@@ -4145,12 +4380,22 @@ const b = {
|
||||
have: false,
|
||||
do() {},
|
||||
fire() {
|
||||
if (m.crouch) {
|
||||
b.drone({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 45)
|
||||
m.fireCDcycle = m.cycle + Math.floor(13 * b.fireCD); // cool down
|
||||
if (tech.isDroneRadioactive) {
|
||||
if (m.crouch) {
|
||||
b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 45)
|
||||
m.fireCDcycle = m.cycle + Math.floor(7 * 13 * b.fireCD); // cool down
|
||||
} else {
|
||||
b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 10)
|
||||
m.fireCDcycle = m.cycle + Math.floor(7 * 6 * b.fireCD); // cool down
|
||||
}
|
||||
} else {
|
||||
b.drone()
|
||||
m.fireCDcycle = m.cycle + Math.floor(6 * b.fireCD); // cool down
|
||||
if (m.crouch) {
|
||||
b.drone({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 45)
|
||||
m.fireCDcycle = m.cycle + Math.floor(13 * b.fireCD); // cool down
|
||||
} else {
|
||||
b.drone()
|
||||
m.fireCDcycle = m.cycle + Math.floor(6 * b.fireCD); // cool down
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
133
js/level.js
133
js/level.js
@@ -16,12 +16,15 @@ const level = {
|
||||
// simulation.difficulty = 20
|
||||
// simulation.isHorizontalFlipped = true
|
||||
// level.difficultyIncrease(99)
|
||||
// m.setField("standing wave harmonics")
|
||||
// tech.giveTech("spherical harmonics")
|
||||
// for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics")
|
||||
// m.setField("nano-scale manufacturing")
|
||||
// b.giveGuns("grenades")
|
||||
// tech.giveTech("neutron bomb")
|
||||
// b.giveGuns("drones")
|
||||
// tech.giveTech("radioactive drones")
|
||||
// tech.isRadioactiveResistance = true
|
||||
// for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics")
|
||||
// tech.isExplodeRadio = true
|
||||
// tech.giveTech("chain reaction")
|
||||
// tech.giveTech("vacuum permittivity")
|
||||
// tech.giveTech("quenching")
|
||||
// tech.giveTech("decoherence")
|
||||
// tech.giveTech("supertemporal")
|
||||
@@ -96,7 +99,7 @@ const level = {
|
||||
powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "tech", false);
|
||||
}
|
||||
if (tech.isHealLowHealth) {
|
||||
const len = Math.ceil((m.maxHealth - m.health) / 0.33)
|
||||
const len = Math.ceil((m.maxHealth - m.health) / 0.25)
|
||||
for (let i = 0; i < len; i++) powerUps.spawn(player.position.x + 90 * (Math.random() - 0.5), player.position.y + 90 * (Math.random() - 0.5), "heal", false);
|
||||
}
|
||||
if (tech.isMACHO) spawn.MACHO()
|
||||
@@ -965,23 +968,12 @@ const level = {
|
||||
ctx.fillRect(this.min.x, this.min.y + offset, this.width, this.height - offset)
|
||||
|
||||
if (this.height > 0 && Matter.Query.region([player], this).length) {
|
||||
const drain = 0.003 + m.fieldRegen
|
||||
if (m.energy > drain) {
|
||||
m.energy -= drain
|
||||
const DRAIN = 0.003 * (tech.isRadioactiveResistance ? 0.25 : 1) + m.fieldRegen
|
||||
console.log(DRAIN)
|
||||
if (m.energy > DRAIN) {
|
||||
m.energy -= DRAIN
|
||||
} else {
|
||||
if (damage < 0.02) {
|
||||
m.damage(damage)
|
||||
} else if (m.immuneCycle < m.cycle) {
|
||||
m.immuneCycle = m.cycle + tech.collisionImmuneCycles;
|
||||
m.damage(damage)
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: player.position.x,
|
||||
y: player.position.y,
|
||||
radius: damage * 1500,
|
||||
color: simulation.mobDmgColor,
|
||||
time: 20
|
||||
});
|
||||
}
|
||||
m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1))
|
||||
}
|
||||
//float
|
||||
if (player.velocity.y > 5) player.force.y -= 0.95 * player.mass * simulation.g
|
||||
@@ -1926,7 +1918,7 @@ const level = {
|
||||
const doorWidth2 = 15 + Math.floor(100 * Math.random() * Math.random())
|
||||
spawn.bodyRect(offset.x + 2050 - doorWidth2 / 2, offset.y - 175, doorWidth2, 165); //block door
|
||||
} else {
|
||||
spawn.mapRect(offset.x + 2000, offset.y - 2800, 100, 2800); //right wall
|
||||
spawn.mapRect(offset.x + 2000, offset.y - 2800, 100, 2900); //right wall
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2086,7 +2078,7 @@ const level = {
|
||||
},
|
||||
testing() {
|
||||
// const button = level.button(200, -700)
|
||||
const toggle = level.toggle(200, -700)
|
||||
// const toggle = level.toggle(200, -700)
|
||||
level.custom = () => {
|
||||
// button.draw();
|
||||
ctx.fillStyle = "rgba(0,255,255,0.1)";
|
||||
@@ -2096,7 +2088,7 @@ const level = {
|
||||
level.enter.draw();
|
||||
};
|
||||
level.customTopLayer = () => {
|
||||
toggle.query();
|
||||
// toggle.query();
|
||||
};
|
||||
|
||||
level.setPosToSpawn(0, -750); //normal spawn
|
||||
@@ -2127,11 +2119,9 @@ const level = {
|
||||
function blockDoor(x, y, blockSize = 58) {
|
||||
spawn.mapRect(x, y - 290, 40, 60); // door lip
|
||||
spawn.mapRect(x, y, 40, 50); // door lip
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
spawn.bodyRect(x + 5, y - 260 + i * blockSize, 30, blockSize);
|
||||
}
|
||||
for (let i = 0; i < 4; ++i) spawn.bodyRect(x + 5, y - 260 + i * blockSize, 30, blockSize);
|
||||
}
|
||||
blockDoor(710, -710);
|
||||
// blockDoor(710, -710);
|
||||
// for (let i = 0; i < 30; i++) powerUps.directSpawn(710, -710, "tech");
|
||||
|
||||
spawn.mapRect(2500, -1200, 200, 750); //right wall
|
||||
@@ -2151,10 +2141,10 @@ const level = {
|
||||
// spawn.shooterBoss(1900, -500)
|
||||
// spawn.historyBoss(1200, -500)
|
||||
// spawn.laserTargetingBoss(1600, -400)
|
||||
// spawn.striker(1600, -500)
|
||||
spawn.hopper(1600, -500)
|
||||
// spawn.laserTargetingBoss(1700, -120)
|
||||
// spawn.bomberBoss(1400, -500)
|
||||
// spawn.ghoster(1800, -120)
|
||||
spawn.hopBoss(1800, -120)
|
||||
// spawn.streamBoss(1600, -500)
|
||||
// spawn.orbitalBoss(1600, -500)
|
||||
// spawn.cellBossCulture(1600, -500)
|
||||
@@ -2962,8 +2952,6 @@ const level = {
|
||||
|
||||
button1.query();
|
||||
button1.draw();
|
||||
hazard.query();
|
||||
hazard.level(button1.isUp)
|
||||
rotor.rotate();
|
||||
|
||||
ctx.fillStyle = "hsl(175, 15%, 76%)"
|
||||
@@ -4017,43 +4005,54 @@ const level = {
|
||||
level.enter.draw();
|
||||
};
|
||||
|
||||
|
||||
// simulation.draw.mapPath = new Path2D();
|
||||
// for (let i = 0, len = map.length; i < len; ++i) {
|
||||
// let vertices = map[i].vertices;
|
||||
// simulation.draw.mapPath.moveTo(vertices[0].x, vertices[0].y);
|
||||
// for (let j = 1; j < vertices.length; j += 1) {
|
||||
// simulation.draw.mapPath.lineTo(vertices[j].x, vertices[j].y);
|
||||
// }
|
||||
// simulation.draw.mapPath.lineTo(vertices[0].x, vertices[0].y);
|
||||
// }
|
||||
const lightingPath = new Path2D() //pre-draw the complex lighting path to save processing
|
||||
lightingPath.moveTo(-1800, -500)
|
||||
lightingPath.lineTo(-910, -500) //3rd floor light
|
||||
lightingPath.lineTo(-1300, 0)
|
||||
lightingPath.lineTo(-500, 0)
|
||||
lightingPath.lineTo(-890, -500)
|
||||
lightingPath.lineTo(-175, -500)
|
||||
lightingPath.lineTo(-175, -250)
|
||||
lightingPath.lineTo(175, -250)
|
||||
lightingPath.lineTo(175, 0)
|
||||
lightingPath.lineTo(-910, 100) //2nd floor light left
|
||||
lightingPath.lineTo(-1300, 600)
|
||||
lightingPath.lineTo(-500, 600)
|
||||
lightingPath.lineTo(-890, 100)
|
||||
lightingPath.lineTo(190, 100) //2nd floor light right
|
||||
lightingPath.lineTo(-200, 600)
|
||||
lightingPath.lineTo(600, 600)
|
||||
lightingPath.lineTo(210, 100)
|
||||
lightingPath.lineTo(1100, 100)
|
||||
lightingPath.lineTo(1100, 1400)
|
||||
lightingPath.lineTo(600, 1400) //1st floor light right
|
||||
lightingPath.lineTo(10, 700)
|
||||
lightingPath.lineTo(-10, 700)
|
||||
lightingPath.lineTo(-600, 1400)
|
||||
lightingPath.lineTo(-1950, 1400) //1st floor light left
|
||||
lightingPath.lineTo(-2290, 950)
|
||||
lightingPath.lineTo(-2310, 950)
|
||||
lightingPath.lineTo(-2650, 1400)
|
||||
lightingPath.lineTo(-3025, 1400)
|
||||
lightingPath.lineTo(-3025, 150)
|
||||
lightingPath.lineTo(-2590, 150)
|
||||
lightingPath.lineTo(-2600, -150)
|
||||
lightingPath.lineTo(-1800, -150)
|
||||
lightingPath.lineTo(-1800, -500) //top left end/start of path
|
||||
|
||||
level.customTopLayer = () => {
|
||||
ctx.fillStyle = "rgba(0,0,0,0.15)"; //shadows and lights
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(-1800, -500)
|
||||
ctx.lineTo(-910, -500) //3rd floor light
|
||||
ctx.lineTo(-1300, 0)
|
||||
ctx.lineTo(-500, 0)
|
||||
ctx.lineTo(-890, -500)
|
||||
ctx.lineTo(-175, -500)
|
||||
ctx.lineTo(-175, -250)
|
||||
ctx.lineTo(175, -250)
|
||||
ctx.lineTo(175, 0)
|
||||
ctx.lineTo(-910, 100) //2nd floor light left
|
||||
ctx.lineTo(-1300, 600)
|
||||
ctx.lineTo(-500, 600)
|
||||
ctx.lineTo(-890, 100)
|
||||
ctx.lineTo(190, 100) //2nd floor light right
|
||||
ctx.lineTo(-200, 600)
|
||||
ctx.lineTo(600, 600)
|
||||
ctx.lineTo(210, 100)
|
||||
ctx.lineTo(1100, 100)
|
||||
ctx.lineTo(1100, 1400)
|
||||
ctx.lineTo(600, 1400) //1st floor light right
|
||||
ctx.lineTo(10, 700)
|
||||
ctx.lineTo(-10, 700)
|
||||
ctx.lineTo(-600, 1400)
|
||||
ctx.lineTo(-1950, 1400) //1st floor light left
|
||||
ctx.lineTo(-2290, 950)
|
||||
ctx.lineTo(-2310, 950)
|
||||
ctx.lineTo(-2650, 1400)
|
||||
ctx.lineTo(-3025, 1400)
|
||||
ctx.lineTo(-3025, 150)
|
||||
ctx.lineTo(-2590, 150)
|
||||
ctx.lineTo(-2600, -150)
|
||||
ctx.lineTo(-1800, -150)
|
||||
ctx.lineTo(-1800, -500) //top left end/start of path
|
||||
ctx.fill()
|
||||
ctx.fill(lightingPath);
|
||||
};
|
||||
|
||||
level.setPosToSpawn(25, -55); //normal spawn
|
||||
|
||||
@@ -495,7 +495,7 @@ const m = {
|
||||
if (tech.isSlowFPS) dmg *= 0.8
|
||||
// if (tech.isPiezo) dmg *= 0.85
|
||||
if (tech.isHarmReduce && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.4
|
||||
if (tech.isBotArmor) dmg *= 0.94 ** b.totalBots()
|
||||
if (tech.isBotArmor) dmg *= 0.93 ** b.totalBots()
|
||||
if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.33;
|
||||
if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.34
|
||||
if (tech.energyRegen === 0) dmg *= 0.34
|
||||
@@ -1682,6 +1682,9 @@ const m = {
|
||||
} else if (tech.isIceField) {
|
||||
m.energy -= 0.04;
|
||||
b.iceIX(1)
|
||||
} else if (tech.isDroneRadioactive) {
|
||||
m.energy -= 1;
|
||||
b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 25)
|
||||
} else {
|
||||
m.energy -= 0.45 * tech.droneEnergyReduction;
|
||||
b.drone()
|
||||
|
||||
@@ -736,7 +736,11 @@ const powerUps = {
|
||||
|
||||
//bonus power ups for clearing runs in the last game
|
||||
if (level.levelsCleared === 0 && !simulation.isCheating && localSettings.levelsClearedLastGame > 1) {
|
||||
for (let i = 0; i < localSettings.levelsClearedLastGame / 3; i++) powerUps.spawn(m.pos.x, m.pos.y, "tech", false); //spawn a tech for levels cleared in last game
|
||||
for (let i = 0; i < localSettings.levelsClearedLastGame / 3; i++) {
|
||||
powerUps.spawn(m.pos.x, m.pos.y, "tech", false); //spawn a tech for levels cleared in last game
|
||||
simulation.makeTextLog(`for (let i = 0; i < localSettings.levelsClearedLastGame / 3; i++)`);
|
||||
simulation.makeTextLog(`{ powerUps.spawn(m.pos.x, m.pos.y, "tech") //simulation superposition }`);
|
||||
}
|
||||
localSettings.levelsClearedLastGame = 0 //after getting bonus power ups reset run history
|
||||
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
|
||||
}
|
||||
|
||||
114
js/spawn.js
114
js/spawn.js
@@ -170,13 +170,13 @@ const spawn = {
|
||||
Matter.Body.setVelocity(this, { x: 0, y: 0 });
|
||||
|
||||
//aoe damage to player
|
||||
if (m.immuneCycle < m.cycle && Vector.magnitude(Vector.sub(player.position, this.position)) < this.radius && !tech.isNeutronImmune) {
|
||||
const DRAIN = 0.07
|
||||
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
|
||||
if (m.energy > DRAIN) {
|
||||
m.energy -= DRAIN
|
||||
} else {
|
||||
m.energy = 0;
|
||||
m.damage(0.007 * simulation.dmgScale)
|
||||
m.damage((tech.isRadioactiveResistance ? 0.007 * 0.25 : 0.007) * simulation.dmgScale)
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: this.position.x,
|
||||
y: this.position.y,
|
||||
@@ -233,7 +233,7 @@ const spawn = {
|
||||
y: me.position.y
|
||||
},
|
||||
bodyB: me,
|
||||
stiffness: 0.001,
|
||||
stiffness: 1,
|
||||
damping: 1
|
||||
});
|
||||
World.add(engine.world, me.constraint);
|
||||
@@ -244,7 +244,7 @@ const spawn = {
|
||||
me.memory = Infinity;
|
||||
me.hasRunDeathScript = false
|
||||
me.locatePlayer();
|
||||
const density = 0.25
|
||||
const density = 0.23
|
||||
Matter.Body.setDensity(me, density); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
// spawn.shield(me, x, y, 1);
|
||||
me.onDeath = function() {
|
||||
@@ -416,7 +416,7 @@ const spawn = {
|
||||
}
|
||||
} else if (this.mode !== 3) { //all three modes at once
|
||||
this.cycle = 0;
|
||||
Matter.Body.setDensity(me, density); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
Matter.Body.setDensity(me, 10 * density); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
if (this.mode === 2) {
|
||||
Matter.Body.scale(this, 5, 5);
|
||||
} else {
|
||||
@@ -1017,6 +1017,8 @@ const spawn = {
|
||||
me.accelMag = 0.04;
|
||||
me.g = 0.0017; //required if using 'gravity'
|
||||
me.frictionAir = 0.01;
|
||||
me.friction = 1
|
||||
me.frictionStatic = 1
|
||||
me.restitution = 0;
|
||||
me.delay = 120 * simulation.CDScale;
|
||||
me.randomHopFrequency = 200 + Math.floor(Math.random() * 150);
|
||||
@@ -1032,7 +1034,7 @@ const spawn = {
|
||||
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.07 + 0.02) * this.mass; //antigravity
|
||||
this.force.y += forceMag * Math.sin(angle) - (Math.random() * 0.07 + 0.06) * this.mass; //antigravity
|
||||
}
|
||||
} else {
|
||||
//randomly hob if not aware of player
|
||||
@@ -1048,6 +1050,96 @@ const spawn = {
|
||||
}
|
||||
};
|
||||
},
|
||||
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 '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.do = function() {
|
||||
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)) {
|
||||
mobs.spawn(x, y, 5, radius, "#000000");
|
||||
let me = mob[mob.length - 1];
|
||||
@@ -2063,7 +2155,7 @@ const spawn = {
|
||||
y: me.position.y
|
||||
},
|
||||
bodyB: me,
|
||||
stiffness: 0.001,
|
||||
stiffness: 1,
|
||||
damping: 1
|
||||
});
|
||||
World.add(engine.world, me.constraint);
|
||||
@@ -2575,8 +2667,8 @@ const spawn = {
|
||||
y: me.position.y
|
||||
},
|
||||
bodyB: me,
|
||||
stiffness: 0.0002,
|
||||
damping: 1
|
||||
stiffness: 0.00004,
|
||||
damping: 0.1
|
||||
});
|
||||
World.add(engine.world, me.constraint);
|
||||
}, 2000); //add in a delay in case the level gets flipped left right
|
||||
@@ -2912,7 +3004,7 @@ const spawn = {
|
||||
y: me.position.y
|
||||
},
|
||||
bodyB: me,
|
||||
stiffness: 0.001,
|
||||
stiffness: 0.0001,
|
||||
damping: 1
|
||||
});
|
||||
World.add(engine.world, me.constraint);
|
||||
|
||||
129
js/tech.js
129
js/tech.js
@@ -177,7 +177,7 @@
|
||||
if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.22
|
||||
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 1.9
|
||||
if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.43, player.speed * 0.015)
|
||||
if (tech.isBotDamage) dmg *= 1 + 0.05 * b.totalBots()
|
||||
if (tech.isBotDamage) dmg *= 1 + 0.06 * b.totalBots()
|
||||
return dmg * tech.slowFire * tech.aimDamage
|
||||
},
|
||||
duplicationChance() {
|
||||
@@ -716,7 +716,7 @@
|
||||
},
|
||||
requires: "an explosive damage source, not ammonium nitrate or nitroglycerin",
|
||||
effect: () => {
|
||||
tech.isExplodeRadio = true;
|
||||
tech.isExplodeRadio = true; //iridium-192
|
||||
},
|
||||
remove() {
|
||||
tech.isExplodeRadio = false;
|
||||
@@ -823,9 +823,9 @@
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isMissileField || tech.isExplodeMob || tech.isPulseLaser || tech.isBlockExplosion
|
||||
return !tech.isExplodeRadio && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isMissileField || tech.isExplodeMob || tech.isPulseLaser || tech.isBlockExplosion)
|
||||
},
|
||||
requires: "an explosive damage source",
|
||||
requires: "an explosive damage source, not iridium-192",
|
||||
effect: () => {
|
||||
tech.isImmuneExplosion = true;
|
||||
},
|
||||
@@ -841,9 +841,9 @@
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return ((m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField)) || tech.haveGunCheck("drones") || 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
|
||||
},
|
||||
requires: "drones, super balls, shotgun",
|
||||
requires: "super balls, shotgun, drones, not radioactive drones",
|
||||
effect() {
|
||||
tech.isIncendiary = true
|
||||
},
|
||||
@@ -1376,7 +1376,7 @@
|
||||
},
|
||||
{
|
||||
name: "perimeter defense",
|
||||
description: "reduce <strong class='color-harm'>harm</strong> by <strong>6%</strong><br>for each of your permanent <strong class='color-bot'>bots</strong>",
|
||||
description: "reduce <strong class='color-harm'>harm</strong> by <strong>7%</strong><br>for each of your permanent <strong class='color-bot'>bots</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
@@ -1394,7 +1394,7 @@
|
||||
},
|
||||
{
|
||||
name: "network effect",
|
||||
description: "increase <strong class='color-d'>damage</strong> by <strong>5%</strong><br>for each of your permanent <strong class='color-bot'>bots</strong>",
|
||||
description: "increase <strong class='color-d'>damage</strong> by <strong>6%</strong><br>for each of your permanent <strong class='color-bot'>bots</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
@@ -2509,7 +2509,7 @@
|
||||
},
|
||||
{
|
||||
name: "negentropy",
|
||||
description: `at the start of each <strong>level</strong><br>spawn a <strong class='color-h'>heal</strong> for every <strong>33</strong> missing health`,
|
||||
description: `at the start of each <strong>level</strong><br>spawn a <strong class='color-h'>heal</strong> for every <strong>25</strong> missing health`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -4039,7 +4039,7 @@
|
||||
},
|
||||
{
|
||||
name: "neutron bomb",
|
||||
description: "<strong>grenades</strong> are irradiated with <strong class='color-p'>Cf-252</strong><br>does <strong class='color-d'>damage</strong>, <strong class='color-harm'>harm</strong>, and drains <strong class='color-f'>energy</strong>",
|
||||
description: "<strong>grenades</strong> are <strong class='color-p'>irradiated</strong> with <strong class='color-p'>Cf-252</strong><br>does <strong class='color-d'>damage</strong>, <strong class='color-harm'>harm</strong>, and drains <strong class='color-f'>energy</strong>",
|
||||
isGunTech: true,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -4060,35 +4060,35 @@
|
||||
},
|
||||
{
|
||||
name: "water shielding",
|
||||
description: "increase <strong>neutron bomb's</strong> range by <strong>20%</strong><br>you are <strong>immune</strong> to its harmful effects",
|
||||
description: "<strong class='color-p'>radioactive</strong> effects on you are reduced by 75%<br><em>neutron bomb, drones, explosions, slime</em>",
|
||||
isGunTech: true,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return tech.isNeutronBomb
|
||||
return tech.isNeutronBomb || tech.isDroneRadioactive
|
||||
},
|
||||
requires: "neutron bomb",
|
||||
requires: "neutron bomb or radioactive drones",
|
||||
effect() {
|
||||
tech.isNeutronImmune = true
|
||||
tech.isRadioactiveResistance = true
|
||||
},
|
||||
remove() {
|
||||
tech.isNeutronImmune = false
|
||||
tech.isRadioactiveResistance = false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "vacuum permittivity",
|
||||
description: "increase <strong>neutron bomb's</strong> range by <strong>20%</strong><br>objects in range of the bomb are <strong>slowed</strong>",
|
||||
description: "increase <strong class='color-p'>radioactive</strong> range by <strong>20%</strong><br>objects in range of the bomb are <strong>slowed</strong>",
|
||||
isGunTech: true,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return tech.isNeutronBomb
|
||||
return tech.isNeutronBomb || tech.isDroneRadioactive
|
||||
},
|
||||
requires: "neutron bomb",
|
||||
requires: "neutron bomb or radioactive drones",
|
||||
effect() {
|
||||
tech.isNeutronSlow = true
|
||||
},
|
||||
@@ -4270,6 +4270,39 @@
|
||||
tech.isMutualism = false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "radioisotope generator",
|
||||
description: "<strong class='color-p'>irradiate</strong> <strong>drones</strong>, reduce <strong class='color-g'>ammo</strong> by <strong>75%</strong><br>does <strong class='color-d'>damage</strong>, <strong class='color-harm'>harm</strong>, and drains <strong class='color-f'>energy</strong>",
|
||||
isGunTech: true,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return tech.haveGunCheck("drones") && tech.droneCycleReduction === 1 && !tech.isIncendiary
|
||||
},
|
||||
requires: "drone gun, not reduced tolerances or incendiary",
|
||||
effect() {
|
||||
tech.isDroneRadioactive = true
|
||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||
if (b.guns[i].name === "drones") {
|
||||
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * 0.25
|
||||
b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 0.25)
|
||||
}
|
||||
}
|
||||
},
|
||||
remove() {
|
||||
if (tech.isDroneRadioactive) {
|
||||
tech.isDroneRadioactive = false
|
||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||
if (b.guns[i].name === "drones") {
|
||||
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack
|
||||
b.guns[i].ammo = b.guns[i].ammo * 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "brushless motor",
|
||||
description: "<strong>drones</strong> accelerate <strong>50%</strong> faster",
|
||||
@@ -4308,33 +4341,6 @@
|
||||
tech.isDroneGrab = false
|
||||
}
|
||||
},
|
||||
{
|
||||
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>",
|
||||
isGunTech: true,
|
||||
maxCount: 3,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField))
|
||||
},
|
||||
requires: "drones",
|
||||
effect() {
|
||||
tech.droneCycleReduction = Math.pow(0.6, 1 + this.count)
|
||||
tech.droneEnergyReduction = Math.pow(0.333, 1 + this.count)
|
||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||
if (b.guns[i].name === "drones") b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * Math.pow(3, this.count)
|
||||
}
|
||||
},
|
||||
remove() {
|
||||
tech.droneCycleReduction = 1
|
||||
tech.droneEnergyReduction = 1
|
||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||
if (b.guns[i].name === "drones") b.guns[i].ammoPack = b.guns[i].defaultAmmoPack
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "drone repair",
|
||||
description: "broken <strong>drones</strong> <strong>repair</strong> if the drone <strong class='color-g'>gun</strong> is active<br><strong>repairing</strong> has a <strong>33%</strong> chance to use <strong>1</strong> <strong class='color-g'>ammo</strong>",
|
||||
@@ -4354,6 +4360,36 @@
|
||||
tech.isDroneRespawn = false
|
||||
}
|
||||
},
|
||||
{
|
||||
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>",
|
||||
isGunTech: true,
|
||||
maxCount: 3,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return !tech.isDroneRadioactive && (tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField)))
|
||||
},
|
||||
requires: "drones",
|
||||
effect() {
|
||||
tech.droneCycleReduction = Math.pow(0.6, 1 + this.count)
|
||||
tech.droneEnergyReduction = Math.pow(0.333, 1 + this.count)
|
||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||
if (b.guns[i].name === "drones") {
|
||||
const scale = Math.pow(3, this.count + 1)
|
||||
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * scale
|
||||
}
|
||||
}
|
||||
},
|
||||
remove() {
|
||||
tech.droneCycleReduction = 1
|
||||
tech.droneEnergyReduction = 1
|
||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||
if (b.guns[i].name === "drones") b.guns[i].ammoPack = b.guns[i].defaultAmmoPack
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "necrophoresis",
|
||||
description: "<strong>foam</strong> bubbles grow and split into 3 <strong>copies</strong><br> when the mob they are stuck to <strong>dies</strong>",
|
||||
@@ -7209,5 +7245,6 @@
|
||||
isBlockExplosion: null,
|
||||
superBallDelay: null,
|
||||
isBlockExplode: null,
|
||||
isOverHeal: null
|
||||
isOverHeal: null,
|
||||
isDroneRadioactive: null
|
||||
}
|
||||
Reference in New Issue
Block a user