diff --git a/js/bullet.js b/js/bullet.js
index 5557896..a1516d0 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -467,17 +467,18 @@ const b = {
Matter.Body.setVelocity(bullet[bIndex], velocity);
World.add(engine.world, bullet[bIndex]); //add bullet to world
},
- spore(who) { //used with the mod upgrade in mob.death()
+ spore(where, isFreeze = mod.isSporeFreeze) { //used with the mod upgrade in mob.death()
const bIndex = bullet.length;
const side = 4;
- bullet[bIndex] = Bodies.polygon(who.position.x, who.position.y, 5, side, {
+ bullet[bIndex] = Bodies.polygon(where.x, where.y, 5, side, {
// density: 0.0015, //frictionAir: 0.01,
inertia: Infinity,
+ isFreeze: isFreeze,
restitution: 0.5,
angle: Math.random() * 2 * Math.PI,
friction: 0,
frictionAir: 0.025,
- thrust: mod.isFastSpores ? 0.001 : 0.0004,
+ thrust: (mod.isFastSpores ? 0.001 : 0.0004) * (1 + 0.3 * (Math.random() - 0.5)),
dmg: mod.isMutualism ? 5.6 : 2.8, //2x bonus damage from mod.isMutualism
lookFrequency: 97 + Math.floor(117 * Math.random()),
classType: "bullet",
@@ -491,8 +492,9 @@ const b = {
x: 100 * (Math.random() - 0.5),
y: 100 * (Math.random() - 0.5)
},
- onDmg() {
+ onDmg(who) {
this.endCycle = 0; //bullet ends cycle after doing damage
+ if (this.isFreeze) mobs.statusSlow(who, 60)
},
onEnd() {
if (mod.isMutualism && this.isMutualismActive && !mod.isEnergyHealth) {
@@ -503,39 +505,70 @@ const b = {
}
},
do() {
- if (!(game.cycle % this.lookFrequency)) { //find mob targets
- this.closestTarget = null;
- this.lockedOn = null;
- let closeDist = Infinity;
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (mob[i].dropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
- // Matter.Query.ray(body, this.position, mob[i].position).length === 0
- const targetVector = Vector.sub(this.position, mob[i].position)
- const dist = Vector.magnitude(targetVector);
- if (dist < closeDist) {
- this.closestTarget = mob[i].position;
- closeDist = dist;
- this.lockedOn = mob[i] //Vector.normalise(targetVector);
- if (0.3 > Math.random()) break //doesn't always target the closest mob
+ if (this.lockedOn && this.lockedOn.alive) {
+ this.force = Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), this.mass * this.thrust)
+ } else {
+ if (!(game.cycle % this.lookFrequency)) { //find mob targets
+ this.closestTarget = null;
+ this.lockedOn = null;
+ let closeDist = Infinity;
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (mob[i].dropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
+ const targetVector = Vector.sub(this.position, mob[i].position)
+ const dist = Vector.magnitude(targetVector) * (Math.random() + 0.5);
+ if (dist < closeDist) {
+ this.closestTarget = mob[i].position;
+ closeDist = dist;
+ this.lockedOn = mob[i]
+ if (0.3 > Math.random()) break //doesn't always target the closest mob
+ }
}
}
}
- }
-
- if (this.lockedOn && this.lockedOn.alive) { //accelerate towards mobs
- this.force = Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), this.mass * this.thrust)
- } else if (mod.isSporeFollow && this.lockedOn !== undefined) { //move towards player
- //checking for undefined means that the spores don't go after the player until it has looked and not found a target
- const dx = this.position.x - mech.pos.x;
- const dy = this.position.y - mech.pos.y;
- if (dx * dx + dy * dy > 10000) {
- this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, Vector.add(this.playerOffPosition, this.position))), this.mass * this.thrust)
+ if (mod.isSporeFollow && this.lockedOn === null) { //move towards player
+ //checking for null means that the spores don't go after the player until it has looked and not found a target
+ const dx = this.position.x - mech.pos.x;
+ const dy = this.position.y - mech.pos.y;
+ if (dx * dx + dy * dy > 10000) {
+ this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, Vector.add(this.playerOffPosition, this.position))), this.mass * this.thrust)
+ }
+ } else {
+ this.force.y += this.mass * 0.0001; //gravity
}
- // this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.thrust)
- } else {
- this.force.y += this.mass * 0.0001; //gravity
}
+
+ // if (!this.lockedOn && !(game.cycle % this.lookFrequency)) { //find mob targets
+ // this.closestTarget = null;
+ // this.lockedOn = null;
+ // let closeDist = Infinity;
+ // for (let i = 0, len = mob.length; i < len; ++i) {
+ // if (mob[i].dropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
+ // // Matter.Query.ray(body, this.position, mob[i].position).length === 0
+ // const targetVector = Vector.sub(this.position, mob[i].position)
+ // const dist = Vector.magnitude(targetVector);
+ // if (dist < closeDist) {
+ // this.closestTarget = mob[i].position;
+ // closeDist = dist;
+ // this.lockedOn = mob[i] //Vector.normalise(targetVector);
+ // if (0.3 > Math.random()) break //doesn't always target the closest mob
+ // }
+ // }
+ // }
+ // }
+ // if (this.lockedOn && this.lockedOn.alive) { //accelerate towards mobs
+ // this.force = Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), this.mass * this.thrust)
+ // } else if (mod.isSporeFollow && this.lockedOn !== undefined) { //move towards player
+ // //checking for undefined means that the spores don't go after the player until it has looked and not found a target
+ // const dx = this.position.x - mech.pos.x;
+ // const dy = this.position.y - mech.pos.y;
+ // if (dx * dx + dy * dy > 10000) {
+ // this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, Vector.add(this.playerOffPosition, this.position))), this.mass * this.thrust)
+ // }
+ // // this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.thrust)
+ // } else {
+ // this.force.y += this.mass * 0.0001; //gravity
+ // }
},
});
const SPEED = 4 + 8 * Math.random();
@@ -578,7 +611,7 @@ const b = {
onDmg(who) {
mobs.statusSlow(who, 60)
this.endCycle = game.cycle
- if (mod.isAlphaRadiation) mobs.statusDoT(who, 0.1, 180)
+ if (mod.isHeavyWater) mobs.statusDoT(who, 0.1, 180)
},
onEnd() {},
do() {
@@ -1226,18 +1259,27 @@ const b = {
fire() {
let knock, spread
if (mech.crouch) {
+ spread = 0.75
mech.fireCDcycle = mech.cycle + Math.floor(55 * b.fireCD); // cool down
if (mod.isShotgunImmune) mech.immuneCycle = mech.cycle + Math.floor(58 * b.fireCD); //player is immune to collision damage for 30 cycles
- spread = 0.75
- knock = 0.01 * mod.bulletSize * mod.bulletSize
+ knock = 0.01
} else {
mech.fireCDcycle = mech.cycle + Math.floor(45 * b.fireCD); // cool down
if (mod.isShotgunImmune) mech.immuneCycle = mech.cycle + Math.floor(47 * b.fireCD); //player is immune to collision damage for 30 cycles
spread = 1.3
- knock = 0.08 * mod.bulletSize * mod.bulletSize
+ knock = 0.08
}
- player.force.x -= knock * Math.cos(mech.angle)
- player.force.y -= knock * Math.sin(mech.angle) * 0.3 //reduce knock back in vertical direction to stop super jumps
+
+ if (mod.isShotgunRecoil) {
+ mech.fireCDcycle -= 15
+ player.force.x -= 2 * knock * Math.cos(mech.angle)
+ player.force.y -= 2 * knock * Math.sin(mech.angle) //reduce knock back in vertical direction to stop super jumps
+ } else {
+ player.force.x -= knock * Math.cos(mech.angle)
+ player.force.y -= knock * Math.sin(mech.angle) * 0.3 //reduce knock back in vertical direction to stop super jumps
+ }
+
+
b.muzzleFlash(35);
if (mod.isNailShot) {
@@ -2142,7 +2184,7 @@ const b = {
bullet[me].onEnd = function () {
const NUM = 10
for (let i = 0; i < NUM; i++) {
- b.spore(this)
+ b.spore(this.position)
}
}
}
@@ -2669,10 +2711,20 @@ const b = {
}
//use energy to explode
- const energy = 0.3 * Math.min(mech.energy, 1.75)
- mech.energy -= energy * mod.isLaserDiode
- if (best.who) b.explosion(path[1], 1000 * energy, true)
- mech.fireCDcycle = mech.cycle + Math.floor(50 * b.fireCD); // cool down
+ let energy;
+ if (mod.isRapidPulse) {
+ energy = 0.02 + 0.06 * Math.min(mech.energy, 1.75)
+ if (mech.energy < energy) return
+ mech.energy -= energy * mod.isLaserDiode
+ if (best.who) b.explosion(path[1], 2000 * energy, true)
+ mech.fireCDcycle = mech.cycle + Math.floor(15 * b.fireCD); // cool down
+ } else {
+ energy = 0.3 * Math.min(mech.energy, 1.75)
+ mech.energy -= energy * mod.isLaserDiode
+ if (best.who) b.explosion(path[1], 1000 * energy, true)
+ mech.fireCDcycle = mech.cycle + Math.floor(50 * b.fireCD); // cool down
+ }
+
if (mod.isPulseStun) {
const range = 100 + 2000 * energy
diff --git a/js/engine.js b/js/engine.js
index 1420f9e..9eab081 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -205,13 +205,9 @@ function collisionChecks(event) {
if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) {
// const dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)));
let dmg = b.dmgScale * (obj.dmg + mod.acidDmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)))
- // console.log(obj.dmg, 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)))
- // console.log(obj.dmg / (0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity))))
if (mod.isCrit && !mob[k].seePlayer.recall && !mob[k].shield) dmg *= 5
mob[k].foundPlayer();
- console.log(dmg)
mob[k].damage(dmg);
- // console.log(dmg)
obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn
game.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x,
diff --git a/js/game.js b/js/game.js
index d963dcf..1725a51 100644
--- a/js/game.js
+++ b/js/game.js
@@ -771,6 +771,12 @@ const game = {
if (mod.isHealthRecovery) mech.addHealth(0.01)
}
+ if (mod.isHealLowHealth) {
+ if (mech.health < mech.maxHealth * 0.25) {
+ mech.addHealth(0.01 * mech.maxHealth)
+ }
+ }
+
if (!(game.cycle % 420)) { //once every 7 seconds
fallCheck = function (who, save = false) {
let i = who.length;
diff --git a/js/index.js b/js/index.js
index a956a52..b41bc25 100644
--- a/js/index.js
+++ b/js/index.js
@@ -81,7 +81,7 @@ const build = {
${mob.length} mobs, ${body.length} blocks, ${bullet.length} bullets, ${powerUp.length} power ups
mouse: (${game.mouseInGame.x.toFixed(1)}, ${game.mouseInGame.y.toFixed(1)}) ${mech.cycle} cycles
-
health: ${(mech.health*100).toFixed(0)}% energy: ${(mech.energy*100).toFixed(0)}%
+
health: (${(mech.health*100).toFixed(0)} / ${(mech.maxHealth*100).toFixed(0)}) energy: (${(mech.energy*100).toFixed(0)} / ${(mech.maxEnergy*100).toFixed(0)})
mass: ${player.mass.toFixed(1)} rerolls: ${powerUps.reroll.rerolls}
position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)}) velocity: (${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)})
diff --git a/js/level.js b/js/level.js
index fc2f255..2ca8244 100644
--- a/js/level.js
+++ b/js/level.js
@@ -16,17 +16,13 @@ const level = {
if (level.levelsCleared === 0) { //this code only runs on the first level
// game.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(9)
- // mech.setField("time dilation field")
- // mod.giveMod("logistics");
- // mod.giveMod("negative temperature");
- // b.giveGuns("flechettes")
+ mod.giveMod("automatic shotgun");
// b.giveGuns("spores")
- // mech.setField("negative mass field")
- // mech.setField("phase decoherence field")
+ // mech.setField("plasma torch")
level.intro(); //starting level
- // level.testing();
+ // level.testing();
// level.stronghold()
// level.bosses();
// level.satellite();
@@ -58,8 +54,8 @@ const level = {
}
if (mod.isArmorFromPowerUps) {
// for (let i = 0; i < powerUps.totalPowerUps; i++) {}
- mech.maxHealth += 0.03 * powerUps.totalPowerUps
- game.makeTextLog(" max health increased by " + (0.05 * powerUps.totalPowerUps * 100).toFixed(0) + "%", 300)
+ mech.maxHealth += 0.04 * powerUps.totalPowerUps
+ if (powerUps.totalPowerUps) game.makeTextLog(" max health increased by " + (0.04 * powerUps.totalPowerUps * 100).toFixed(0) + "%", 300)
}
},
isBuildRun: false,
@@ -135,7 +131,7 @@ const level = {
//******************************************************************************************************************
testing() {
- level.difficultyIncrease(14); //hard mode level 7
+ // level.difficultyIncrease(14); //hard mode level 7
spawn.setSpawnList();
spawn.setSpawnList();
level.defaultZoom = 1500
@@ -193,9 +189,10 @@ const level = {
// spawn.launcherBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400)
// spawn.spawner(1600, -500)
- spawn.sniper(1700, -120, 50)
- // spawn.sniper(1600, -120)
- // spawn.sniper(1800, -120)
+ // spawn.sniper(1700, -120, 50)
+ spawn.sniper(1400, -120)
+ spawn.sniper(1800, -120)
+ spawn.sniper(2200, -120)
// spawn.cellBossCulture(1600, -500)
// spawn.shooter(1600, -500)
// spawn.striker(1600, -500)
diff --git a/js/mob.js b/js/mob.js
index 978ac4e..e7a9409 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -45,6 +45,9 @@ const mobs = {
},
statusSlow(who, cycles = 60) {
if (!who.shield && !who.isShielded && !mech.isBodiesAsleep) {
+ if (who.isBoss) {
+ cycles = Math.floor(cycles * 0.25)
+ }
//remove other "slow" effects on this mob
let i = who.status.length
while (i--) {
@@ -993,7 +996,7 @@ const mobs = {
if (Math.random() < mod.sporesOnDeath) {
const len = Math.min(30, Math.floor(4 + this.mass * Math.random()))
for (let i = 0; i < len; i++) {
- b.spore(this) //spawn drone
+ b.spore(this.position)
}
}
if (Math.random() < mod.isBotSpawner) {
diff --git a/js/mods.js b/js/mods.js
index 88b41d8..8896e66 100644
--- a/js/mods.js
+++ b/js/mods.js
@@ -245,14 +245,14 @@ const mod = {
},
{
name: "electrostatic shots",
- description: "33% increased damage
33% increased delay after firing",
+ description: "25% increased damage
25% increased delay after firing",
maxCount: 1,
count: 0,
allowed() {
return true
},
effect() {
- mod.slowFire = 1.33
+ mod.slowFire = 1.25
b.setFireCD();
},
remove() {
@@ -431,7 +431,7 @@ const mod = {
effect() {
mod.sporesOnDeath += 0.11;
for (let i = 0; i < 10; i++) {
- b.spore(player)
+ b.spore(mech.pos)
}
},
remove() {
@@ -552,7 +552,7 @@ const mod = {
mech.immuneCycle = mech.cycle + mod.collisionImmuneCycles; //player is immune to collision damage for 30 cycles
},
remove() {
- mod.collisionImmuneCycles = 30;
+ mod.collisionImmuneCycles = 15;
}
},
{
@@ -720,6 +720,38 @@ const mod = {
mech.displayHealth();
}
},
+ {
+ name: "negentropy",
+ description: "when below 25% of maximum health
heal 1% of maximum health per second",
+ maxCount: 9,
+ count: 0,
+ allowed() {
+ return mech.maxHealth > 1
+ },
+ requires: "increased max health",
+ effect() {
+ mod.isHealLowHealth = true;
+ },
+ remove() {
+ mod.isHealLowHealth = false;
+ }
+ },
+ {
+ name: "crystallized armor",
+ description: "increase maximum health by 4% for each
unused power up at the end of a level",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return !mod.isEnergyHealth
+ },
+ requires: "not mass-energy equivalence",
+ effect() {
+ mod.isArmorFromPowerUps = true;
+ },
+ remove() {
+ mod.isArmorFromPowerUps = false;
+ }
+ },
{
name: "recursive healing",
description: "healing power ups trigger +1 more time",
@@ -736,22 +768,6 @@ const mod = {
mod.recursiveHealing = 1;
}
},
- {
- name: "crystallized armor",
- description: "increase maximum health by 3% for each
unused power up at the end of a level",
- maxCount: 1,
- count: 0,
- allowed() {
- return !mod.isEnergyHealth
- },
- requires: "not mass-energy equivalence",
- effect() {
- mod.isArmorFromPowerUps = true;
- },
- remove() {
- mod.isArmorFromPowerUps = false;
- }
- },
{
name: "pair production",
description: "power ups overfill your energy
temporarily gain twice your max energy",
@@ -787,13 +803,13 @@ const mod = {
},
{
name: "logistics",
- description: "ammo power ups add to your current gun
spawn 4 ammo",
+ description: "ammo power ups add to your current gun
spawn 4 ammo",
maxCount: 1,
count: 0,
allowed() {
- return true
+ return b.inventory.length > 1
},
- requires: "",
+ requires: "at least 2 guns",
effect() {
mod.isAmmoForGun = true;
for (let i = 0; i < 4; i++) {
@@ -858,6 +874,7 @@ const mod = {
description: "spawn 5 mods
power ups are limited to one choice",
maxCount: 1,
count: 0,
+ isNonRefundable: true,
allowed() {
return !mod.isExtraChoice
},
@@ -873,15 +890,36 @@ const mod = {
mod.isDeterminism = false;
}
},
+ {
+ name: "superdeterminism",
+ description: "spawn 4 mods
rerolls, guns, and fields will no longer spawn",
+ maxCount: 1,
+ count: 0,
+ isNonRefundable: true,
+ allowed() {
+ return mod.isDeterminism && !mod.manyWorlds
+ },
+ requires: "determinism",
+ effect: () => {
+ mod.isSuperDeterminism = true;
+ for (let i = 0; i < 4; i++) { //if you change the six also change it in Born rule
+ powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
+ if (Math.random() < mod.bayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
+ }
+ },
+ remove() {
+ mod.isSuperDeterminism = false;
+ }
+ },
{
name: "many-worlds",
description: "after choosing a gun, field, or mod
spawn a reroll, if you have none",
maxCount: 1,
count: 0,
allowed() {
- return true
+ return !mod.isSuperDeterminism
},
- requires: "",
+ requires: "not superdeterminism",
effect: () => {
mod.manyWorlds = true;
},
@@ -947,7 +985,9 @@ const mod = {
for (let i = 0, len = mod.mods.length; i < len; i++) { // spawn new mods power ups
if (!mod.mods[i].isNonRefundable) count += mod.mods[i].count
}
- if (mod.isDeterminism) count -= 5 //remove the 5 bonus mods when getting rid of determinism
+ if (mod.isDeterminism) count -= 3 //remove the bonus mods
+ if (mod.isSuperDeterminism) count -= 2 //remove the bonus mods
+
mod.setupAllMods(); // remove all mods
for (let i = 0; i < count; i++) { // spawn new mods power ups
powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
@@ -963,7 +1003,7 @@ const mod = {
count: 0,
isNonRefundable: true,
allowed() {
- return (mod.totalCount > 0) && !build.isCustomSelection
+ return (mod.totalCount > 0) && !build.isCustomSelection && !mod.isSuperDeterminism
},
requires: "at least 1 mod",
effect: () => {
@@ -1121,6 +1161,22 @@ const mod = {
mod.isNailShot = false;
}
},
+ {
+ name: "automatic shotgun",
+ description: "the shotgun fires 66% faster
recoil is greatly increased",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return mod.haveGunCheck("shotgun")
+ },
+ requires: "shotgun",
+ effect() {
+ mod.isShotgunRecoil = true;
+ },
+ remove() {
+ mod.isShotgunRecoil = false;
+ }
+ },
{
name: "super duper",
description: "fire +2 additional super balls",
@@ -1187,7 +1243,7 @@ const mod = {
},
{
name: "6s half-life",
- description: "needles are exposed to plutonium-238
2x damage spread over 6 seconds",
+ description: "flechette needles made of plutonium-238
2x damage spread over 6 seconds",
maxCount: 1,
count: 0,
allowed() {
@@ -1203,7 +1259,7 @@ const mod = {
},
{
name: "1/2s half-life",
- description: "needles are exposed to lithium-8
flechette damage occurs after 1/2 a second",
+ description: "flechette needles made of lithium-8
flechette damage occurs after 1/2 a second",
maxCount: 1,
count: 0,
allowed() {
@@ -1259,7 +1315,7 @@ const mod = {
},
requires: "wave beam",
effect() {
- mod.waveSpeedMap = 3 //needs to be 3 for pocket universe require check
+ mod.waveSpeedMap = 3 //needs to be 3 to stop bound state require check
mod.waveSpeedBody = 1.9
},
remove() {
@@ -1268,8 +1324,8 @@ const mod = {
}
},
{
- name: "pocket universe",
- description: "wave beam bullets last 5x longer
bullets are confined to a region around player",
+ name: "bound state",
+ description: "wave beam bullets last 5x longer
bullets are bound to a region around player",
maxCount: 1,
count: 0,
allowed() {
@@ -1385,7 +1441,7 @@ const mod = {
},
{
name: "rocket-propelled grenade",
- description: "grenades are rapidly accelerated forward
map collisions trigger an explosion",
+ description: "grenades rapidly accelerate forward
map collisions trigger an explosion",
maxCount: 1,
count: 0,
allowed() {
@@ -1527,6 +1583,23 @@ const mod = {
mod.isMutualism = false
}
},
+ {
+ name: "cryodesiccation",
+ description: "spores freeze mobs for 1 second",
+ //
spores do 1/3 damage
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return mod.haveGunCheck("spores") || mod.sporesOnDeath > 0 || mod.isSporeField
+ },
+ requires: "spores",
+ effect() {
+ mod.isSporeFreeze = true
+ },
+ remove() {
+ mod.isSporeFreeze = false
+ }
+ },
{
name: "brushless motor",
description: "drones accelerate 50% faster",
@@ -1545,7 +1618,7 @@ const mod = {
},
{
name: "heavy water",
- description: "ice IX is synthesized with unstable isotopes
does radioactive damage over 3 seconds",
+ description: "ice IX is synthesized with an extra neutron
does radioactive damage over 3 seconds",
maxCount: 1,
count: 0,
allowed() {
@@ -1553,15 +1626,15 @@ const mod = {
},
requires: "ice IX",
effect() {
- mod.isAlphaRadiation = true
+ mod.isHeavyWater = true
},
remove() {
- mod.isAlphaRadiation = false;
+ mod.isHeavyWater = false;
}
},
{
name: "necrophoresis",
- description: "foam splits into 3 copies
when the mob it is stuck to dies",
+ description: "foam splits into 3 copies
when the mob it's stuck to dies",
maxCount: 1,
count: 0,
allowed() {
@@ -1644,6 +1717,38 @@ const mod = {
mod.isPulseStun = false;
}
},
+ // {
+ // name: "aim",
+ // description: "pulse explosions aim",
+ // maxCount: 1,
+ // count: 0,
+ // allowed() {
+ // return mod.haveGunCheck("pulse")
+ // },
+ // requires: "pulse",
+ // effect() {
+ // mod.isPulseAim = true;
+ // },
+ // remove() {
+ // mod.isPulseAim = false;
+ // }
+ // },
+ // {
+ // name: "fast ignition",
+ // description: "pulse explosions more efficient
delay after firing is shorter",
+ // maxCount: 1,
+ // count: 0,
+ // allowed() {
+ // return mod.haveGunCheck("pulse")
+ // },
+ // requires: "pulse",
+ // effect() {
+ // mod.isRapidPulse = true;
+ // },
+ // remove() {
+ // mod.isRapidPulse = false;
+ // }
+ // },
//**************************************************
//************************************************** field
//************************************************** mods
@@ -1772,7 +1877,7 @@ const mod = {
},
{
name: "bremsstrahlung radiation",
- description: "blocking with your field does damage",
+ description: "blocking with standing wave harmonics
does damage to mobs",
maxCount: 9,
count: 0,
allowed() {
@@ -1945,9 +2050,9 @@ const mod = {
count: 0,
isNonRefundable: true,
allowed() {
- return true
+ return !mod.isSuperDeterminism
},
- requires: "",
+ requires: "not superdeterminism",
effect() {
for (let i = 0; i < 6; i++) {
powerUps.spawn(mech.pos.x, mech.pos.y, "reroll");
@@ -1963,9 +2068,9 @@ const mod = {
count: 0,
isNonRefundable: true,
allowed() {
- return true
+ return !mod.isSuperDeterminism
},
- requires: "",
+ requires: "not superdeterminism",
effect() {
powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
if (Math.random() < mod.bayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
@@ -1979,9 +2084,9 @@ const mod = {
count: 0,
isNonRefundable: true,
allowed() {
- return true
+ return !mod.isSuperDeterminism
},
- requires: "",
+ requires: "not superdeterminism",
effect() {
powerUps.spawn(mech.pos.x, mech.pos.y, "field");
if (Math.random() < mod.bayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "field");
@@ -2050,7 +2155,7 @@ const mod = {
isBlockStun: null,
isStunField: null,
isHarmDamage: null,
- isAlphaRadiation: null,
+ isHeavyWater: null,
energyRegen: null,
isVacuumShield: null,
renormalization: null,
@@ -2067,6 +2172,7 @@ const mod = {
isRPG: null,
is3Missiles: null,
isDeterminism: null,
+ isSuperDeterminism: null,
isHarmReduce: null,
nailsDeathMob: null,
isSlowFPS: null,
@@ -2081,5 +2187,10 @@ const mod = {
fastTimeJump: null,
isFastDot: null,
isArmorFromPowerUps: null,
- isAmmoForGun: null
+ isAmmoForGun: null,
+ isRapidPulse: null,
+ // isPulseAim: null,
+ isSporeFreeze: null,
+ isShotgunRecoil: null,
+ isHealLowHealth: null
}
\ No newline at end of file
diff --git a/js/player.js b/js/player.js
index 1e2f799..17dfe23 100644
--- a/js/player.js
+++ b/js/player.js
@@ -219,17 +219,6 @@ const mech = {
mech.doCrouch();
mech.yOff = mech.yOffWhen.jump;
mech.hardLandCD = mech.cycle + Math.min(momentum / 6.5 - 6, 40)
-
- // if (mod.isStomp) {
- // const len = Math.min(25, (momentum - 120) * 0.1)
- // for (let i = 0; i < len; i++) {
- // b.spore(player) //spawn drone
- // }
- // } else if (player.velocity.y > 27 && momentum > 180 * mod.squirrelFx) { //falling damage
- // let dmg = Math.sqrt(momentum - 180) * 0.01
- // dmg = Math.min(Math.max(dmg, 0.02), 0.20);
- // mech.damage(dmg);
- // }
} else {
mech.yOffGoal = mech.yOffWhen.stand;
}
@@ -316,8 +305,11 @@ const mech = {
//count mods
let totalMods = 0;
for (let i = 0; i < mod.mods.length; i++) {
- totalMods += mod.mods[i].count
+ if (!mod.mods[i].isNonRefundable) totalMods += mod.mods[i].count
}
+ if (mod.isDeterminism) totalMods -= 3 //remove the bonus mods
+ if (mod.isSuperDeterminism) totalMods -= 2 //remove the bonus mods
+
const totalGuns = b.inventory.length //count guns
function randomizeMods() {
@@ -328,7 +320,6 @@ const mech = {
if (mod.mods[i].count < mod.mods[i].maxCount &&
!mod.mods[i].isNonRefundable &&
mod.mods[i].name !== "quantum immortality" &&
- mod.mods[i].name !== "determinism" &&
mod.mods[i].allowed()
) options.push(i);
}
@@ -1335,7 +1326,7 @@ const mech = {
const len = Math.floor(6 + 4 * Math.random())
mech.energy -= len * 0.074;
for (let i = 0; i < len; i++) {
- b.spore(player)
+ b.spore(mech.pos)
}
} else if (mod.isMissileField) {
// mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones
@@ -1506,9 +1497,8 @@ const mech = {
name: "plasma torch",
description: "use energy to emit short range plasma
plasma damages and pushes mobs",
isEasyToAim: false,
- effect: () => {
+ effect() {
mech.fieldMeterColor = "#f0f"
-
mech.hold = function () {
if (mech.isHolding) {
mech.drawHold(mech.holdingTarget);
@@ -1607,13 +1597,6 @@ const mech = {
x: best.who.velocity.x * 0.7,
y: best.who.velocity.y * 0.7
});
- // const angle = Math.atan2(player.position.y - best.who.position.y, player.position.x - best.who.position.x);
- // const mass = Math.min(Math.sqrt(best.who.mass), 6);
- // Matter.Body.setVelocity(best.who, {
- // x: best.who.velocity.x * 0.85 - 3 * Math.cos(angle) / mass,
- // y: best.who.velocity.y * 0.85 - 3 * Math.sin(angle) / mass
- // });
-
//draw mob damage circle
game.drawList.push({
x: path[1].x,
@@ -1648,7 +1631,6 @@ const mech = {
ctx.beginPath();
ctx.moveTo(x, y);
const step = Vector.magnitude(Vector.sub(path[0], path[1])) / 10
-
for (let i = 0; i < 8; i++) {
x += step * (Dx + 1.5 * (Math.random() - 0.5))
y += step * (Dy + 1.5 * (Math.random() - 0.5))
@@ -1656,12 +1638,6 @@ const mech = {
}
ctx.lineWidth = 2 * Math.random();
ctx.stroke();
- //draw shield around player
- // ctx.beginPath();
- // ctx.arc(mech.pos.x, mech.pos.y, mech.fieldRange * 0.75, 0, 2 * Math.PI);
- // ctx.fillStyle = "rgba(255,0,255,0.05)"
- // ctx.fill();
- // mech.pushBody360(100); //disabled because doesn't work at short range
}
} else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
mech.pickUp();
@@ -1669,6 +1645,7 @@ const mech = {
mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
}
mech.drawFieldMeter("rgba(0, 0, 0, 0.2)")
+
}
}
},
diff --git a/js/powerup.js b/js/powerup.js
index de7b2e6..127a344 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -475,35 +475,35 @@ const powerUps = {
}
},
spawn(x, y, target, moving = true, mode = null) {
- // if (!level.isBuildRun || target === "heal" || target === "ammo") {
- let index = powerUp.length;
- target = powerUps[target];
- size = target.size();
- powerUp[index] = Matter.Bodies.polygon(x, y, 0, size, {
- density: 0.001,
- frictionAir: 0.01,
- restitution: 0.8,
- inertia: Infinity, //prevents rotation
- collisionFilter: {
- group: 0,
- category: cat.powerUp,
- mask: cat.map | cat.powerUp
- },
- color: target.color,
- effect: target.effect,
- name: target.name,
- size: size
- });
- if (mode) {
- powerUp[index].mode = mode
- }
- if (moving) {
- Matter.Body.setVelocity(powerUp[index], {
- x: (Math.random() - 0.5) * 15,
- y: Math.random() * -9 - 3
+ if (!(mod.isSuperDeterminism && (target === 'gun' || target === 'field' || target === 'reroll'))) {
+ let index = powerUp.length;
+ target = powerUps[target];
+ size = target.size();
+ powerUp[index] = Matter.Bodies.polygon(x, y, 0, size, {
+ density: 0.001,
+ frictionAir: 0.01,
+ restitution: 0.8,
+ inertia: Infinity, //prevents rotation
+ collisionFilter: {
+ group: 0,
+ category: cat.powerUp,
+ mask: cat.map | cat.powerUp
+ },
+ color: target.color,
+ effect: target.effect,
+ name: target.name,
+ size: size
});
+ if (mode) {
+ powerUp[index].mode = mode
+ }
+ if (moving) {
+ Matter.Body.setVelocity(powerUp[index], {
+ x: (Math.random() - 0.5) * 15,
+ y: Math.random() * -9 - 3
+ });
+ }
+ World.add(engine.world, powerUp[index]); //add to world
}
- World.add(engine.world, powerUp[index]); //add to world
- // }
},
};
\ No newline at end of file
diff --git a/js/spawn.js b/js/spawn.js
index 8eb97c3..1bbe00f 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -159,6 +159,7 @@ const spawn = {
cellBoss(x, y, radius = 20) {
mobs.spawn(x + Math.random(), y + Math.random(), 20, radius * (1 + 1.2 * Math.random()), "rgba(0,150,155,0.7)");
let me = mob[mob.length - 1];
+ me.isBoss = true;
me.isCell = true;
me.accelMag = 0.00015 * game.accelScale;
me.memory = 40;
@@ -214,11 +215,12 @@ const spawn = {
}
};
me.onDeath = function () {
+ this.isCell = false;
let count = 0 //count other cells
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].isCell) count++
}
- if (count === 1) { //only drop a power up if this is the last cell
+ if (count < 1) { //only drop a power up if this is the last cell
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
} else {
this.leaveBody = false;
@@ -553,6 +555,7 @@ const spawn = {
suckerBoss(x, y, radius = 25) {
mobs.spawn(x, y, 12, radius, "#000");
let me = mob[mob.length - 1];
+ me.isBoss = true;
me.stroke = "transparent"; //used for drawSneaker
me.eventHorizon = 1100; //required for black hole
me.seeAtDistance2 = (me.eventHorizon + 1000) * (me.eventHorizon + 1000); //vision limit is event horizon
@@ -653,6 +656,7 @@ const spawn = {
let targets = [] //track who is in the node boss, for shields
mobs.spawn(x, y, 6, radius, "#b386e8");
let me = mob[mob.length - 1];
+ me.isBoss = true;
targets.push(me.id) //add to shield protection
me.friction = 0;
me.frictionAir = 0.0065;
@@ -732,6 +736,7 @@ const spawn = {
timeSkipBoss(x, y, radius = 55) {
mobs.spawn(x, y, 6, radius, '#000');
let me = mob[mob.length - 1];
+ me.isBoss = true;
// me.stroke = "transparent"; //used for drawSneaker
me.timeSkipLastCycle = 0
me.eventHorizon = 1800; //required for black hole
@@ -896,6 +901,7 @@ const spawn = {
const color = "#05f"
mobs.spawn(x, y, 3, radius, color);
let me = mob[mob.length - 1];
+ me.isBoss = true;
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
me.accelMag = 0.0005 * game.accelScale;
@@ -1054,6 +1060,7 @@ const spawn = {
laserBoss(x, y, radius = 30) {
mobs.spawn(x, y, 3, radius, "#f00");
let me = mob[mob.length - 1];
+ me.isBoss = true;
me.startingPosition = {
x: x,
y: y
@@ -1463,6 +1470,7 @@ const spawn = {
//boss that drops bombs from above and holds a set distance from player
mobs.spawn(x, y, 3, radius, "transparent");
let me = mob[mob.length - 1];
+ me.isBoss = true;
Matter.Body.setDensity(me, 0.0015 + 0.0004 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.stroke = "rgba(255,0,200)"; //used for drawGhost
@@ -1527,6 +1535,7 @@ const spawn = {
shooterBoss(x, y, radius = 130) {
mobs.spawn(x, y, 3, radius, "rgb(255,70,180)");
let me = mob[mob.length - 1];
+ me.isBoss = true;
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
me.isVerticesChange = true
me.memory = 240;
@@ -1739,7 +1748,7 @@ const spawn = {
this.seePlayerCheck();
this.checkStatus();
this.attraction();
- if (this.seePlayer.recall && !(game.cycle % this.fireFreq)) {
+ if (this.seePlayer.recall && !(game.cycle % this.fireFreq) && !mech.isBodiesAsleep) {
Matter.Body.setAngularVelocity(this, 0.14)
//fire a bullet from each vertex
for (let i = 0, len = this.vertices.length; i < len; i++) {
@@ -1757,6 +1766,7 @@ const spawn = {
launcherBoss(x, y, radius = 90) {
mobs.spawn(x, y, 6, radius, "rgb(150,150,255)");
let me = mob[mob.length - 1];
+ me.isBoss = true;
me.accelMag = 0.00008 * game.accelScale;
me.fireFreq = Math.floor(330 * game.CDScale)
me.frictionStatic = 0;
@@ -1776,7 +1786,7 @@ const spawn = {
this.checkStatus();
this.attraction();
this.repulsion();
- if (this.seePlayer.recall && !(game.cycle % this.fireFreq)) {
+ if (this.seePlayer.recall && !(game.cycle % this.fireFreq) && !mech.isBodiesAsleep) {
Matter.Body.setAngularVelocity(this, 0.11)
//fire a bullet from each vertex
for (let i = 0, len = this.vertices.length; i < len; i++) {
@@ -1881,6 +1891,7 @@ const spawn = {
//snake boss with a laser head
mobs.spawn(x, y, 8, radius, "rgb(255,50,130)");
let me = mob[mob.length - 1];
+ me.isBoss = true;
me.accelMag = 0.0012 * game.accelScale;
me.memory = 200;
me.laserRange = 500;
@@ -1922,6 +1933,7 @@ const spawn = {
// often has a ring of mobs around it
mobs.spawn(x, y, 8, radius, "rgb(0,60,80)");
let me = mob[mob.length - 1];
+ me.isBoss = true;
me.g = 0.0001; //required if using 'gravity'
me.accelMag = 0.002 * game.accelScale;
me.memory = 20;
diff --git a/todo.txt b/todo.txt
index b7ea3a3..9b7d1e9 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,25 +1,47 @@
-added mods to spawn a gun, a field, and rerolls
-added mod that gives max health for leftover power ups
- this mod has some interesting interactions with other mods
-mod annihilation now uses 20% of base energy and doesn't trigger damage immunity
-mod Hawking radiation removed
-mod negative temperature: freezed mobs in range of negative mass field, but drain energy
-mod: logistics
- ammo power ups are added to your current gun
- spawn 4 ammo immediately
+damage immunity after a collisions is reduced from 1/2s to 1/4s
+freezing status effects only last 1/4 as long on boss mobs
+mod - shotgun 66% increased fire rate and recoil
+mod - slowly heal when below 25% health
+mod - superdeterminism spawn 4 mods, but rerolls, fields, and guns no longer spawn
************** TODO - n-gon **************
+physics question: why don't the bound states of fields spread out. What is making them bound.
-very high speed projectile that checks for collisions in future positions to avoid tunneling
+rework reaction inhibitor to spawn mobs with 12% less life, rather then killing them at 12%
+
+mod: all mobs have a shield (or just a higher rate)
+ all mobs drop an extra ammo power up?
+
+levels: make a function in the main game loop that runs level specific code
+ reset the level function as each new level loads
+
+mod: foam grenades
+ or maybe all explosions make foam?
+
+mod: use the stealth flag from the phase decoherence field
+ maybe trigger it along with the damage immunity CD
+
+mod: efficient shielding (requires standing wave harmonics field)
+ lowers force applied when blocking mobs (instead of flinging them away, you push them like with plasma torch), but uses less energy to block mobs
+ and making it so liquid nitrogen and uranium reactor core have that effect in a radius around the player instead of on contact
+ the idea being that you're sacrificing defense and instead of flinging away mobs when they touch the field, you're letting them stay longer in your field so that they take more damage
+
+mod harmonic shield: slow everything in range around shield (temporal shield)
+ set max speed?
+
+need a mod that effects ice status
+ mod: ice status effect lasts twice as long
+
+mod: bot very slowly follows you and gives you a bonus when it's in range
+ it moves through walls
+ effect: damage bonus?, damage reduction?, push away mobs, limit top speed of mobs/blocks/player?
+
+pulse and laser can auto aim
+ can hit multiple targets if they are in range
make a visual indication of max health
-mod: give a gun auto aiming
- minigun?
-
-ice status effect lasts twice as long
-
shrink font on small screens (so you can see 5 options on power ups)
graphic idea: bezier curve that moves smoothly from mob to mob
@@ -29,8 +51,6 @@ give rail gun projectile a trail
only draw above speed 5
track previous positions?
-shielded mobs don't knock back the same as unshielded mobs
-
movement fluidity
let legs jump on mobs, but player will still take damage
like: ori and the blind forest, celeste