planned obsolescence

bug fixes
  strong anthropic principle does 0.03599% more damage
  spores can stick to rotating blocks now
  probably fixed the new wormhole field while targeting a block -> crouch lock bug
  ceramic needles now correctly bypass shields

needles fire 3 at a time with a short delay and no spread

tech: planned obsolescence - 3x drone ammo, 1/3 drone nano-scale energy cost, but 53% reduced drone life span
This commit is contained in:
landgreen
2021-03-16 05:03:50 -07:00
parent 862a0ae9d0
commit 05fcb823b2
8 changed files with 554 additions and 507 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -35,7 +35,7 @@ const b = {
if (m.health > 0.05) { if (m.health > 0.05) {
m.damage(0.05 / m.harmReduction()); // /m.harmReduction() undoes damage increase from difficulty m.damage(0.05 / m.harmReduction()); // /m.harmReduction() undoes damage increase from difficulty
if (!(tech.isRewindAvoidDeath && m.energy > 0.66)) { //don't give ammo if CPT triggered if (!(tech.isRewindAvoidDeath && m.energy > 0.66)) { //don't give ammo if CPT triggered
for (let i = 0; i < 3; i++) powerUps.spawn(m.pos.x, m.pos.y, "ammo"); for (let i = 0; i < 4; i++) powerUps.spawn(m.pos.x, m.pos.y, "ammo");
} }
} }
} else { } else {
@@ -66,7 +66,7 @@ const b = {
if (m.health > 0.05) { if (m.health > 0.05) {
m.damage(0.05 / m.harmReduction()); // /m.harmReduction() undoes damage increase from difficulty m.damage(0.05 / m.harmReduction()); // /m.harmReduction() undoes damage increase from difficulty
if (!(tech.isRewindAvoidDeath && m.energy > 0.66)) { //don't give ammo if CPT triggered if (!(tech.isRewindAvoidDeath && m.energy > 0.66)) { //don't give ammo if CPT triggered
for (let i = 0; i < 3; i++) powerUps.spawn(m.pos.x, m.pos.y, "ammo"); for (let i = 0; i < 4; i++) powerUps.spawn(m.pos.x, m.pos.y, "ammo");
} }
} }
} else { } else {
@@ -98,7 +98,7 @@ const b = {
if (m.health > 0.05) { if (m.health > 0.05) {
m.damage(0.05 / m.harmReduction()); // /m.harmReduction() undoes damage increase from difficulty m.damage(0.05 / m.harmReduction()); // /m.harmReduction() undoes damage increase from difficulty
if (!(tech.isRewindAvoidDeath && m.energy > 0.66)) { //don't give ammo if CPT triggered if (!(tech.isRewindAvoidDeath && m.energy > 0.66)) { //don't give ammo if CPT triggered
for (let i = 0; i < 3; i++) powerUps.spawn(m.pos.x, m.pos.y, "ammo"); for (let i = 0; i < 4; i++) powerUps.spawn(m.pos.x, m.pos.y, "ammo");
} }
} }
} else { } else {
@@ -2037,7 +2037,7 @@ const b = {
restitution: 1, restitution: 1,
dmg: 0.24, //damage done in addition to the damage from momentum dmg: 0.24, //damage done in addition to the damage from momentum
lookFrequency: 80 + Math.floor(23 * Math.random()), lookFrequency: 80 + Math.floor(23 * Math.random()),
endCycle: simulation.cycle + Math.floor((1100 + 420 * Math.random()) * tech.isBulletsLastLonger), endCycle: simulation.cycle + Math.floor((1100 + 420 * Math.random()) * tech.isBulletsLastLonger * tech.droneCycleReduction),
classType: "bullet", classType: "bullet",
collisionFilter: { collisionFilter: {
category: cat.bullet, category: cat.bullet,
@@ -2109,7 +2109,7 @@ const b = {
powerUp.splice(i, 1); powerUp.splice(i, 1);
if (tech.isDroneGrab) { if (tech.isDroneGrab) {
this.isImproved = true; this.isImproved = true;
const SCALE = 3 const SCALE = 2.5
Matter.Body.scale(this, SCALE, SCALE); Matter.Body.scale(this, SCALE, SCALE);
this.lookFrequency = 30; this.lookFrequency = 30;
this.endCycle += 2500 this.endCycle += 2500
@@ -3214,8 +3214,6 @@ 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() {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 33 : 16) * b.fireCD); // cool down
function makeNeedle(angle = m.angle) { function makeNeedle(angle = m.angle) {
const me = bullet.length; const me = bullet.length;
bullet[me] = Bodies.rectangle(m.pos.x + 40 * Math.cos(m.angle), m.pos.y + 40 * Math.sin(m.angle), 50, 1, b.fireAttributes(angle)); bullet[me] = Bodies.rectangle(m.pos.x + 40 * Math.cos(m.angle), m.pos.y + 40 * Math.sin(m.angle), 50, 1, b.fireAttributes(angle));
@@ -3226,34 +3224,36 @@ const b = {
bullet[me].do = function() { bullet[me].do = function() {
const whom = Matter.Query.collides(this, mob) const whom = Matter.Query.collides(this, mob)
if (whom.length && this.speed > 20) { //if touching a mob if (whom.length && this.speed > 20) { //if touching a mob
who = whom[whom.length - 1].bodyA for (let i = 0, len = whom.length; i < len; i++) {
if (who && who.mob) { who = whom[i].bodyA
let immune = false if (who && who.mob) {
for (let i = 0; i < this.immuneList.length; i++) { let immune = false
if (this.immuneList[i] === who.id) { for (let i = 0; i < this.immuneList.length; i++) { //check if this needle has hit this mob already
immune = true if (this.immuneList[i] === who.id) {
break immune = true
break
}
} }
} if (!immune) {
if (!immune) { if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.975) {
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 + 30 * Math.random()); //makes bullet do explosive damage at end
b.explosion(this.position, 220 + 30 * Math.random()); //makes bullet do explosive damage at end }
} this.immuneList.push(who.id) //remember that this needle has hit this mob once already
this.immuneList.push(who.id) who.foundPlayer();
who.foundPlayer(); if (tech.isNailRadiation) {
if (tech.isNailRadiation) { mobs.statusDoT(who, tech.isFastRadiation ? 9 : 2.25, tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
mobs.statusDoT(who, tech.isFastRadiation ? 8 : 2, tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles } else {
} else { let dmg = b.dmgScale * 3.5
let dmg = b.dmgScale * 3.25 if (tech.isCrit && who.isStunned) dmg *= 4
if (tech.isCrit && who.isStunned) dmg *= 4 who.damage(dmg, tech.isNeedleShieldPierce);
who.damage(dmg, tech.isNeedleShieldPierce); simulation.drawList.push({ //add dmg to draw queue
simulation.drawList.push({ //add dmg to draw queue x: this.position.x,
x: this.position.x, y: this.position.y,
y: this.position.y, radius: Math.log(2 * dmg + 1.1) * 40,
radius: Math.log(2 * dmg + 1.1) * 40, color: simulation.playerDmgColor,
color: simulation.playerDmgColor, time: simulation.drawTime
time: simulation.drawTime });
}); }
} }
} }
} }
@@ -3277,10 +3277,26 @@ const b = {
Matter.Body.setDensity(bullet[me], 0.00001); Matter.Body.setDensity(bullet[me], 0.00001);
World.add(engine.world, bullet[me]); //add bullet to world World.add(engine.world, bullet[me]); //add bullet to world
} }
const spread = (m.crouch ? 0.013 : 0.06)
makeNeedle(m.angle + spread) if (m.crouch) {
makeNeedle() m.fireCDcycle = m.cycle + 50 * b.fireCD; // cool down
makeNeedle(m.angle - spread) makeNeedle()
for (let i = 1; i < 4; i++) { //4 total needles
setTimeout(() => { if (!simulation.paused) makeNeedle() }, 40 * i);
}
} else {
m.fireCDcycle = m.cycle + 30 * b.fireCD; // cool down
makeNeedle()
for (let i = 1; i < 3; i++) { //3 total needles
setTimeout(() => { if (!simulation.paused) makeNeedle() }, 40 * 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 ? 30 : 25) * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 30 : 25) * b.fireCD); // cool down
@@ -3553,8 +3569,7 @@ const b = {
} }
} }
} }
}, }, {
{
name: "super balls", name: "super balls",
description: "fire <strong>four</strong> balls in a wide arc<br>balls <strong>bounce</strong> with no momentum loss", description: "fire <strong>four</strong> balls in a wide arc<br>balls <strong>bounce</strong> with no momentum loss",
ammo: 0, ammo: 0,
@@ -3618,8 +3633,7 @@ const b = {
} }
} }
} }
}, }, {
{
name: "wave beam", name: "wave beam",
description: "emit a <strong>sine wave</strong> of oscillating particles<br>propagates through <strong>walls</strong>", description: "emit a <strong>sine wave</strong> of oscillating particles<br>propagates through <strong>walls</strong>",
ammo: 0, ammo: 0,
@@ -3729,8 +3743,7 @@ const b = {
const transverse = Vector.normalise(Vector.perp(bullet[me].velocity)) const transverse = Vector.normalise(Vector.perp(bullet[me].velocity))
} }
} }
}, }, {
{
name: "missiles", name: "missiles",
description: "launch <strong>homing</strong> missiles that <strong class='color-e'>explode</strong><br>crouch to <strong>rapidly</strong> launch smaller missiles", description: "launch <strong>homing</strong> missiles that <strong class='color-e'>explode</strong><br>crouch to <strong>rapidly</strong> launch smaller missiles",
ammo: 0, ammo: 0,
@@ -3846,8 +3859,7 @@ const b = {
// } // }
} }
}, }, {
{
name: "grenades", name: "grenades",
description: "lob a single <strong>bouncy</strong> projectile<br><strong class='color-e'>explodes</strong> on <strong>contact</strong> or after one second", description: "lob a single <strong>bouncy</strong> projectile<br><strong class='color-e'>explodes</strong> on <strong>contact</strong> or after one second",
ammo: 0, ammo: 0,
@@ -3857,8 +3869,7 @@ const b = {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 40 : 30) * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 40 : 30) * b.fireCD); // cool down
b.grenade() b.grenade()
}, },
}, }, {
{
name: "mine", name: "mine",
description: "toss a <strong>proximity</strong> mine that <strong>sticks</strong> to walls<br>fires <strong>nails</strong> at mobs within range", description: "toss a <strong>proximity</strong> mine that <strong>sticks</strong> to walls<br>fires <strong>nails</strong> at mobs within range",
ammo: 0, ammo: 0,
@@ -3885,8 +3896,7 @@ const b = {
} }
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 50 : 25) * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 50 : 25) * b.fireCD); // cool down
} }
}, }, {
{
name: "spores", name: "spores",
description: "fire a <strong class='color-p' style='letter-spacing: 2px;'>sporangium</strong> that discharges <strong class='color-p' style='letter-spacing: 2px;'>spores</strong><br><strong class='color-p' style='letter-spacing: 2px;'>spores</strong> seek out nearby mobs", description: "fire a <strong class='color-p' style='letter-spacing: 2px;'>sporangium</strong> that discharges <strong class='color-p' style='letter-spacing: 2px;'>spores</strong><br><strong class='color-p' style='letter-spacing: 2px;'>spores</strong> seek out nearby mobs",
ammo: 0, ammo: 0,
@@ -3947,7 +3957,7 @@ const b = {
} else { } else {
const bodyCollisions = Matter.Query.collides(this, body) const bodyCollisions = Matter.Query.collides(this, body)
if (bodyCollisions.length) { if (bodyCollisions.length) {
if (!bodyCollisions[0].bodyA.isNotHoldable) { if (!bodyCollisions[0].bodyA.isComposite) {
onCollide(this) onCollide(this)
this.stuckTo = bodyCollisions[0].bodyA this.stuckTo = bodyCollisions[0].bodyA
//find the relative position for when the mob is at angle zero by undoing the mobs rotation //find the relative position for when the mob is at angle zero by undoing the mobs rotation
@@ -4015,12 +4025,12 @@ const b = {
} }
} }
} }
}, }, {
{
name: "drones", name: "drones",
description: "deploy drones that <strong>crash</strong> into mobs<br>crashes reduce their <strong>lifespan</strong> by 1 second", description: "deploy drones that <strong>crash</strong> into mobs<br>crashes reduce their <strong>lifespan</strong> by 1 second",
ammo: 0, ammo: 0,
ammoPack: 14, ammoPack: 14,
defaultAmmoPack: 14,
have: false, have: false,
fire() { fire() {
if (m.crouch) { if (m.crouch) {
@@ -4086,8 +4096,7 @@ const b = {
b.foam(position, Vector.rotate(velocity, 0.5 * (Math.random() - 0.5)), radius) b.foam(position, Vector.rotate(velocity, 0.5 * (Math.random() - 0.5)), radius)
} }
} }
}, }, {
{
name: "rail gun", name: "rail gun",
description: "use <strong class='color-f'>energy</strong> to launch a high-speed <strong>dense</strong> rod<br><strong>hold</strong> left mouse to charge, <strong>release</strong> to fire", description: "use <strong class='color-f'>energy</strong> to launch a high-speed <strong>dense</strong> rod<br><strong>hold</strong> left mouse to charge, <strong>release</strong> to fire",
ammo: 0, ammo: 0,
@@ -4431,8 +4440,7 @@ const b = {
} }
} }
} }
}, }, {
{
name: "laser", name: "laser",
description: "emit a <strong>beam</strong> of collimated coherent <strong class='color-laser'>light</strong><br>drains <strong class='color-f'>energy</strong> instead of ammunition", description: "emit a <strong>beam</strong> of collimated coherent <strong class='color-laser'>light</strong><br>drains <strong class='color-f'>energy</strong> instead of ammunition",
ammo: 0, ammo: 0,

View File

@@ -16,11 +16,11 @@ const level = {
// simulation.zoomScale = 1000; // simulation.zoomScale = 1000;
// simulation.setZoom(); // simulation.setZoom();
// m.setField("nano-scale manufacturing") // m.setField("nano-scale manufacturing")
// b.giveGuns("foam") // b.giveGuns("spores")
// tech.isExplodeRadio = true // tech.isExplodeRadio = true
// for (let i = 0; i < 1; i++) tech.giveTech("dynamo-bot") // for (let i = 0; i < 1; i++) tech.giveTech("dynamo-bot")
// tech.giveTech("supercritical fission") // tech.giveTech("needle gun")
// tech.giveTech("micro-extruder") // tech.giveTech("ceramic needles")
// tech.giveTech("causality bombs") // tech.giveTech("causality bombs")
// tech.giveTech("cardinality") // tech.giveTech("cardinality")
// tech.giveTech("Bayesian statistics") // tech.giveTech("Bayesian statistics")
@@ -424,12 +424,14 @@ const level = {
rotor(x, y, rotate = 0, radius = 800, width = 40, density = 0.0005) { rotor(x, y, rotate = 0, radius = 800, width = 40, density = 0.0005) {
const rotor1 = Matter.Bodies.rectangle(x, y, width, radius, { const rotor1 = Matter.Bodies.rectangle(x, y, width, radius, {
density: density, density: density,
isNotHoldable: true isNotHoldable: true,
isComposite: true
}); });
const rotor2 = Matter.Bodies.rectangle(x, y, width, radius, { const rotor2 = Matter.Bodies.rectangle(x, y, width, radius, {
angle: Math.PI / 2, angle: Math.PI / 2,
density: density, density: density,
isNotHoldable: true isNotHoldable: true,
isComposite: true
}); });
rotor = Body.create({ //combine rotor1 and rotor2 rotor = Body.create({ //combine rotor1 and rotor2
parts: [rotor1, rotor2], parts: [rotor1, rotor2],
@@ -1100,8 +1102,8 @@ const level = {
// simulation.difficulty = 30 // simulation.difficulty = 30
// spawn.starter(1900, -500, 200) //big boy // spawn.starter(1900, -500, 200) //big boy
spawn.pulsar(1900, -500) // spawn.pulsar(1900, -500)
spawn.pulsarBoss(1900, -500) // spawn.pulsarBoss(1900, -500)
// spawn.historyBoss(1900, -500) // spawn.historyBoss(1900, -500)
// spawn.ghoster(2900, -500) // spawn.ghoster(2900, -500)
// spawn.launcherBoss(1200, -500) // spawn.launcherBoss(1200, -500)
@@ -1113,7 +1115,7 @@ const level = {
// spawn.streamBoss(1600, -500) // spawn.streamBoss(1600, -500)
// spawn.orbitalBoss(1600, -500) // spawn.orbitalBoss(1600, -500)
// spawn.cellBossCulture(1600, -500) // spawn.cellBossCulture(1600, -500)
// spawn.shieldingBoss(1600, -500) spawn.shieldingBoss(1600, -500)
// spawn.beamer(1200, -500) // spawn.beamer(1200, -500)
// spawn.shield(mob[mob.length - 1], 1800, -120, 1); // spawn.shield(mob[mob.length - 1], 1800, -120, 1);
@@ -4956,13 +4958,13 @@ const level = {
document.body.style.backgroundColor = "#dcdcde"; document.body.style.backgroundColor = "#dcdcde";
//Level //Level
level.setPosToSpawn(200, 50); level.setPosToSpawn(200, 50);
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.exit.x = 8950; level.exit.x = 8950;
level.exit.y = 200; level.exit.y = 170;
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20);
//Map //Map
spawn.mapRect(150, 90, 100, 100);
spawn.mapRect(8950, 190, 100, 100);
spawn.mapRect(-100, -400, 100, 600); spawn.mapRect(-100, -400, 100, 600);
spawn.mapRect(-100, 100, 700, 100); spawn.mapRect(-100, 100, 700, 100);
spawn.mapRect(500, 100, 100, 1700); spawn.mapRect(500, 100, 100, 1700);
@@ -5006,7 +5008,7 @@ const level = {
spawn.mapRect(8000, 1500, 300, 100); spawn.mapRect(8000, 1500, 300, 100);
spawn.mapRect(7120, -100, 300, 100); spawn.mapRect(7120, -100, 300, 100);
spawn.mapRect(7000, 1500, 300, 100); spawn.mapRect(7000, 1500, 300, 100);
spawn.mapRect(6500, 1000, 300, 2100); spawn.mapRect(6500, 1000, 300, 1200);
spawn.mapRect(5800, 1100, 300, 100); spawn.mapRect(5800, 1100, 300, 100);
spawn.mapRect(5900, 1700, 300, 100); spawn.mapRect(5900, 1700, 300, 100);
spawn.mapRect(5300, 1400, 300, 100); spawn.mapRect(5300, 1400, 300, 100);
@@ -5063,11 +5065,11 @@ const level = {
spawn.randomMob(8650, -200, 0.9); //end guards spawn.randomMob(8650, -200, 0.9); //end guards
//Boss Spawning //Boss Spawning
spawn.randomLevelBoss(6000, 700, ["pulsarBoss", "laserTargetingBoss", "powerUpBoss", "bomberBoss", "historyBoss", "orbitalBoss"]); if (simulation.difficulty > 3) {
spawn.shieldingBoss(7200, 500); spawn.randomLevelBoss(6000, 700, ["pulsarBoss", "laserTargetingBoss", "powerUpBoss", "bomberBoss", "historyBoss", "orbitalBoss"]);
if (simulation.difficulty > 20) { if (simulation.difficulty > 10) spawn.shieldingBoss(7200, 500);
spawn.randomLevelBoss(2000, 300, ["historyBoss", "shooterBoss"]); if (simulation.difficulty > 20) spawn.randomLevelBoss(2000, 300, ["historyBoss", "shooterBoss"]);
} }
//Blocks //Blocks

View File

@@ -392,7 +392,7 @@ const m = {
simulation.makeGunHUD(); //update gun HUD simulation.makeGunHUD(); //update gun HUD
simulation.updateTechHUD(); simulation.updateTechHUD();
simulation.isTextLogOpen = true; simulation.isTextLogOpen = true;
if (m.holdingTarget) m.drop(); m.drop();
if (simulation.paused) build.pauseGrid() //update the build when paused if (simulation.paused) build.pauseGrid() //update the build when paused
}, },
death() { death() {
@@ -498,7 +498,7 @@ const m = {
harmReduction() { harmReduction() {
let dmg = 1 let dmg = 1
dmg *= m.fieldHarmReduction dmg *= m.fieldHarmReduction
if (tech.isImmortal) dmg *= 0.84 if (tech.isImmortal) dmg *= 0.79
if (tech.isHarmReduceAfterKill) dmg *= (m.lastKillCycle + 300 > m.cycle) ? 0.25 : 1.25 if (tech.isHarmReduceAfterKill) dmg *= (m.lastKillCycle + 300 > m.cycle) ? 0.25 : 1.25
if (tech.healthDrain) dmg *= 1 + 2.667 * tech.healthDrain //tech.healthDrain = 0.03 at one stack //cause more damage if (tech.healthDrain) dmg *= 1 + 2.667 * tech.healthDrain //tech.healthDrain = 0.03 at one stack //cause more damage
if (tech.squirrelFx !== 1) dmg *= 1 + (tech.squirrelFx - 1) / 5 //cause more damage if (tech.squirrelFx !== 1) dmg *= 1 + (tech.squirrelFx - 1) / 5 //cause more damage
@@ -631,7 +631,7 @@ const m = {
} }
m.lastHarmCycle = m.cycle m.lastHarmCycle = m.cycle
if (tech.isDroneOnDamage) { //chance to build a drone on damage from tech if (tech.isDroneOnDamage) { //chance to build a drone on damage from tech
const len = Math.min((dmg - 0.06 * Math.random()) * 40, 40) const len = Math.min((dmg - 0.06 * Math.random()) * 40, 40) / tech.droneEnergyReduction
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
if (Math.random() < 0.5) b.drone() //spawn drone if (Math.random() < 0.5) b.drone() //spawn drone
} }
@@ -1002,11 +1002,11 @@ const m = {
m.isHolding = false; m.isHolding = false;
m.throwCharge = 0; m.throwCharge = 0;
m.definePlayerMass() m.definePlayerMass()
if (m.holdingTarget) { }
m.holdingTarget.collisionFilter.category = cat.body; if (m.holdingTarget) {
m.holdingTarget.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet m.holdingTarget.collisionFilter.category = cat.body;
m.holdingTarget = null; m.holdingTarget.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet
} m.holdingTarget = null;
} }
}, },
definePlayerMass(mass = m.defaultMass) { definePlayerMass(mass = m.defaultMass) {
@@ -1376,7 +1376,7 @@ const m = {
if (tech.isFreezeMobs) { if (tech.isFreezeMobs) {
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
Matter.Sleeping.set(mob[i], false) Matter.Sleeping.set(mob[i], false)
mobs.statusSlow(mob[i], 90) mobs.statusSlow(mob[i], 60)
} }
} else { } else {
wake(mob); wake(mob);
@@ -1566,7 +1566,7 @@ const m = {
m.energy -= 0.057; m.energy -= 0.057;
b.iceIX(1) b.iceIX(1)
} else { } else {
m.energy -= 0.45; m.energy -= 0.45 * tech.droneEnergyReduction;
b.drone(1) b.drone(1)
} }
} }
@@ -2297,15 +2297,246 @@ const m = {
name: "wormhole", name: "wormhole",
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract blocks and power ups<br><strong>7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong> description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract blocks and power ups<br><strong>7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
effect: function() { effect: function() {
m.drop();
m.duplicateChance = 0.07 m.duplicateChance = 0.07
simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw
// if (tech.isRewindGun) { m.hold = function() {
// m.hold = this.rewind // m.hole = { //this is reset with each new field, but I'm leaving it here for reference
// } else { // isOn: false,
m.hold = this.teleport // isReady: true,
// } // pos1: {x: 0,y: 0},
// pos2: {x: 0,y: 0},
// angle: 0,
// unit:{x:0,y:0},
// }
if (m.hole.isOn) {
// draw holes
m.fieldRange = 0.97 * m.fieldRange + 0.03 * (50 + 10 * Math.sin(simulation.cycle * 0.025))
const semiMajorAxis = m.fieldRange + 30
const edge1a = Vector.add(Vector.mult(m.hole.unit, semiMajorAxis), m.hole.pos1)
const edge1b = Vector.add(Vector.mult(m.hole.unit, -semiMajorAxis), m.hole.pos1)
const edge2a = Vector.add(Vector.mult(m.hole.unit, semiMajorAxis), m.hole.pos2)
const edge2b = Vector.add(Vector.mult(m.hole.unit, -semiMajorAxis), m.hole.pos2)
ctx.beginPath();
ctx.moveTo(edge1a.x, edge1a.y)
ctx.bezierCurveTo(m.hole.pos1.x, m.hole.pos1.y, m.hole.pos2.x, m.hole.pos2.y, edge2a.x, edge2a.y);
ctx.lineTo(edge2b.x, edge2b.y)
ctx.bezierCurveTo(m.hole.pos2.x, m.hole.pos2.y, m.hole.pos1.x, m.hole.pos1.y, edge1b.x, edge1b.y);
ctx.fillStyle = `rgba(255,255,255,${200 / m.fieldRange / m.fieldRange})` //"rgba(0,0,0,0.1)"
ctx.fill();
ctx.beginPath();
ctx.ellipse(m.hole.pos1.x, m.hole.pos1.y, m.fieldRange, semiMajorAxis, m.hole.angle, 0, 2 * Math.PI)
ctx.ellipse(m.hole.pos2.x, m.hole.pos2.y, m.fieldRange, semiMajorAxis, m.hole.angle, 0, 2 * Math.PI)
ctx.fillStyle = `rgba(255,255,255,${32 / m.fieldRange})`
ctx.fill();
//suck power ups
for (let i = 0, len = powerUp.length; i < len; ++i) {
//which hole is closer
const dxP1 = m.hole.pos1.x - powerUp[i].position.x;
const dyP1 = m.hole.pos1.y - powerUp[i].position.y;
const dxP2 = m.hole.pos2.x - powerUp[i].position.x;
const dyP2 = m.hole.pos2.y - powerUp[i].position.y;
let dxP, dyP, dist2
if (dxP1 * dxP1 + dyP1 * dyP1 < dxP2 * dxP2 + dyP2 * dyP2) {
dxP = dxP1
dyP = dyP1
} else {
dxP = dxP2
dyP = dyP2
}
dist2 = dxP * dxP + dyP * dyP;
if (dist2 < 600000 && !(m.health === m.maxHealth && powerUp[i].name === "heal")) {
powerUp[i].force.x += 4 * (dxP / dist2) * powerUp[i].mass; // float towards hole
powerUp[i].force.y += 4 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity
Matter.Body.setVelocity(powerUp[i], { //extra friction
x: powerUp[i].velocity.x * 0.05,
y: powerUp[i].velocity.y * 0.05
});
if (dist2 < 1000 && !simulation.isChoosing) { //use power up if it is close enough
m.fieldRange *= 0.8
powerUps.onPickUp(powerUp[i]);
powerUp[i].effect();
Matter.World.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1);
break; //because the array order is messed up after splice
}
}
}
//suck and shrink blocks
const suckRange = 500
const shrinkRange = 100
const shrinkScale = 0.97;
const slowScale = 0.9
for (let i = 0, len = body.length; i < len; i++) {
if (!body[i].isNotHoldable) {
const dist1 = Vector.magnitude(Vector.sub(m.hole.pos1, body[i].position))
const dist2 = Vector.magnitude(Vector.sub(m.hole.pos2, body[i].position))
if (dist1 < dist2) {
if (dist1 < suckRange) {
const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos1, body[i].position)), 1)
const slow = Vector.mult(body[i].velocity, slowScale)
Matter.Body.setVelocity(body[i], Vector.add(slow, pull));
//shrink
if (Vector.magnitude(Vector.sub(m.hole.pos1, body[i].position)) < shrinkRange) {
Matter.Body.scale(body[i], shrinkScale, shrinkScale);
if (body[i].mass < 0.05) {
Matter.World.remove(engine.world, body[i]);
body.splice(i, 1);
m.fieldRange *= 0.8
if (tech.isWormholeEnergy) m.energy += 0.63
if (tech.isWormSpores) { //pandimensionalspermia
for (let i = 0, len = Math.ceil(3 * Math.random()); i < len; i++) {
b.spore(Vector.add(m.hole.pos2, Vector.rotate({
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -15));
}
}
break
}
}
}
} else if (dist2 < suckRange) {
const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos2, body[i].position)), 1)
const slow = Vector.mult(body[i].velocity, slowScale)
Matter.Body.setVelocity(body[i], Vector.add(slow, pull));
//shrink
if (Vector.magnitude(Vector.sub(m.hole.pos2, body[i].position)) < shrinkRange) {
Matter.Body.scale(body[i], shrinkScale, shrinkScale);
if (body[i].mass < 0.05) {
Matter.World.remove(engine.world, body[i]);
body.splice(i, 1);
m.fieldRange *= 0.8
// if (tech.isWormholeEnergy && m.energy < m.maxEnergy * 2) m.energy = m.maxEnergy * 2
if (tech.isWormholeEnergy) m.energy += 0.63
if (tech.isWormSpores) { //pandimensionalspermia
for (let i = 0, len = Math.ceil(3 * Math.random()); i < len; i++) {
b.spore(Vector.add(m.hole.pos1, Vector.rotate({
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), 15));
}
}
break
}
}
}
}
}
if (tech.isWormBullets) {
//teleport bullets
for (let i = 0, len = bullet.length; i < len; ++i) { //teleport bullets from hole1 to hole2
if (!bullet[i].botType && !bullet[i].isInHole) { //don't teleport bots
if (Vector.magnitude(Vector.sub(m.hole.pos1, bullet[i].position)) < m.fieldRange) { //find if bullet is touching hole1
Matter.Body.setPosition(bullet[i], Vector.add(m.hole.pos2, Vector.sub(m.hole.pos1, bullet[i].position)));
m.fieldRange += 5
bullet[i].isInHole = true
} else if (Vector.magnitude(Vector.sub(m.hole.pos2, bullet[i].position)) < m.fieldRange) { //find if bullet is touching hole1
Matter.Body.setPosition(bullet[i], Vector.add(m.hole.pos1, Vector.sub(m.hole.pos2, bullet[i].position)));
m.fieldRange += 5
bullet[i].isInHole = true
}
}
}
// mobs get pushed away
for (let i = 0, len = mob.length; i < len; i++) {
if (Vector.magnitude(Vector.sub(m.hole.pos1, mob[i].position)) < 200) {
const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos1, mob[i].position)), -0.07)
Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
}
if (Vector.magnitude(Vector.sub(m.hole.pos2, mob[i].position)) < 200) {
const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos2, mob[i].position)), -0.07)
Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
}
}
}
}
if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
const justPastMouse = Vector.add(Vector.mult(Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)), 50), simulation.mouseInGame)
const scale = 60
// console.log(Matter.Query.region(map, bounds))
if (m.hole.isReady &&
(
Matter.Query.region(map, {
min: {
x: simulation.mouseInGame.x - scale,
y: simulation.mouseInGame.y - scale
},
max: {
x: simulation.mouseInGame.x + scale,
y: simulation.mouseInGame.y + scale
}
}).length === 0 &&
Matter.Query.ray(map, m.pos, justPastMouse).length === 0
// Matter.Query.ray(map, m.pos, simulation.mouseInGame).length === 0 &&
// Matter.Query.ray(map, player.position, simulation.mouseInGame).length === 0 &&
// Matter.Query.ray(map, player.position, justPastMouse).length === 0
)
) {
const sub = Vector.sub(simulation.mouseInGame, m.pos)
const mag = Vector.magnitude(sub)
const drain = 0.03 + 0.005 * Math.sqrt(mag)
if (m.energy > drain && mag > 300) {
m.energy -= drain
m.hole.isReady = false;
m.fieldRange = 0
Matter.Body.setPosition(player, simulation.mouseInGame);
m.buttonCD_jump = 0 //this might fix a bug with jumping
const velocity = Vector.mult(Vector.normalise(sub), 18)
Matter.Body.setVelocity(player, {
x: velocity.x,
y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer
});
if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
// move bots to player
for (let i = 0; i < bullet.length; i++) {
if (bullet[i].botType) {
Matter.Body.setPosition(bullet[i], Vector.add(player.position, {
x: 250 * (Math.random() - 0.5),
y: 250 * (Math.random() - 0.5)
}));
Matter.Body.setVelocity(bullet[i], {
x: 0,
y: 0
});
}
}
//set holes
m.hole.isOn = true;
m.hole.pos1.x = m.pos.x
m.hole.pos1.y = m.pos.y
m.hole.pos2.x = player.position.x
m.hole.pos2.y = player.position.y
m.hole.angle = Math.atan2(sub.y, sub.x)
m.hole.unit = Vector.perp(Vector.normalise(sub))
if (tech.isWormholeDamage) {
who = Matter.Query.ray(mob, m.pos, simulation.mouseInGame, 100)
for (let i = 0; i < who.length; i++) {
if (who[i].body.alive) {
mobs.statusDoT(who[i].body, 1, 420)
mobs.statusStun(who[i].body, 360)
}
}
}
} else {
m.grabPowerUp();
}
} else {
m.grabPowerUp();
}
// } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
// m.pickUp();
} else {
m.hole.isReady = true;
}
m.drawFieldMeter()
}
}, },
rewindCount: 0, rewindCount: 0,
// rewind: function() { // rewind: function() {
@@ -2392,244 +2623,6 @@ const m = {
// } // }
// m.drawFieldMeter() // m.drawFieldMeter()
// }, // },
teleport: function() {
// m.hole = { //this is reset with each new field, but I'm leaving it here for reference
// isOn: false,
// isReady: true,
// pos1: {x: 0,y: 0},
// pos2: {x: 0,y: 0},
// angle: 0,
// unit:{x:0,y:0},
// }
if (m.hole.isOn) {
// draw holes
m.fieldRange = 0.97 * m.fieldRange + 0.03 * (50 + 10 * Math.sin(simulation.cycle * 0.025))
const semiMajorAxis = m.fieldRange + 30
const edge1a = Vector.add(Vector.mult(m.hole.unit, semiMajorAxis), m.hole.pos1)
const edge1b = Vector.add(Vector.mult(m.hole.unit, -semiMajorAxis), m.hole.pos1)
const edge2a = Vector.add(Vector.mult(m.hole.unit, semiMajorAxis), m.hole.pos2)
const edge2b = Vector.add(Vector.mult(m.hole.unit, -semiMajorAxis), m.hole.pos2)
ctx.beginPath();
ctx.moveTo(edge1a.x, edge1a.y)
ctx.bezierCurveTo(m.hole.pos1.x, m.hole.pos1.y, m.hole.pos2.x, m.hole.pos2.y, edge2a.x, edge2a.y);
ctx.lineTo(edge2b.x, edge2b.y)
ctx.bezierCurveTo(m.hole.pos2.x, m.hole.pos2.y, m.hole.pos1.x, m.hole.pos1.y, edge1b.x, edge1b.y);
ctx.fillStyle = `rgba(255,255,255,${200 / m.fieldRange / m.fieldRange})` //"rgba(0,0,0,0.1)"
ctx.fill();
ctx.beginPath();
ctx.ellipse(m.hole.pos1.x, m.hole.pos1.y, m.fieldRange, semiMajorAxis, m.hole.angle, 0, 2 * Math.PI)
ctx.ellipse(m.hole.pos2.x, m.hole.pos2.y, m.fieldRange, semiMajorAxis, m.hole.angle, 0, 2 * Math.PI)
ctx.fillStyle = `rgba(255,255,255,${32 / m.fieldRange})`
ctx.fill();
//suck power ups
for (let i = 0, len = powerUp.length; i < len; ++i) {
//which hole is closer
const dxP1 = m.hole.pos1.x - powerUp[i].position.x;
const dyP1 = m.hole.pos1.y - powerUp[i].position.y;
const dxP2 = m.hole.pos2.x - powerUp[i].position.x;
const dyP2 = m.hole.pos2.y - powerUp[i].position.y;
let dxP, dyP, dist2
if (dxP1 * dxP1 + dyP1 * dyP1 < dxP2 * dxP2 + dyP2 * dyP2) {
dxP = dxP1
dyP = dyP1
} else {
dxP = dxP2
dyP = dyP2
}
dist2 = dxP * dxP + dyP * dyP;
if (dist2 < 600000 && !(m.health === m.maxHealth && powerUp[i].name === "heal")) {
powerUp[i].force.x += 4 * (dxP / dist2) * powerUp[i].mass; // float towards hole
powerUp[i].force.y += 4 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity
Matter.Body.setVelocity(powerUp[i], { //extra friction
x: powerUp[i].velocity.x * 0.05,
y: powerUp[i].velocity.y * 0.05
});
if (dist2 < 1000 && !simulation.isChoosing) { //use power up if it is close enough
m.fieldRange *= 0.8
powerUps.onPickUp(powerUp[i]);
powerUp[i].effect();
Matter.World.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1);
break; //because the array order is messed up after splice
}
}
}
//suck and shrink blocks
const suckRange = 500
const shrinkRange = 100
const shrinkScale = 0.97;
const slowScale = 0.9
for (let i = 0, len = body.length; i < len; i++) {
if (!body[i].isNotHoldable) {
const dist1 = Vector.magnitude(Vector.sub(m.hole.pos1, body[i].position))
const dist2 = Vector.magnitude(Vector.sub(m.hole.pos2, body[i].position))
if (dist1 < dist2) {
if (dist1 < suckRange) {
const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos1, body[i].position)), 1)
const slow = Vector.mult(body[i].velocity, slowScale)
Matter.Body.setVelocity(body[i], Vector.add(slow, pull));
//shrink
if (Vector.magnitude(Vector.sub(m.hole.pos1, body[i].position)) < shrinkRange) {
Matter.Body.scale(body[i], shrinkScale, shrinkScale);
if (body[i].mass < 0.05) {
Matter.World.remove(engine.world, body[i]);
body.splice(i, 1);
m.fieldRange *= 0.8
if (tech.isWormholeEnergy) m.energy += 0.63
if (tech.isWormSpores) { //pandimensionalspermia
for (let i = 0, len = Math.ceil(3 * Math.random()); i < len; i++) {
b.spore(Vector.add(m.hole.pos2, Vector.rotate({
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -15));
}
}
break
}
}
}
} else if (dist2 < suckRange) {
const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos2, body[i].position)), 1)
const slow = Vector.mult(body[i].velocity, slowScale)
Matter.Body.setVelocity(body[i], Vector.add(slow, pull));
//shrink
if (Vector.magnitude(Vector.sub(m.hole.pos2, body[i].position)) < shrinkRange) {
Matter.Body.scale(body[i], shrinkScale, shrinkScale);
if (body[i].mass < 0.05) {
Matter.World.remove(engine.world, body[i]);
body.splice(i, 1);
m.fieldRange *= 0.8
// if (tech.isWormholeEnergy && m.energy < m.maxEnergy * 2) m.energy = m.maxEnergy * 2
if (tech.isWormholeEnergy) m.energy += 0.63
if (tech.isWormSpores) { //pandimensionalspermia
for (let i = 0, len = Math.ceil(3 * Math.random()); i < len; i++) {
b.spore(Vector.add(m.hole.pos1, Vector.rotate({
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), 15));
}
}
break
}
}
}
}
}
if (tech.isWormBullets) {
//teleport bullets
for (let i = 0, len = bullet.length; i < len; ++i) { //teleport bullets from hole1 to hole2
if (!bullet[i].botType && !bullet[i].isInHole) { //don't teleport bots
if (Vector.magnitude(Vector.sub(m.hole.pos1, bullet[i].position)) < m.fieldRange) { //find if bullet is touching hole1
Matter.Body.setPosition(bullet[i], Vector.add(m.hole.pos2, Vector.sub(m.hole.pos1, bullet[i].position)));
m.fieldRange += 5
bullet[i].isInHole = true
} else if (Vector.magnitude(Vector.sub(m.hole.pos2, bullet[i].position)) < m.fieldRange) { //find if bullet is touching hole1
Matter.Body.setPosition(bullet[i], Vector.add(m.hole.pos1, Vector.sub(m.hole.pos2, bullet[i].position)));
m.fieldRange += 5
bullet[i].isInHole = true
}
}
}
// mobs get pushed away
for (let i = 0, len = mob.length; i < len; i++) {
if (Vector.magnitude(Vector.sub(m.hole.pos1, mob[i].position)) < 200) {
const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos1, mob[i].position)), -0.07)
Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
}
if (Vector.magnitude(Vector.sub(m.hole.pos2, mob[i].position)) < 200) {
const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos2, mob[i].position)), -0.07)
Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
}
}
}
}
if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
const justPastMouse = Vector.add(Vector.mult(Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)), 50), simulation.mouseInGame)
const scale = 60
// console.log(Matter.Query.region(map, bounds))
if (m.hole.isReady &&
(
Matter.Query.region(map, {
min: {
x: simulation.mouseInGame.x - scale,
y: simulation.mouseInGame.y - scale
},
max: {
x: simulation.mouseInGame.x + scale,
y: simulation.mouseInGame.y + scale
}
}).length === 0 &&
Matter.Query.ray(map, m.pos, justPastMouse).length === 0
// Matter.Query.ray(map, m.pos, simulation.mouseInGame).length === 0 &&
// Matter.Query.ray(map, player.position, simulation.mouseInGame).length === 0 &&
// Matter.Query.ray(map, player.position, justPastMouse).length === 0
)
) {
const sub = Vector.sub(simulation.mouseInGame, m.pos)
const mag = Vector.magnitude(sub)
const drain = 0.03 + 0.005 * Math.sqrt(mag)
if (m.energy > drain && mag > 300) {
m.energy -= drain
m.hole.isReady = false;
m.fieldRange = 0
Matter.Body.setPosition(player, simulation.mouseInGame);
m.buttonCD_jump = 0 //this might fix a bug with jumping
const velocity = Vector.mult(Vector.normalise(sub), 18)
Matter.Body.setVelocity(player, {
x: velocity.x,
y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer
});
if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
// move bots to player
for (let i = 0; i < bullet.length; i++) {
if (bullet[i].botType) {
Matter.Body.setPosition(bullet[i], Vector.add(player.position, {
x: 250 * (Math.random() - 0.5),
y: 250 * (Math.random() - 0.5)
}));
Matter.Body.setVelocity(bullet[i], {
x: 0,
y: 0
});
}
}
//set holes
m.hole.isOn = true;
m.hole.pos1.x = m.pos.x
m.hole.pos1.y = m.pos.y
m.hole.pos2.x = player.position.x
m.hole.pos2.y = player.position.y
m.hole.angle = Math.atan2(sub.y, sub.x)
m.hole.unit = Vector.perp(Vector.normalise(sub))
if (tech.isWormholeDamage) {
who = Matter.Query.ray(mob, m.pos, simulation.mouseInGame, 100)
for (let i = 0; i < who.length; i++) {
if (who[i].body.alive) {
mobs.statusDoT(who[i].body, 1, 420)
mobs.statusStun(who[i].body, 360)
}
}
}
} else {
m.grabPowerUp();
}
} else {
m.grabPowerUp();
}
} else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
m.pickUp();
} else {
m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
m.hole.isReady = true;
}
m.drawFieldMeter()
},
}, },
], ],
isShipMode: false, isShipMode: false,

