diff --git a/js/bullets.js b/js/bullets.js
index b6dac44..b0b69d0 100644
--- a/js/bullets.js
+++ b/js/bullets.js
@@ -56,6 +56,7 @@ const b = {
isModSporeField: null,
isModFlechetteMultiShot: null,
isModMineAmmoBack: null,
+ isModRailNails: null,
modOnHealthChange() { //used with acid mod
if (b.isModAcidDmg && mech.health > 0.8) {
game.playerDmgColor = "rgba(0,80,80,0.9)"
@@ -148,38 +149,6 @@ const b = {
b.isModLowHealthDmg = false;
}
},
- {
- name: "reaction inhibitor",
- description: "mobs die if their life goes below 12%",
- maxCount: 1,
- count: 0,
- allowed() {
- return true
- },
- requires: "",
- effect: () => {
- b.modMobDieAtHealth = 0.15
- },
- remove() {
- b.modMobDieAtHealth = 0.05;
- }
- },
- {
- name: "thermal runaway",
- description: "mobs explode when they die",
- maxCount: 1,
- count: 0,
- allowed() {
- return b.modMobDieAtHealth > 0.05
- },
- requires: "reaction inhibitor",
- effect: () => {
- b.isModExplodeMob = true;
- },
- remove() {
- b.isModExplodeMob = false;
- }
- },
{
name: "high explosives",
description: "explosions do +20% more damage
explosive area is +44% larger",
@@ -245,42 +214,6 @@ const b = {
b.modNoAmmo = 0;
}
},
- {
- name: "Lorentzian topology",
- description: "your bullets last +33% longer",
- maxCount: 3,
- count: 0,
- allowed() {
- return mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" || b.haveGunCheck("spores") || b.haveGunCheck("drones") || b.haveGunCheck("super balls") || b.haveGunCheck("foam") || b.haveGunCheck("wave beam")
- },
- requires: "drones, spores, super balls,
foam, or wave beam",
- effect() {
- b.isModBulletsLastLonger += 0.33
- },
- remove() {
- b.isModBulletsLastLonger = 1;
- }
- },
-
- {
- name: "zoospore vector",
- description: "enemies discharge spores on death
+11% chance",
- maxCount: 9,
- count: 0,
- allowed() {
- return true
- },
- requires: "",
- effect() {
- b.modSporesOnDeath += 0.11;
- for (let i = 0; i < 10; i++) {
- b.spore(player)
- }
- },
- remove() {
- b.modSporesOnDeath = 0;
- }
- },
{
name: "laser-bot",
description: "a bot defends the space around you
uses a short range laser that drains energy",
@@ -335,35 +268,71 @@ const b = {
}
},
{
- name: "bremsstrahlung radiation",
- description: "when your field blocks it also does damage",
+ name: "Lorentzian topology",
+ description: "your bullets last +33% longer",
+ maxCount: 3,
+ count: 0,
+ allowed() {
+ return mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" || b.haveGunCheck("spores") || b.haveGunCheck("drones") || b.haveGunCheck("super balls") || b.haveGunCheck("foam") || b.haveGunCheck("wave beam")
+ },
+ requires: "drones, spores, super balls,
foam, or wave beam",
+ effect() {
+ b.isModBulletsLastLonger += 0.33
+ },
+ remove() {
+ b.isModBulletsLastLonger = 1;
+ }
+ },
+
+ {
+ name: "zoospore vector",
+ description: "enemies discharge spores on death
+11% chance",
maxCount: 9,
count: 0,
allowed() {
- return mech.fieldUpgrades[mech.fieldMode].name !== "time dilation field" && mech.fieldUpgrades[mech.fieldMode].name !== "phase decoherence field"
+ return true
},
- requires: "not time dilation field
requires not phase decoherence field",
+ requires: "",
effect() {
- b.modBlockDmg += 0.7 //if you change this value also update the for loop in the electricity graphics in mech.pushMass
+ b.modSporesOnDeath += 0.11;
+ for (let i = 0; i < 10; i++) {
+ b.spore(player)
+ }
},
remove() {
- b.modBlockDmg = 0;
+ b.modSporesOnDeath = 0;
}
},
{
- name: "field superposition",
- description: "increase your field radius by 40%",
+ name: "reaction inhibitor",
+ description: "mobs die if their life goes below 12%",
maxCount: 1,
count: 0,
allowed() {
- return mech.fieldUpgrades[mech.fieldMode].name !== "time dilation field" && mech.fieldUpgrades[mech.fieldMode].name !== "phase decoherence field"
+ return true
},
- requires: "not time dilation field
requires not phase decoherence field",
- effect() {
- mech.fieldRange = 175 * 1.4
+ requires: "",
+ effect: () => {
+ b.modMobDieAtHealth = 0.15
},
remove() {
- mech.fieldRange = 175;
+ b.modMobDieAtHealth = 0.05;
+ }
+ },
+ {
+ name: "thermal runaway",
+ description: "mobs explode when they die",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return b.modMobDieAtHealth > 0.05
+ },
+ requires: "reaction inhibitor",
+ effect: () => {
+ b.isModExplodeMob = true;
+ },
+ remove() {
+ b.isModExplodeMob = false;
}
},
{
@@ -550,6 +519,38 @@ const b = {
b.isModPiezo = false;
}
},
+ {
+ name: "bremsstrahlung radiation",
+ description: "when your field blocks it also does damage",
+ maxCount: 9,
+ count: 0,
+ allowed() {
+ return mech.fieldUpgrades[mech.fieldMode].name !== "time dilation field" && mech.fieldUpgrades[mech.fieldMode].name !== "phase decoherence field"
+ },
+ requires: "not time dilation field
requires not phase decoherence field",
+ effect() {
+ b.modBlockDmg += 0.7 //if you change this value also update the for loop in the electricity graphics in mech.pushMass
+ },
+ remove() {
+ b.modBlockDmg = 0;
+ }
+ },
+ {
+ name: "field superposition",
+ description: "increase your field radius by 40%",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return mech.fieldUpgrades[mech.fieldMode].name !== "time dilation field" && mech.fieldUpgrades[mech.fieldMode].name !== "phase decoherence field"
+ },
+ requires: "not time dilation field
requires not phase decoherence field",
+ effect() {
+ mech.fieldRange = 175 * 1.4
+ },
+ remove() {
+ mech.fieldRange = 175;
+ }
+ },
{
name: "energy conservation",
description: "gain energy proportional to damage done",
@@ -744,38 +745,8 @@ const b = {
//nothing to undo
}
},
- {
- name: "redundant systems",
- description: "drone collisions no longer reduce their lifespan",
- maxCount: 1,
- count: 0,
- allowed() {
- return b.haveGunCheck("drones") || (mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !b.isModSporeField)
- },
- requires: "drones",
- effect() {
- b.isModDroneCollide = true
- },
- remove() {
- b.isModDroneCollide = true;
- }
- },
- {
- name: "tinsellated flagella",
- description: "your spores accelerate 33% faster",
- maxCount: 1,
- count: 0,
- allowed() {
- return b.haveGunCheck("spores") || b.modSporesOnDeath > 0 || b.isModStomp || b.isModSporeField
- },
- requires: "spores",
- effect() {
- b.isModFastSpores = true
- },
- remove() {
- b.isModFastSpores = false
- }
- },
+
+
{
name: "crystal nucleation",
description: "fire crystals formed from the air
your minigun no longer requires ammo",
@@ -805,97 +776,6 @@ const b = {
break;
}
}
-
- }
- },
- {
- name: "super duper",
- description: "you fire +1 additional super ball",
- maxCount: 9,
- count: 0,
- allowed() {
- return b.haveGunCheck("super balls")
- },
- requires: "super balls",
- effect() {
- b.modSuperBallNumber++
- },
- remove() {
- b.modSuperBallNumber = 4;
- }
- },
- {
- name: "specular reflection",
- description: "your laser gains +1 reflection
+30% laser damage and energy drain",
- maxCount: 9,
- count: 0,
- allowed() {
- return b.haveGunCheck("laser")
- },
- requires: "laser",
- effect() {
- b.modLaserReflections++;
- b.modLaserDamage += 0.015; //base is 0.05
- b.modLaserFieldDrain += 0.0006 //base is 0.002
- },
- remove() {
- b.modLaserReflections = 2;
- b.modLaserDamage = 0.05;
- b.modLaserFieldDrain = 0.002;
- }
- },
- {
- name: "optimized shell packing",
- description: "flak ammo drops contain 2x more shells",
- maxCount: 3,
- count: 0,
- allowed() {
- return b.haveGunCheck("flak")
- },
- requires: "flak",
- effect() {
- for (i = 0, len = b.guns.length; i < len; i++) { //find which gun is flak
- if (b.guns[i].name === "flak") b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * (2 + this.count);
- }
- },
- remove() {
- for (i = 0, len = b.guns.length; i < len; i++) { //find which gun is flak
- if (b.guns[i].name === "flak") b.guns[i].ammoPack = b.guns[i].defaultAmmoPack;
- }
- }
- },
- {
- name: "foam stabilization",
- description: "foam can stick to shields",
- maxCount: 1,
- count: 0,
- allowed() {
- return b.haveGunCheck("foam")
- },
- requires: "foam",
- effect() {
- b.isModFoamShieldHit = true;
- },
- remove() {
- b.isModFoamShieldHit = false;
- }
- },
- {
- name: "wave phase velocity",
- description: "your wave beam propagates faster through solids",
- maxCount: 1,
- count: 0,
- allowed() {
- return b.haveGunCheck("wave beam")
- },
- requires: "wave beam",
- effect() {
- b.modWaveSpeedMap = 3
- b.modWaveSpeedBody = 1.9
- },
- remove() {
- b.modWaveSpeedMap = 0.08
- b.modWaveSpeedBody = 0.25
}
},
{
@@ -914,6 +794,22 @@ const b = {
b.isModShotgunImmune = false;
}
},
+ {
+ name: "super duper",
+ description: "you fire +1 additional super ball",
+ maxCount: 9,
+ count: 0,
+ allowed() {
+ return b.haveGunCheck("super balls")
+ },
+ requires: "super balls",
+ effect() {
+ b.modSuperBallNumber++
+ },
+ remove() {
+ b.modSuperBallNumber = 4;
+ }
+ },
{
name: "fléchettes cartridges",
description: "fléchettes release three needles in each shot
ammo cost are increases by 3x",
@@ -946,6 +842,44 @@ const b = {
game.updateGunHUD();
}
},
+ {
+ name: "wave phase velocity",
+ description: "your wave beam propagates faster through solids",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return b.haveGunCheck("wave beam")
+ },
+ requires: "wave beam",
+ effect() {
+ b.modWaveSpeedMap = 3
+ b.modWaveSpeedBody = 1.9
+ },
+ remove() {
+ b.modWaveSpeedMap = 0.08
+ b.modWaveSpeedBody = 0.25
+ }
+ },
+ {
+ name: "optimized shell packing",
+ description: "flak ammo drops contain 2x more shells",
+ maxCount: 3,
+ count: 0,
+ allowed() {
+ return b.haveGunCheck("flak")
+ },
+ requires: "flak",
+ effect() {
+ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun is flak
+ if (b.guns[i].name === "flak") b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * (2 + this.count);
+ }
+ },
+ remove() {
+ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun is flak
+ if (b.guns[i].name === "flak") b.guns[i].ammoPack = b.guns[i].defaultAmmoPack;
+ }
+ }
+ },
{
name: "mine reclamation",
description: "ammo from undetonated mines is returned
at the end of a level or after 2000 second",
@@ -962,6 +896,90 @@ const b = {
b.isModMineAmmoBack = false;
}
},
+ {
+ name: "tinsellated flagella",
+ description: "your spores accelerate 33% faster",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return b.haveGunCheck("spores") || b.modSporesOnDeath > 0 || b.isModStomp || b.isModSporeField
+ },
+ requires: "spores",
+ effect() {
+ b.isModFastSpores = true
+ },
+ remove() {
+ b.isModFastSpores = false
+ }
+ },
+ {
+ name: "redundant systems",
+ description: "drone collisions no longer reduce their lifespan",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return b.haveGunCheck("drones") || (mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !b.isModSporeField)
+ },
+ requires: "drones",
+ effect() {
+ b.isModDroneCollide = true
+ },
+ remove() {
+ b.isModDroneCollide = true;
+ }
+ },
+ {
+ name: "foam stabilization",
+ description: "foam can stick to shields",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return b.haveGunCheck("foam")
+ },
+ requires: "foam",
+ effect() {
+ b.isModFoamShieldHit = true;
+ },
+ remove() {
+ b.isModFoamShieldHit = false;
+ }
+ },
+ {
+ name: "stress fragmentation",
+ description: "rail gun fragments into nails after hitting mobs at high speeds",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return b.haveGunCheck("rail gun")
+ },
+ requires: "rail gun",
+ effect() {
+ b.isModRailNails = true;
+ },
+ remove() {
+ b.isModRailNails = false;
+ }
+ },
+ {
+ name: "specular reflection",
+ description: "your laser gains +1 reflection
+30% laser damage and energy drain",
+ maxCount: 9,
+ count: 0,
+ allowed() {
+ return b.haveGunCheck("laser")
+ },
+ requires: "laser",
+ effect() {
+ b.modLaserReflections++;
+ b.modLaserDamage += 0.015; //base is 0.05
+ b.modLaserFieldDrain += 0.0006 //base is 0.002
+ },
+ remove() {
+ b.modLaserReflections = 2;
+ b.modLaserDamage = 0.05;
+ b.modLaserFieldDrain = 0.002;
+ }
+ },
{
name: "perfect diamagnetism",
description: "when blocking with the basic field emitter
gain energy instead losing it",
@@ -2532,6 +2550,37 @@ const b = {
Matter.Body.setDensity(this, 0.001);
// this.endCycle = 0;
}
+ if (b.isModRailNails && this.speed > 10) {
+ const targets = [] //target nearby mobs
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (mob[i].dropPowerUp) {
+ const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
+ if (dist < 1000000 && //1000*1000
+ Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
+ Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
+ targets.push(Vector.add(mob[i].position, Vector.mult(mob[i].velocity, Math.sqrt(dist) / 60))) //predict where the mob will be in a few cycles
+ }
+ }
+ }
+ for (let i = 0; i < this.speed - 10; i++) {
+ const speed = 50 + 10 * Math.random()
+ if (targets.length > 0) { // aim near a random target in array
+ const index = Math.floor(Math.random() * targets.length)
+ const SPREAD = 150 / targets.length
+ const WHERE = {
+ x: targets[index].x + SPREAD * (Math.random() - 0.5),
+ y: targets[index].y + SPREAD * (Math.random() - 0.5)
+ }
+ b.nail(this.position, Vector.mult(Vector.normalise(Vector.sub(WHERE, this.position)), speed), 1.1)
+ } else { // aim in random direction
+ const ANGLE = 2 * Math.PI * Math.random()
+ b.nail(this.position, {
+ x: speed * Math.cos(ANGLE),
+ y: speed * Math.sin(ANGLE)
+ })
+ }
+ }
+ }
}, //this.endCycle = 0 //triggers despawn
onEnd() {}
diff --git a/js/level.js b/js/level.js
index 52e47d9..17ac7fd 100644
--- a/js/level.js
+++ b/js/level.js
@@ -14,13 +14,9 @@ const level = {
start() {
if (level.levelsCleared === 0) {
// level.difficultyIncrease(9)
- // b.giveGuns("fléchettes")
+ // b.giveGuns("rail gun")
// mech.setField("nano-scale manufacturing")
- // for (let i = 0; i < 9; i++) {
// b.giveMod("fléchettes multishot");
- // b.giveMod("basidio-stomp");
- // b.giveMod("acute stress response");
- // }
level.intro(); //starting level
// level.testingMap();