diff --git a/.gitignore b/.gitignore
index 73bad25..97e094b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
.jsbeautifyrc
.DS_Store
+.DS_Store
diff --git a/js/bullet.js b/js/bullet.js
index 3b2e7fc..d3090bb 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -852,7 +852,7 @@ const b = {
if (mod.iceEnergy && !who.shield && !who.isShielded && who.dropPowerUp && who.alive) {
setTimeout(function() {
if (!who.alive) {
- mech.energy += mod.iceEnergy * 0.66 * mech.maxEnergy
+ mech.energy += mod.iceEnergy * 0.5 * mech.maxEnergy
mech.addHealth(mod.iceEnergy * 0.04)
}
}, 10);
@@ -2066,7 +2066,7 @@ const b = {
y: SPEED * Math.sin(dir)
});
// Matter.Body.setDensity(bullet[me], 0.0001);
- bullet[me].endCycle = game.cycle + Math.floor((300 + 60 * Math.random()) * mod.isBulletsLastLonger);
+ bullet[me].endCycle = game.cycle + Math.floor(300 + 60 * Math.random());
bullet[me].minDmgSpeed = 0;
bullet[me].restitution = 1;
bullet[me].friction = 0;
@@ -2363,12 +2363,13 @@ const b = {
//missile(where, dir, speed, size = 1, spawn = 0) {
if (mod.is3Missiles) {
if (mech.crouch) {
- mech.fireCDcycle = mech.cycle + 18 * b.fireCD; // cool down
+ mech.fireCDcycle = mech.cycle + 17 * b.fireCD; // cool down
for (let i = 0; i < 3; i++) {
b.missile({
x: mech.pos.x,
y: mech.pos.y - 40
- }, -Math.PI / 2 + 0.08 * (1 - i), 0, 0.7, mod.recursiveMissiles)
+ }, -Math.PI / 2 + 0.08 * (1 - i) + 0.3 * (Math.random() - 0.5), 0, 0.7, mod.recursiveMissiles)
+ bullet[bullet.length - 1].force.x -= 0.015 * (i - 1);
}
} else {
mech.fireCDcycle = mech.cycle + 55 * b.fireCD; // cool down
@@ -2381,19 +2382,22 @@ const b = {
b.missile({
x: mech.pos.x + 40 * direction.x,
y: mech.pos.y + 40 * direction.y
- }, mech.angle + 0.1 * (Math.random() - 0.5), 5, 0.7, mod.recursiveMissiles)
+ }, mech.angle + 0.06 * (Math.random() - 0.5), 5, 0.7, mod.recursiveMissiles)
bullet[bullet.length - 1].force.x += push.x * (i - 1);
bullet[bullet.length - 1].force.y += push.y * (i - 1);
}
}
} else {
if (mech.crouch) {
- mech.fireCDcycle = mech.cycle + 18 * b.fireCD; // cool down
+ mech.fireCDcycle = mech.cycle + 17 * b.fireCD; // cool down
+ const off = Math.random() - 0.5
b.missile({
x: mech.pos.x,
y: mech.pos.y - 40
},
- -Math.PI / 2, 0, 1, mod.recursiveMissiles)
+ -Math.PI / 2 + 0.15 * off, 0, 1, mod.recursiveMissiles)
+ bullet[bullet.length - 1].force.x += off * 0.03;
+ // bullet[bullet.length - 1].force.y += push.y * (i - 1);
} else {
mech.fireCDcycle = mech.cycle + 55 * b.fireCD; // cool down
b.missile({
@@ -2501,7 +2505,7 @@ const b = {
const me = bullet.length;
const dir = mech.angle;
bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 10, 4, b.fireAttributes(dir, false));
- b.fireProps(mech.crouch ? 45 : 25, mech.crouch ? 30 : 20, dir, me); //cd , speed
+ b.fireProps(mech.crouch ? 45 : 25, mech.crouch ? 35 : 20, dir, me); //cd , speed
Matter.Body.setDensity(bullet[me], 0.000001);
bullet[me].endCycle = Infinity;
bullet[me].frictionAir = 0;
@@ -2510,9 +2514,11 @@ const b = {
bullet[me].restitution = 0;
bullet[me].minDmgSpeed = 0;
bullet[me].damageRadius = 100;
- bullet[me].maxDamageRadius = (435 + 150 * Math.random()) * (mod.isNeutronImmune ? 1.2 : 1)
+ bullet[me].maxDamageRadius = 450 + 130 * mod.isNeutronSlow + 130 * mod.isNeutronImmune //+ 150 * Math.random()
+ bullet[me].radiusDecay = (0.81 + 0.15 * mod.isNeutronSlow + 0.15 * mod.isNeutronImmune) / mod.isBulletsLastLonger
bullet[me].stuckTo = null;
bullet[me].stuckToRelativePosition = null;
+ bullet[me].vacuumSlow = 0.97;
bullet[me].beforeDmg = function() {};
bullet[me].stuck = function() {};
bullet[me].do = function() {
@@ -2581,12 +2587,11 @@ const b = {
}
}
}
- bullet[me].radiationMode = function() {
+ bullet[me].radiationMode = function() { //the do code after the bullet is stuck on something, projects a damaging radiation field
this.stuck(); //runs different code based on what the bullet is stuck to
if (!mech.isBodiesAsleep) {
this.damageRadius = this.damageRadius * 0.85 + 0.15 * this.maxDamageRadius //smooth radius towards max
- this.maxDamageRadius -= 0.8 / mod.isBulletsLastLonger //+ 0.5 * Math.sin(game.cycle * 0.1) //slowly shrink max radius
-
+ this.maxDamageRadius -= this.radiusDecay
if (this.damageRadius < 15) {
this.endCycle = 0;
} else {
@@ -2603,11 +2608,17 @@ const b = {
//aoe damage to mobs
for (let i = 0, len = mob.length; i < len; i++) {
if (Vector.magnitude(Vector.sub(mob[i].position, this.position)) < this.damageRadius) {
- let dmg = b.dmgScale * 0.08
+ let dmg = b.dmgScale * 0.082
if (Matter.Query.ray(map, mob[i].position, this.position).length > 0) dmg *= 0.25 //reduce damage if a wall is in the way
if (mob[i].shield) dmg *= 4 //x5 to make up for the /5 that shields normally take
mob[i].damage(dmg);
mob[i].locatePlayer();
+ if (mod.isNeutronSlow) {
+ Matter.Body.setVelocity(mob[i], {
+ x: mob[i].velocity.x * this.vacuumSlow,
+ y: mob[i].velocity.y * this.vacuumSlow
+ });
+ }
}
}
ctx.beginPath();
@@ -2616,6 +2627,24 @@ const b = {
ctx.fillStyle = `rgba(25,139,170,${0.2+0.06*Math.random()})`;
ctx.fill();
ctx.globalCompositeOperation = "source-over"
+ if (mod.isNeutronSlow) {
+ const that = this
+
+ function slow(who, radius = that.explodeRad * 3.2) {
+ for (i = 0, len = who.length; i < len; i++) {
+ const sub = Vector.sub(that.position, who[i].position);
+ const dist = Vector.magnitude(sub);
+ if (dist < radius) {
+ Matter.Body.setVelocity(who[i], {
+ x: who[i].velocity.x * that.vacuumSlow,
+ y: who[i].velocity.y * that.vacuumSlow
+ });
+ }
+ }
+ }
+ slow(body, this.damageRadius)
+ slow([player], this.damageRadius)
+ }
}
}
}
diff --git a/js/game.js b/js/game.js
index 5a101b3..26733a1 100644
--- a/js/game.js
+++ b/js/game.js
@@ -459,13 +459,9 @@ const game = {
addGravity(body, game.g);
player.force.y += player.mass * game.g;
},
- // reset() { //run on first run, and each later run after you die
-
- // },
firstRun: true,
splashReturn() {
game.onTitlePage = true;
- // document.getElementById('splash').onclick = 'run(this)';
document.getElementById("splash").onclick = function() {
game.startGame();
};
diff --git a/js/level.js b/js/level.js
index f7034fc..b7c70e1 100644
--- a/js/level.js
+++ b/js/level.js
@@ -13,16 +13,15 @@ const level = {
start() {
if (level.levelsCleared === 0) { //this code only runs on the first level
// game.enableConstructMode() //used to build maps in testing mode
- // level.difficultyIncrease(8)
+ // level.difficultyIncrease(26)
// game.zoomScale = 1000;
// game.setZoom();
// mech.setField("wormhole")
// b.giveGuns("missiles")
// mod.is3Missiles = true
- // mod.giveMod("incendiary ammunition")
+ // mod.giveMod("neutron bomb")
// mod.giveMod("super ball")
-
level.intro(); //starting level
// level.testing(); //not in rotation
// level.finalBoss() //final boss level
@@ -147,16 +146,16 @@ const level = {
// spawn.launcherBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400)
// spawn.spawner(1600, -500)
- spawn.shooter(1700, -120)
+ // spawn.shooter(1700, -120)
// spawn.bomberBoss(1400, -500)
- spawn.sniper(1800, -120)
+ // spawn.sniper(1800, -120)
// spawn.cellBossCulture(1600, -500)
// spawn.spiderBoss(1600, -500)
- spawn.launcher(1200, -500)
+ // spawn.launcher(1200, -500)
// spawn.shield(mob[mob.length - 1], 1800, -120, 1);
// spawn.nodeBoss(1200, -500, "launcher")
- // spawn.snakeBoss(1200, -500)
+ spawn.snakeBoss(1200, -500)
// spawn.timeSkipBoss(2900, -500)
// spawn.randomMob(1600, -500)
},
diff --git a/js/mob.js b/js/mob.js
index 225b123..27a1463 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -145,7 +145,7 @@ const mobs = {
who.isStunned = false
},
type: "stun",
- endCycle: game.cycle + cycles,
+ endCycle: game.cycle + cycles * (who.isBoss ? 0.2 : 1),
})
}
},
diff --git a/js/mods.js b/js/mods.js
index 612a164..31bfd48 100644
--- a/js/mods.js
+++ b/js/mods.js
@@ -1596,7 +1596,7 @@ const mod = {
maxCount: 1,
count: 0,
allowed() {
- return (mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(mod.isSporeField || mod.isMissileField || mod.isIceField)) || mod.haveGunCheck("drones") || mod.haveGunCheck("super balls") || (mod.haveGunCheck("nail gun") && !mod.isIceCrystals && !mod.isNailCrit) || (mod.haveGunCheck("shotgun") && !mod.isNailShot)
+ return (mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(mod.isSporeField || mod.isMissileField || mod.isIceField)) || mod.haveGunCheck("drones") || mod.haveGunCheck("super balls") || (mod.haveGunCheck("nail gun")) || (mod.haveGunCheck("shotgun")) && !mod.isIceCrystals && !mod.isNailCrit && !mod.isNailShot && !mod.isNailPoison
},
requires: "drones, super balls, nail gun, shotgun",
effect() {
@@ -1608,15 +1608,15 @@ const mod = {
},
{
name: "Lorentzian topology",
- description: "bullets last 33% longer
drones, spores, super balls, foam, wave, ice IX, neutron",
+ description: "bullets last 30% longer
drones, spores, missiles, foam, wave, ice IX, neutron",
maxCount: 3,
count: 0,
allowed() {
- return mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" || mod.haveGunCheck("spores") || mod.haveGunCheck("drones") || mod.haveGunCheck("super balls") || mod.haveGunCheck("foam") || mod.haveGunCheck("wave beam") || mod.haveGunCheck("ice IX") || mod.haveGunCheck("neutron bomb")
+ return mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" || mod.haveGunCheck("spores") || mod.haveGunCheck("drones") || mod.haveGunCheck("missiles") || mod.haveGunCheck("foam") || mod.haveGunCheck("wave beam") || mod.haveGunCheck("ice IX") || mod.isNeutronBomb
},
- requires: "drones, spores, super balls, foam
wave beam, ice IX, neutron bomb",
+ requires: "drones, spores, missiles, foam
wave beam, ice IX, neutron bomb",
effect() {
- mod.isBulletsLastLonger += 0.33
+ mod.isBulletsLastLonger += 0.3
},
remove() {
mod.isBulletsLastLonger = 1;
@@ -2071,7 +2071,7 @@ const mod = {
allowed() {
return mod.haveGunCheck("grenades") && !mod.isRPG && !mod.isNeutronBomb
},
- requires: "grenades, not rocket-propelled or neutron bomb",
+ requires: "grenades, not rocket-propelled",
effect() {
mod.isVacuumBomb = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -2080,8 +2080,10 @@ const mod = {
},
remove() {
mod.isVacuumBomb = false;
- for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
- if (b.guns[i].name === "grenades") b.guns[i].fire = b.guns[i].fireNormal
+ if (!mod.isNeutronBomb) {
+ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
+ if (b.guns[i].name === "grenades") b.guns[i].fire = (mod.isNeutronBomb) ? b.guns[i].fireNeutron : b.guns[i].fireNormal
+ }
}
}
},
@@ -2091,9 +2093,9 @@ const mod = {
maxCount: 1,
count: 0,
allowed() {
- return mod.haveGunCheck("grenades") && !mod.isRPG && !mod.isVacuumBomb && !mod.grenadeFragments
+ return mod.haveGunCheck("grenades") && !mod.isRPG && !mod.grenadeFragments && !mod.isVacuumBomb
},
- requires: "grenades, not rocket-propelled, vacuum bomb, or fragmentation",
+ requires: "grenades, not rocket-propelled or fragmentation",
effect() {
mod.isNeutronBomb = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -2103,7 +2105,7 @@ const mod = {
remove() {
mod.isNeutronBomb = false;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
- if (b.guns[i].name === "grenades") b.guns[i].fire = b.guns[i].fireNormal
+ if (b.guns[i].name === "grenades") b.guns[i].fire = (mod.isVacuumBomb) ? b.guns[i].fireVacuum : b.guns[i].fireNormal
}
}
},
@@ -2123,6 +2125,22 @@ const mod = {
mod.isNeutronImmune = false
}
},
+ {
+ name: "vacuum permittivity",
+ description: "increase neutron bomb's range by 20%
objects in range of the bomb are slowed",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return mod.isNeutronBomb
+ },
+ requires: "neutron bomb",
+ effect() {
+ mod.isNeutronSlow = true
+ },
+ remove() {
+ mod.isNeutronSlow = false
+ }
+ },
{
name: "mine reclamation",
description: "retrieve ammo from all undetonated mines
and 20% of mines after detonation",
@@ -2334,7 +2352,7 @@ const mod = {
},
{
name: "thermoelectric effect",
- description: "killing mobs with ice IX gives 4% health
and overloads energy by 166% of your max",
+ description: "killing mobs with ice IX gives 4% health
and overloads energy by 50% of your max",
maxCount: 9,
count: 0,
allowed() {
@@ -3279,5 +3297,6 @@ const mod = {
isRailEnergyGain: null,
isMineSentry: null,
isIncendiary: null,
- overfillDrain: null
+ overfillDrain: null,
+ isNeutronSlow: null
}
\ No newline at end of file
diff --git a/js/player.js b/js/player.js
index 1bdddc7..4e5d05a 100644
--- a/js/player.js
+++ b/js/player.js
@@ -390,6 +390,8 @@ const mech = {
document.getElementById("text-log").style.opacity = 0; //fade out any active text logs
document.getElementById("fade-out").style.opacity = 1; //slowly fades out
setTimeout(function() {
+ World.clear(engine.world);
+ Engine.clear(engine);
game.splashReturn();
}, 3000);
}
@@ -462,6 +464,7 @@ const mech = {
if (Math.random() < 0.5) b.drone() //spawn drone
}
}
+
if (mod.isEnergyHealth) {
mech.energy -= dmg;
if (mech.energy < 0 || isNaN(mech.energy)) { //taking deadly damage
@@ -1339,7 +1342,7 @@ const mech = {
description: "use energy to block mobs
excess energy used to build drones
double your default energy regeneration",
effect: () => {
mech.hold = function() {
- if (mech.energy > mech.maxEnergy - 0.02 && mech.fieldCDcycle < mech.cycle) {
+ if (mech.energy > mech.maxEnergy - 0.02 && mech.fieldCDcycle < mech.cycle && input.field) {
if (mod.isSporeField) {
// mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones
const len = Math.floor(6 + 5 * Math.random())
diff --git a/js/spawn.js b/js/spawn.js
index 91ea90c..d82e596 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -2192,16 +2192,23 @@ const spawn = {
};
},
snakeBoss(x, y, radius = 75) { //snake boss with a laser head
- mobs.spawn(x, y, 8, radius, "rgb(255,50,130)");
+ mobs.spawn(x, y, 8, radius, "rgb(55,170,170)");
let me = mob[mob.length - 1];
me.isBoss = true;
- me.accelMag = 0.0011 * game.accelScale;
+ me.accelMag = 0.0008 * game.accelScale;
me.memory = 250;
me.laserRange = 500;
- Matter.Body.setDensity(me, 0.0013 + 0.0005 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
+ Matter.Body.setDensity(me, 0.0015 + 0.0005 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
spawn.shield(me, x, y, 1);
me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
+ //wake up tail mobs
+ for (let i = 0; i < mob.length; i++) {
+ if (mob[i].isSnakeTail && mob[i].alive) {
+ mob[i].do = mob[i].doActive
+ mob[i].removeConsBB();
+ }
+ }
};
me.do = function() {
this.seePlayerCheck();
@@ -2211,7 +2218,7 @@ const spawn = {
};
//snake tail
- const nodes = 2 + Math.min(3 + Math.ceil(Math.random() * game.difficulty + 2), 8)
+ const nodes = Math.min(8 + Math.ceil(0.5 * game.difficulty), 40)
spawn.lineBoss(x + 105, y, "snakeBody", nodes);
//constraint boss with first 3 mobs in lineboss
consBB[consBB.length] = Constraint.create({
@@ -2235,7 +2242,7 @@ const spawn = {
},
snakeBody(x, y, radius = 20) {
- mobs.spawn(x, y, 4, radius, "rgb(255,0,0)");
+ mobs.spawn(x, y, 4, radius, "rgb(55,170,170)");
let me = mob[mob.length - 1];
me.onHit = function() {
//run this function on hitting player
@@ -2243,16 +2250,18 @@ const spawn = {
};
me.collisionFilter.mask = cat.bullet | cat.player
// me.g = 0.0002; //required if using 'gravity'
- // me.accelMag = 0 //0.001 * game.accelScale;
- // me.memory = 0;
+ me.accelMag = 0.001 * game.accelScale;
me.leaveBody = false;
- // me.seePlayerFreq = Math.round((80 + 50 * Math.random()) * game.lookFreqScale);
+ me.seePlayerFreq = Math.round((80 + 50 * Math.random()) * game.lookFreqScale);
me.frictionAir = 0.02;
+ me.isSnakeTail = true;
me.do = function() {
- // this.gravity();
- // this.seePlayerCheck();
this.checkStatus();
- // this.attraction();
+ };
+ me.doActive = function() {
+ this.seePlayerCheck();
+ this.checkStatus();
+ this.attraction();
};
},
tetherBoss(x, y, radius = 90) {
diff --git a/todo.txt b/todo.txt
index e95a331..f4290e9 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,8 +1,11 @@
*********** NEXT PATCH ***********
-some changes to snake boss
-supercapacitor - overfill energy decays 66% slower
- (thanks to NoHaxJustPi for coding this)
+snake boss is updated
+ -fear the snake
+
+mod neutron bomb: vacuum permittivity - gets a larger radius and a slow effect
+
+bosses are only stunned for 1/5 of the normal stun time
************** BUGS **************
@@ -25,7 +28,10 @@ supercapacitor - overfill energy decays 66% slower
************** TODO **************
-vacuum and neutron bomb could merge
+mod - railgun's push effect is increased, and it does some damage to nearby mobs
+ maybe only triggers at max energy
+
+Laser mod: For each reflection of laser, damage increases by 10%
new power up - increase damage and fire speed, for 15 seconds
named boost?
@@ -34,43 +40,27 @@ new power up - increase damage and fire speed, for 15 seconds
how to indicate effect duration
or just give the effect after picking up a reroll
-mod - overfilled energy decays slower
+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?
-mod - remove max health, but you take 60% more harm
-
-mod - taking damage fires your current weapon at the nearest mob
- requires? some harm reduction
-
-mod - a 4th mod selection option that is always a bot
-
-mod - railgun's push effect is increased, and it does some damage to nearby mobs
- maybe only triggers at max energy
-
-mod - nano scale field could be a mod
- excess energy is converted to bullets
- run this code in the energy overfill code check
- possible issues
- worm hole, Penrose process - nerf a bit
- pair production - nerf and give it to anyone
- cloaking field - maybe just don't spawn bullets when cloaked
+add an ending to the game
+ maybe the game ending should ask you to open the console and type in some commands like in the end of doki doki
+ mirror ending (if no cheats)
+ level after final boss battle is the intro level, but flipped left right, with a fake player
+ damage the fake player to end the game
+ message about go outside
+ no ending (if cheats)
+ game goes on forever
+ also game goes on if player attacks, the fake player
+ game never ends if you have used cheats
Mod: "Solar Power": Energy regeneration is doubled while standing still
run in the 1 second check
-mod - a bot that eats up health and ammo, but poops out a mod (10 power ups = 1 mod?)
- or it poops a reroll after picking up 2 heal/ammo
- requires the reroll -> bot mod
- 4 rerolls can convert to a bot, also 1 rerolls can convert to 5% damage
- the mods that do those effects could be required before you see this bot
- it passes through walls
- moves slower then the player so you can get to it before the bot if you hurry
- disable crystalized armor?
-
mod: take less harm if you are in the air
require squirrel cage rotor
-Laser mod: For each reflection of laser, damage increases by 10%
-
mechanic - remove a random mod as a condition for picking up a really good mod
mechanic - do something for 2 seconds after firing
@@ -80,10 +70,6 @@ mod - do 50% more damage in close, but 50% less at a distance
code it like mod.isFarAwayDmg
have these mods disable each other
-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?
-
mod - foam is attracted to mobs
use a gravitational attraction model?
could foam be attracted to other foam bullets too?
@@ -105,21 +91,11 @@ repeat map in vertical and horizontal space
or at least vertical space
camera looks strange when you teleport player with a high velocity
-add an ending to the game
- maybe the game ending should ask you to open the console and type in some commands like in the end of doki doki
- mirror ending (if no cheats)
- level after final boss battle is the intro level, but flipped left right, with a fake player
- damage the fake player to end the game
- message about go outside
- no ending (if cheats)
- game goes on forever
- also game goes on if player attacks, the fake player
- game never ends if you have used cheats
-
new status effect: fear - push mob away from player for a time
new status effect - apply status effect to mobs that makes blocks attracted to them
only lasts a few cycles
+ or zero cycles and it doesn't need to be a status
have some mobs spawn in later in the level (in hard and why modes)
where