View File

@@ -2566,7 +2566,7 @@ const spawn = {
this.cycle = 0 this.cycle = 0
ctx.beginPath(); ctx.beginPath();
for (let i = 0; i < mob.length; i++) { for (let i = 0; i < mob.length; i++) {
if (!mob[i].isShielded && !mob[i].shield && mob[i].dropPowerUp) { if (!mob[i].isShielded && !mob[i].shield && mob[i].dropPowerUp && mob[i].alive) {
ctx.moveTo(this.position.x, this.position.y) ctx.moveTo(this.position.x, this.position.y)
ctx.lineTo(mob[i].position.x, mob[i].position.y) ctx.lineTo(mob[i].position.x, mob[i].position.y)

View File

@@ -124,7 +124,7 @@
damageFromTech() { damageFromTech() {
let dmg = m.fieldDamage let dmg = m.fieldDamage
if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555 if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555
if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.37 if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599
if (tech.isDamageAfterKill) dmg *= (m.lastKillCycle + 300 > m.cycle) ? 1.5 : 0.5 if (tech.isDamageAfterKill) dmg *= (m.lastKillCycle + 300 > m.cycle) ? 1.5 : 0.5
if (tech.isTechDamage) dmg *= 2 if (tech.isTechDamage) dmg *= 2
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance()) if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
@@ -270,8 +270,8 @@
} }
}, },
{ {
name: "gun technology", name: "gun sciences",
description: "</strong>double</strong> the <strong class='flicker'>frequency</strong> of finding <strong class='color-g'>gun</strong> <strong class='color-m'>tech</strong><br>spawn a <strong class='color-g'>gun</strong>", description: "spawn a <strong class='color-g'>gun</strong> and </strong>double</strong> the <strong class='flicker'>frequency</strong><br>of finding <strong class='color-m'>tech</strong> for a specific <strong class='color-g'>gun</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -358,14 +358,14 @@
}, },
{ {
name: "catabolism", name: "catabolism",
description: "when you <strong>fire</strong> while <strong>out</strong> of <strong class='color-g'>ammo</strong><br>gain <strong>3</strong> <strong class='color-g'>ammo</strong>, but lose <strong>5</strong> <strong class='color-h'>health</strong>", description: "when you <strong>fire</strong> while <strong>out</strong> of <strong class='color-g'>ammo</strong><br>gain <strong>4</strong> <strong class='color-g'>ammo</strong>, but lose <strong>5</strong> <strong class='color-h'>health</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
allowed() { allowed() {
return !tech.isEnergyHealth && !tech.isEnergyNoAmmo return m.harmReduction() < 1 && !tech.isEnergyHealth && !tech.isEnergyNoAmmo
}, },
requires: "not mass-energy equivalence<br>not exciton-lattice", requires: "some harm reduction, not mass-energy equivalence, exciton-lattice",
effect: () => { effect: () => {
tech.isAmmoFromHealth = true; tech.isAmmoFromHealth = true;
}, },
@@ -613,6 +613,58 @@
b.setFireCD(); b.setFireCD();
} }
}, },
{
name: "microstates",
description: "increase <strong class='color-d'>damage</strong> by <strong>4%</strong><br>for every <strong>10</strong> active <strong>bullets</strong>",
maxCount: 1,
count: 0,
frequency: 1,
allowed() {
return tech.isBulletsLastLonger > 1
},
requires: "anti-shear topology",
effect() {
tech.isDamageFromBulletCount = true
},
remove() {
tech.isDamageFromBulletCount = false
}
},
{
name: "anti-shear topology",
description: "some <strong>bullets</strong> last <strong>30% longer</strong><br><em style = 'font-size: 83%'>drones, spores, missiles, foam, wave, neutron</em>",
// isGunTech: true,
maxCount: 3,
count: 0,
frequency: 1,
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
},
requires: "drones, spores, missiles, foam<br>wave beam, neutron bomb",
effect() {
tech.isBulletsLastLonger += 0.3
},
remove() {
tech.isBulletsLastLonger = 1;
}
},
{
name: "radioactive contamination",
description: "after a mob or shield <strong>dies</strong>,<br> leftover <strong class='color-p'>radiation</strong> <strong>spreads</strong> to a nearby mob",
maxCount: 1,
count: 0,
frequency: 1,
allowed() {
return tech.isNailRadiation || tech.isWormholeDamage || tech.isNeutronBomb || tech.isExplodeRadio
},
requires: "radiation damage source",
effect() {
tech.isRadioactive = true
},
remove() {
tech.isRadioactive = false
}
},
{ {
name: "iridium-192", name: "iridium-192",
description: "<strong class='color-e'>explosions</strong> release <strong class='color-p'>gamma radiation</strong><br><strong>100%</strong> more <strong class='color-d'>damage</strong>, but over 4 seconds", description: "<strong class='color-e'>explosions</strong> release <strong class='color-p'>gamma radiation</strong><br><strong>100%</strong> more <strong class='color-d'>damage</strong>, but over 4 seconds",
@@ -699,6 +751,40 @@
tech.isImmuneExplosion = false; tech.isImmuneExplosion = false;
} }
}, },
{
name: "incendiary ammunition",
description: "<strong>shotgun</strong>, <strong>super balls</strong>, and <strong>drones</strong><br>are loaded with <strong class='color-e'>explosives</strong>",
maxCount: 1,
count: 0,
frequency: 1,
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
},
requires: "drones, super balls, shotgun",
effect() {
tech.isIncendiary = true
},
remove() {
tech.isIncendiary = false;
}
},
{
name: "fragmentation",
description: "some <strong class='color-e'>detonations</strong> and collisions eject <strong>nails</strong><br><em style = 'font-size: 90%'>blocks, rail gun, grenades, missiles, shotgun slugs</em>",
maxCount: 9,
count: 0,
frequency: 1,
allowed() {
return (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || tech.haveGunCheck("rail gun") || (tech.haveGunCheck("shotgun") && tech.isSlugShot) || tech.throwChargeRate > 1
},
requires: "grenades, missiles, rail gun, shotgun slugs, or mass driver",
effect() {
tech.fragments++
},
remove() {
tech.fragments = 0
}
},
{ {
name: "thermal runaway", name: "thermal runaway",
description: "mobs <strong class='color-e'>explode</strong> when they <strong>die</strong><br><em>be careful</em>", description: "mobs <strong class='color-e'>explode</strong> when they <strong>die</strong><br><em>be careful</em>",
@@ -716,6 +802,23 @@
tech.isExplodeMob = false; tech.isExplodeMob = false;
} }
}, },
{
name: "impact shear",
description: "mobs release a <strong>nail</strong> when they <strong>die</strong><br><em>nails target nearby mobs</em>",
maxCount: 9,
count: 0,
frequency: 1,
allowed() {
return !tech.sporesOnDeath && !tech.isExplodeMob && !tech.isBotSpawner
},
requires: "no other mob death tech",
effect: () => {
tech.nailsDeathMob++
},
remove() {
tech.nailsDeathMob = 0;
}
},
{ {
name: "zoospore vector", name: "zoospore vector",
description: "mobs produce <strong class='color-p' style='letter-spacing: 2px;'>spores</strong> when they <strong>die</strong><br><strong>9%</strong> chance", description: "mobs produce <strong class='color-p' style='letter-spacing: 2px;'>spores</strong> when they <strong>die</strong><br><strong>9%</strong> chance",
@@ -736,23 +839,6 @@
tech.sporesOnDeath = 0; tech.sporesOnDeath = 0;
} }
}, },
{
name: "impact shear",
description: "mobs release a <strong>nail</strong> when they <strong>die</strong><br><em>nails target nearby mobs</em>",
maxCount: 9,
count: 0,
frequency: 1,
allowed() {
return !tech.sporesOnDeath && !tech.isExplodeMob && !tech.isBotSpawner
},
requires: "no other mob death tech",
effect: () => {
tech.nailsDeathMob++
},
remove() {
tech.nailsDeathMob = 0;
}
},
{ {
name: "reaction inhibitor", name: "reaction inhibitor",
description: "mobs spawn with <strong>11%</strong> less <strong>health</strong>", description: "mobs spawn with <strong>11%</strong> less <strong>health</strong>",
@@ -1492,7 +1578,25 @@
remove() { remove() {
tech.isFreezeHarmImmune = false; tech.isFreezeHarmImmune = false;
} }
}, { },
{
name: "superfluidity",
description: "<strong class='color-s'>freeze</strong> effects are applied to a small area",
maxCount: 1,
count: 0,
frequency: 1,
allowed() {
return tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField
},
requires: "a localized freeze effect",
effect() {
tech.isAoESlow = true
},
remove() {
tech.isAoESlow = false
}
},
{
name: "ablative drones", name: "ablative drones",
description: "rebuild your broken parts as <strong>drones</strong><br>chance to occur after receiving <strong class='color-harm'>harm</strong>", description: "rebuild your broken parts as <strong>drones</strong><br>chance to occur after receiving <strong class='color-harm'>harm</strong>",
maxCount: 1, maxCount: 1,
@@ -2025,7 +2129,7 @@
frequency: 1, frequency: 1,
isHealTech: true, isHealTech: true,
allowed() { allowed() {
return (m.health < 0.75 || build.isExperimentSelection) && !tech.isEnergyHealth return ((m.health / m.maxHealth) < 0.7 || build.isExperimentSelection) && !tech.isEnergyHealth
}, },
requires: "not mass-energy equivalence", requires: "not mass-energy equivalence",
effect() { effect() {
@@ -2036,14 +2140,14 @@
} }
}, },
{ {
name: "healing technology", name: "maintenance",
description: "</strong>double</strong> the <strong class='flicker'>frequency</strong> of finding <strong class='color-h'>healing</strong> <strong class='color-m'>tech</strong><br>spawn <strong>12</strong> <strong class='color-h'>heals</strong>", description: "</strong>double</strong> the <strong class='flicker'>frequency</strong> of finding <strong class='color-h'>healing</strong> <strong class='color-m'>tech</strong><br>spawn <strong>12</strong> <strong class='color-h'>heals</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
isNonRefundable: true, isNonRefundable: true,
allowed() { allowed() {
return true return ((m.health / m.maxHealth) < 0.7 || build.isExperimentSelection)
}, },
requires: "", requires: "",
effect() { effect() {
@@ -2118,14 +2222,14 @@
} }
}, { }, {
name: "quantum immortality", name: "quantum immortality",
description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>16%</strong>", //spawn <strong>4</strong> <strong class='color-r'>research</strong> description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>23%</strong>", //spawn <strong>4</strong> <strong class='color-r'>research</strong>
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
allowed() { allowed() {
return !tech.isSwitchReality && !tech.isResearchReality return !tech.isSwitchReality && !tech.isResearchReality && tech.isDeathAvoid
}, },
requires: "not many-worlds, perturbation theory", requires: "anthropic principle, not many-worlds, perturbation theory",
effect() { effect() {
tech.isImmortal = true; tech.isImmortal = true;
// for (let i = 0; i < 4; i++) powerUps.spawn(m.pos.x + Math.random() * 10, m.pos.y + Math.random() * 10, "research", false); // for (let i = 0; i < 4; i++) powerUps.spawn(m.pos.x + Math.random() * 10, m.pos.y + Math.random() * 10, "research", false);
@@ -2156,9 +2260,9 @@
count: 0, count: 0,
frequency: 1, frequency: 1,
allowed() { allowed() {
return !tech.isImmortal && !tech.isSwitchReality && (powerUps.research.count > 2 || build.isExperimentSelection) return !tech.isImmortal && !tech.isSwitchReality
}, },
requires: "at least 2 research, not quantum immortality, many-worlds", requires: "not quantum immortality, many-worlds",
effect() { effect() {
tech.isResearchReality = true; tech.isResearchReality = true;
for (let i = 0; i < 11; i++) powerUps.spawn(m.pos.x + Math.random() * 10, m.pos.y + Math.random() * 10, "research", false); for (let i = 0; i < 11; i++) powerUps.spawn(m.pos.x + Math.random() * 10, m.pos.y + Math.random() * 10, "research", false);
@@ -2166,22 +2270,6 @@
remove() { remove() {
tech.isResearchReality = false; tech.isResearchReality = false;
} }
}, {
name: "renormalization",
description: "using a <strong class='color-r'>research</strong> for <strong>any</strong> purpose<br>has a <strong>37%</strong> chance to spawn a <strong class='color-r'>research</strong>",
maxCount: 1,
count: 0,
frequency: 1,
allowed() {
return (powerUps.research.count > 2 || build.isExperimentSelection) && !tech.isSuperDeterminism && !tech.isRerollHaste
},
requires: "not superdeterminism or Ψ(t) collapse<br>at least 3 research",
effect() {
tech.renormalization = true;
},
remove() {
tech.renormalization = false;
}
}, { }, {
name: "decoherence", name: "decoherence",
description: "<strong class='color-r'>researched</strong> or <strong>canceled</strong> <strong class='color-m'>tech</strong> won't <strong>reoccur</strong> <br>spawn <strong>5</strong> <strong class='color-r'>research</strong>", description: "<strong class='color-r'>researched</strong> or <strong>canceled</strong> <strong class='color-m'>tech</strong> won't <strong>reoccur</strong> <br>spawn <strong>5</strong> <strong class='color-r'>research</strong>",
@@ -2200,6 +2288,22 @@
tech.isBanish = false tech.isBanish = false
powerUps.tech.banishLog = [] //reset banish log powerUps.tech.banishLog = [] //reset banish log
} }
}, {
name: "renormalization",
description: "using a <strong class='color-r'>research</strong> for <strong>any</strong> purpose<br>has a <strong>37%</strong> chance to spawn a <strong class='color-r'>research</strong>",
maxCount: 1,
count: 0,
frequency: 1,
allowed() {
return (powerUps.research.count > 3 || build.isExperimentSelection) && !tech.isSuperDeterminism && !tech.isRerollHaste
},
requires: "not superdeterminism or Ψ(t) collapse<br>at least 4 research",
effect() {
tech.renormalization = true;
},
remove() {
tech.renormalization = false;
}
}, { }, {
name: "perturbation theory", name: "perturbation theory",
description: "<strong>66%</strong> decreased <strong><em>delay</em></strong> after firing<br>when you have no <strong class='color-r'>research</strong> in your inventory", description: "<strong>66%</strong> decreased <strong><em>delay</em></strong> after firing<br>when you have no <strong class='color-r'>research</strong> in your inventory",
@@ -2319,7 +2423,7 @@
}, },
{ {
name: "meta-analysis", name: "meta-analysis",
description: "if you choose a <strong>junk</strong> <strong class='color-m'>tech</strong> you instead get a <br>random non-junk <strong class='color-m'>tech</strong> and spawn <strong>2</strong> <strong class='color-r'>research</strong>", description: "if you choose a <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> you instead get a <br>random normal <strong class='color-m'>tech</strong> and <strong>2</strong> <strong class='color-r'>research</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
@@ -2336,7 +2440,7 @@
}, },
{ {
name: "replication", name: "replication",
description: "<strong>7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>add <strong>12</strong> junk <strong class='color-m'>tech</strong> to the potential pool", description: "<strong>7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>add <strong>12</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2378,14 +2482,14 @@
}, },
{ {
name: "futures exchange", name: "futures exchange",
description: "clicking <strong style = 'font-size:150%;'>×</strong> to cancel a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>adds <strong>4.5%</strong> power up <strong class='color-dup'>duplication</strong> chance", description: "clicking <strong style = 'font-size:150%;'>×</strong> to <strong>cancel</strong> a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>adds <strong>4.5%</strong> power up <strong class='color-dup'>duplication</strong> chance",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
allowed() { allowed() {
return tech.duplicationChance() < 1 && !tech.isDeterminism && (level.levelsCleared < 5 || Math.random() < 0.5) return tech.duplicationChance() < 1 && !tech.isDeterminism && level.levelsCleared < 5
}, },
requires: "below 100% duplication chance, not determinism", requires: "below 100% duplication chance, below level 5, not determinism",
effect() { effect() {
tech.isCancelDuplication = true tech.isCancelDuplication = true
tech.cancelCount = 0 tech.cancelCount = 0
@@ -2546,7 +2650,7 @@
} }
}, { }, {
name: "dark patterns", name: "dark patterns",
description: "reduce combat <strong>difficulty</strong> by <strong>1 level</strong><br>add <strong>18</strong> junk <strong class='color-m'>tech</strong> to the potential pool", description: "reduce combat <strong>difficulty</strong> by <strong>1 level</strong><br>add <strong>18</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2584,7 +2688,7 @@
} }
}, },
{ {
name: "field technology", name: "vector fields",
description: "</strong>double</strong> the <strong class='flicker'>frequency</strong> of finding <strong class='color-f'>field</strong> <strong class='color-m'>tech</strong><br>spawn a <strong class='color-f'>field</strong>", description: "</strong>double</strong> the <strong class='flicker'>frequency</strong> of finding <strong class='color-f'>field</strong> <strong class='color-m'>tech</strong><br>spawn a <strong class='color-f'>field</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -2646,7 +2750,7 @@
} }
}, { }, {
name: "determinism", name: "determinism",
description: "spawn <strong>5</strong> <strong class='color-m'>tech</strong><br><strong class='color-m'>tech</strong>, <strong class='color-f'>fields</strong>, and <strong class='color-g'>guns</strong> have only <strong>1 choice</strong>", description: "spawn <strong>5</strong> <strong class='color-m'>tech</strong>, but you have <strong>no cancel</strong><br>and <strong>1 choice</strong> for <strong class='color-m'>tech</strong>, <strong class='color-f'>fields</strong>, and <strong class='color-g'>guns</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2666,7 +2770,7 @@
} }
}, { }, {
name: "superdeterminism", name: "superdeterminism",
description: "spawn <strong>7</strong> <strong class='color-m'>tech</strong><br><strong class='color-r'>research</strong>, <strong class='color-g'>guns</strong>, and <strong class='color-f'>fields</strong> no longer <strong>spawn</strong>", description: "spawn <strong>5</strong> <strong class='color-m'>tech</strong><br><strong class='color-r'>research</strong>, <strong class='color-g'>guns</strong>, and <strong class='color-f'>fields</strong> no longer <strong>spawn</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 3, frequency: 3,
@@ -2732,108 +2836,6 @@
tech.isRewindGun = false tech.isRewindGun = false
} }
} }
}, {
name: "incendiary ammunition",
description: "<strong>shotgun</strong>, <strong>super balls</strong>, and <strong>drones</strong><br>are loaded with <strong class='color-e'>explosives</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 1,
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
},
requires: "drones, super balls, shotgun",
effect() {
tech.isIncendiary = true
},
remove() {
tech.isIncendiary = false;
}
}, {
name: "fragmentation",
description: "some <strong class='color-e'>detonations</strong> and collisions eject <strong>nails</strong><br><em style = 'font-size: 90%'>blocks, rail gun, grenades, missiles, shotgun slugs</em>",
isGunTech: true,
maxCount: 9,
count: 0,
frequency: 1,
allowed() {
return (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || tech.haveGunCheck("rail gun") || (tech.haveGunCheck("shotgun") && tech.isSlugShot) || tech.throwChargeRate > 1
},
requires: "grenades, missiles, rail gun, shotgun slugs, or mass driver",
effect() {
tech.fragments++
},
remove() {
tech.fragments = 0
}
}, {
name: "superfluidity",
description: "<strong class='color-s'>freeze</strong> effects are applied to a small area",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 1,
allowed() {
return tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField
},
requires: "a freeze effect",
effect() {
tech.isAoESlow = true
},
remove() {
tech.isAoESlow = false
}
}, {
name: "radioactive contamination",
description: "after a mob or shield <strong>dies</strong>,<br> leftover <strong class='color-p'>radiation</strong> <strong>spreads</strong> to a nearby mob",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 1,
allowed() {
return tech.isNailRadiation || tech.isWormholeDamage || tech.isNeutronBomb || tech.isExplodeRadio
},
requires: "radiation damage source",
effect() {
tech.isRadioactive = true
},
remove() {
tech.isRadioactive = false
}
}, {
name: "anti-shear topology",
description: "some <strong>bullets</strong> last <strong>30% longer</strong><br><em style = 'font-size: 83%'>drones, spores, missiles, foam, wave, neutron</em>",
isGunTech: true,
maxCount: 3,
count: 0,
frequency: 1,
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
},
requires: "drones, spores, missiles, foam<br>wave beam, neutron bomb",
effect() {
tech.isBulletsLastLonger += 0.3
},
remove() {
tech.isBulletsLastLonger = 1;
}
}, {
name: "microstates",
description: "increase <strong class='color-d'>damage</strong> by <strong>4%</strong><br>for every <strong>10</strong> active <strong>bullets</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 1,
allowed() {
return tech.isBulletsLastLonger > 1
},
requires: "anti-shear topology",
effect() {
tech.isDamageFromBulletCount = true
},
remove() {
tech.isDamageFromBulletCount = false
}
}, { }, {
name: "needle gun", name: "needle gun",
description: "<strong>nail gun</strong> fires <strong>3</strong> mob piercing <strong>needles</strong><br>requires <strong>3</strong> times more <strong class='color-g'>ammo</strong>", description: "<strong>nail gun</strong> fires <strong>3</strong> mob piercing <strong>needles</strong><br>requires <strong>3</strong> times more <strong class='color-g'>ammo</strong>",
@@ -2872,7 +2874,7 @@
} }
} }
}, { }, {
name: "ceramic needle", name: "ceramic needles",
description: `your <strong>needles</strong> pierce <strong>shields</strong><br>directly <strong class='color-d'>damaging</strong> shielded mobs`, description: `your <strong>needles</strong> pierce <strong>shields</strong><br>directly <strong class='color-d'>damaging</strong> shielded mobs`,
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
@@ -3600,6 +3602,31 @@
remove() { remove() {
tech.isDroneGrab = false tech.isDroneGrab = false
} }
}, {
name: "planned obsolescence",
description: "reduce all <strong>drone</strong> production costs by <strong>300%</strong><br>reduce the average <strong>drone</strong> lifetime by <strong>53%</strong>",
isGunTech: true,
maxCount: 3,
count: 0,
frequency: 1,
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.47, this.count)
tech.droneEnergyReduction = Math.pow(0.33, 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: "necrophoresis", 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>", description: "<strong>foam</strong> bubbles grow and split into 3 <strong>copies</strong><br> when the mob they are stuck to <strong>dies</strong>",
@@ -4845,7 +4872,7 @@
remove() {} remove() {}
}, { }, {
name: "defragment", name: "defragment",
description: "set the <strong class='flicker'>frequency</strong> of finding junk <strong class='color-m'>tech</strong> to zero", description: "set the <strong class='flicker'>frequency</strong> of finding <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to zero",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 0, frequency: 0,
@@ -5021,7 +5048,7 @@
remove() {} remove() {}
}, { }, {
name: "expert system", name: "expert system",
description: "spawn a <strong class='color-m'>tech</strong> power up<br>add <strong>64</strong> junk <strong class='color-m'>tech</strong> to the potential pool", description: "spawn a <strong class='color-m'>tech</strong> power up<br>add <strong>64</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 0, frequency: 0,
@@ -5795,5 +5822,7 @@
isFlipFlopDamage: null, isFlipFlopDamage: null,
isFlipFlopEnergy: null, isFlipFlopEnergy: null,
isMetaAnalysis: null, isMetaAnalysis: null,
isFoamAttract: null isFoamAttract: null,
droneCycleReduction: null,
droneEnergyReduction: null
} }

View File

@@ -604,6 +604,13 @@ summary {
font-weight: 100; font-weight: 100;
} }
.color-j {
letter-spacing: 1px;
/* font-weight: 100; */
font-family: Lucida Console, Courier, monospace;
/* transform: rotate(-90deg); */
}
/* .color-rewind { /* .color-rewind {
background-image: linear-gradient(to left, #fff, #bbb); background-image: linear-gradient(to left, #fff, #bbb);
border-radius: 5px; border-radius: 5px;

View File

@@ -1,16 +1,19 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** NEXT PATCH ********************************************************
tech: electrostatic induction - foam bullets are attracted to nearby mobs bug fixes
strong anthropic principle does 0.03599% more damage
spores can stick to rotating blocks now
probably fixed the new wormhole field while targeting a block -> crouch lock bug
ceramic needles now correctly bypass shields
portals on perplex map, now remove blocks that fall in needles fire 3 at a time with a short delay and no spread
new community map! coliseum by iNoobBoi
a few more tech can be refunded properly tech: planned obsolescence - 3x drone ammo, 1/3 drone nano-scale energy cost, but 53% reduced drone life span
nonRefundable tech don't show up in the list of tech you have
******************************************************** BUGS ******************************************************** ******************************************************** BUGS ********************************************************
fix issue where you have to press z once to get copy to work for simulation.enableConstructMode() you have to press z once to get copy to work for simulation.enableConstructMode() sometimes
not sure how to reproduce, but it happens often on the first draw
mouse event e.which is deprecated mouse event e.which is deprecated
@@ -22,9 +25,6 @@ fix door.isOpen actually meaning isClosed?
wasn't able to understand bug after extensive testing wasn't able to understand bug after extensive testing
had tech: complex spin statistics had tech: complex spin statistics
(a few times) wormhole teleportation can leave the player in a stuck jump state
seems to be easily fixed, by porting, firing or something
(always) make it so that when you are immune to harm you can either jump on mobs or you pass through them (always) make it so that when you are immune to harm you can either jump on mobs or you pass through them
(always) is there a way to check if the player is stuck inside the map or block (always) is there a way to check if the player is stuck inside the map or block
@@ -41,6 +41,20 @@ fix door.isOpen actually meaning isClosed?
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
mob vision: look at player history
build a new type of attraction for mobs
if mobs can't see player, they check to see if they can see where the player was in the history
if mobs can't see player, they could check to see if they can find player in the past
https://abitawake.com/news/articles/enemy-ai-chasing-a-player-without-navigation2d-or-a-star-pathfinding
tech: chitin - take 50% less damage, reduce harm reduction by 5% after each collision
Mob: "Tentacle": Sits on wall. Is a black blob. When you get near it, reaches out and grabs you, similar to wires. Does not deal damage.
maybe it could be immune to damage? but it is spawned by an actual mob
wormhole, or CPT tech: after taking damage teleport in direction of mouse
after collision
mob sniper: draw aim graphics before fire mob sniper: draw aim graphics before fire
tech laser: photon - laser, but it can only move 100 pixels a cycle tech laser: photon - laser, but it can only move 100 pixels a cycle
@@ -153,12 +167,6 @@ tech pilot wave: antigravity - blocks have no gravity for a few seconds after ex
maybe they bounce too? maybe they bounce too?
maybe they explode? maybe they explode?
mob vision: look at player history
build a new type of attraction for mobs
if mobs can't see player, they check to see if they can see where the player was in the history
if mobs can't see player, they could check to see if they can find player in the past
https://abitawake.com/news/articles/enemy-ai-chasing-a-player-without-navigation2d-or-a-star-pathfinding
wormhole - make it clear when the wormhole can and can't teleport to a location before the player clicks wormhole - make it clear when the wormhole can and can't teleport to a location before the player clicks
flavor - your bullets destroy blocks flavor - your bullets destroy blocks