diff --git a/.DS_Store b/.DS_Store
index 0b7e3ce..2b50f2e 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/js/bullet.js b/js/bullet.js
index ca11b16..a1c34bb 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -3205,7 +3205,7 @@ const b = {
range: (700 + 400 * tech.isLaserBotUpgrade) * (1 + 0.1 * Math.random()),
drainThreshold: tech.isEnergyHealth ? 0.6 : 0.4,
drain: (0.56 - 0.42 * tech.isLaserBotUpgrade) * tech.laserFieldDrain * tech.isLaserDiode,
- laserDamage: 0.6 + 0.43 * tech.isLaserBotUpgrade,
+ laserDamage: 0.7 + 0.5 * tech.isLaserBotUpgrade,
endCycle: Infinity,
classType: "bullet",
collisionFilter: {
@@ -3916,21 +3916,21 @@ const b = {
}
}
} else if (tech.isWormShot) {
- const unit = {
- x: Math.cos(m.angle),
- y: Math.sin(m.angle)
- }
const where = {
- x: m.pos.x + 35 * unit.x,
- y: m.pos.y + 35 * unit.y
+ x: m.pos.x + 35 * Math.cos(m.angle),
+ y: m.pos.y + 35 * Math.sin(m.angle)
}
- for (let i = 0, len = 3 * (tech.isShotgunReversed ? 1.6 : 1) + Math.random(); i < len; i++) {
+ const spread = (m.crouch ? 0.04 : 0.08)
+ const number = 3 * (tech.isShotgunReversed ? 1.6 : 1) + Math.random()
+ let angle = m.angle - (number - 1) * spread * 0.5
+ for (let i = 0; i < number; i++) {
b.worm(where)
- const SPEED = 14 + 6 * Math.random() + 20 * m.crouch;
+ const SPEED = (16 + 20 * m.crouch) * (1 + 0.15 * Math.random())
Matter.Body.setVelocity(bullet[bullet.length - 1], {
- x: SPEED * unit.x,
- y: SPEED * unit.y
+ x: SPEED * Math.cos(angle),
+ y: SPEED * Math.sin(angle)
});
+ angle += spread
}
} else if (tech.isIceShot) {
const spread = (m.crouch ? 0.7 : 1.2)
@@ -4131,7 +4131,7 @@ const b = {
ctx.strokeStyle = "rgba(0,0,0,0.6)" //"000";
ctx.lineWidth = 2 * tech.wavePacketDamage
ctx.beginPath();
- const end = 750 * Math.sqrt(tech.isBulletsLastLonger) / Math.sqrt(tech.waveReflections * 0.5) //should equal about 1060
+ const end = 700 * Math.sqrt(tech.isBulletsLastLonger) / Math.sqrt(tech.waveReflections * 0.5) //should equal about 1060
const damage = 2 * b.dmgScale * tech.wavePacketDamage * tech.waveBeamDamage //damage is lower for large radius mobs, since they feel the waves longer
for (let i = this.waves.length - 1; i > -1; i--) {
@@ -4213,7 +4213,7 @@ const b = {
ctx.strokeStyle = "rgba(0,0,0,0.6)" //"000";
ctx.lineWidth = 2 * tech.wavePacketDamage
ctx.beginPath();
- const end = 1250 * tech.isBulletsLastLonger / Math.sqrt(tech.waveReflections * 0.5) //should equal about 1767
+ const end = 1100 * tech.isBulletsLastLonger / Math.sqrt(tech.waveReflections * 0.5) //should equal about 1767
const damage = 2 * b.dmgScale * tech.wavePacketDamage * tech.waveBeamDamage //damage is lower for large radius mobs, since they feel the waves longer
for (let i = this.waves.length - 1; i > -1; i--) {
diff --git a/js/index.js b/js/index.js
index 91e59b5..0017e50 100644
--- a/js/index.js
+++ b/js/index.js
@@ -30,11 +30,11 @@ function shuffle(array) {
return array;
}
-// shrink power up selection menu to find window height
-if (screen.height < 800) {
- document.getElementById("choose-grid").style.fontSize = "1em"; //1.3em is normal
- if (screen.height < 600) document.getElementById("choose-grid").style.fontSize = "0.8em"; //1.3em is normal
-}
+// shrink power up selection menu
+// if (screen.height < 800) {
+// document.getElementById("choose-grid").style.fontSize = "1em"; //1.3em is normal
+// if (screen.height < 600) document.getElementById("choose-grid").style.fontSize = "0.8em"; //1.3em is normal
+// }
//**********************************************************************
diff --git a/js/level.js b/js/level.js
index 44d0ebd..00616f2 100644
--- a/js/level.js
+++ b/js/level.js
@@ -16,7 +16,6 @@ const level = {
// simulation.isHorizontalFlipped = true
// m.setField("wormhole")
// b.giveGuns("shotgun")
- // b.giveGuns("foam")
// tech.isNeedleShot = true
// tech.isIceShot = true
// tech.isFoamShot = true
@@ -2264,15 +2263,21 @@ const level = {
spawn.mapRect(6400, -200, 400, 300); //right wall
spawn.mapRect(6700, -1800, 800, 2600); //right wall
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
-
- spawn.starter(1900, -500, 200) //big boy
+ //place to hide
+ spawn.mapRect(4650, -300, 1150, 50);
+ spawn.mapRect(5750, -300, 50, 200);
+ spawn.mapRect(5575, -100, 50, 125);
+ spawn.mapRect(5300, -275, 50, 175);
+ spawn.mapRect(5050, -100, 50, 150);
+ spawn.mapRect(4850, -275, 50, 175);
+ // spawn.starter(1900, -500, 200) //big boy
// spawn.growBossCulture(1900, -500)
+ // spawn.blinkBoss(1900, -500)
// spawn.snakeBoss(1900, -500)
- // spawn.shieldingBoss(1900, -500)
// spawn.grenadierBoss(1900, -500)
- // spawn.shieldingBoss(1900, -500)
+ spawn.sneaker(1900, -500)
// spawn.historyBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400)
// spawn.focuser(1600, -500)
@@ -2327,6 +2332,8 @@ const level = {
ctx.fillRect(5400, -550, 300, 350)
};
+ spawn.powerUpBoss(0, 0)
+ spawn.powerUpBoss(0, 0)
level.setPosToSpawn(0, -250); //normal spawn
spawn.mapRect(5500, -330 + 20, 100, 20); //spawn this because the real exit is in the wrong spot
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
@@ -2364,7 +2371,7 @@ const level = {
spawn.mapRect(5700, -3300, 1800, 5100); //right wall
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
spawn.mapRect(5425, -650, 375, 450); //blocking exit
- spawn.secondaryBossChance(4800, -500)
+ // spawn.secondaryBossChance(4800, -500) //no bonus bosses on final level
if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -3229,7 +3236,7 @@ const level = {
spawn.randomGroup(1600, -100, 0);
spawn.randomGroup(5000, -3900, -0.3);
if (simulation.difficulty > 3) {
- if (Math.random() < 0.2) {
+ if (Math.random() < 0.25) {
spawn.randomLevelBoss(2800, -1400);
} else if (Math.random() < 0.25) {
spawn.laserBoss(2900 + 300 * Math.random(), -2950 + 150 * Math.random());
@@ -3606,7 +3613,7 @@ const level = {
spawn.randomMob(3975, -3900, 0.5);
spawn.randomMob(1725, 125, 0.5);
if (simulation.difficulty > 3) {
- if (Math.random() < 0.25) {
+ if (Math.random() < 0.33) {
spawn.randomLevelBoss(4250, -250);
spawn.debris(-250, 50, 1650, 2); //16 debris per level
spawn.debris(2475, 0, 750, 2); //16 debris per level
@@ -4349,7 +4356,7 @@ const level = {
spawn.randomSmallMob(-900, 825);
if (simulation.difficulty > 3) {
- if (Math.random() < 0.25) {
+ if (Math.random() < 0.33) {
spawn.randomLevelBoss(-800, -1300)
} else {
spawn.snakeBoss(-1000 + Math.random() * 2500, -1300); //boss snake with head
diff --git a/js/mob.js b/js/mob.js
index 9fd8d6c..ff26cb6 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -284,7 +284,7 @@ const mobs = {
},
memory: 120, //default time to remember player's location
locatePlayer() { // updates mob's memory of player location
- this.seePlayer.recall = this.memory + Math.round(this.memory * Math.random()); //seconds before mob falls a sleep
+ this.seePlayer.recall = this.memory + Math.round(this.memory * Math.random()); //cycles before mob falls a sleep
this.seePlayer.position.x = player.position.x;
this.seePlayer.position.y = player.position.y;
},
@@ -309,12 +309,38 @@ const mobs = {
// this.seePlayer.position.y = player.position.y;
// }
// },
+ seePlayerByHistory(depth = 30) { //depth max 60? limit of history
+ if (!(simulation.cycle % this.seePlayerFreq)) {
+ if (Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 && !m.isCloak) {
+ this.foundPlayer();
+ } else if (this.seePlayer.recall) {
+ this.lostPlayer();
+ for (let i = 0; i < depth; i++) { //if lost player lock onto a player location in history
+ let history = m.history[(m.cycle - 10 * i) % 600]
+ if (Matter.Query.ray(map, this.position, history.position).length === 0) {
+ this.seePlayer.recall = this.memory + Math.round(this.memory * Math.random()); //cycles before mob falls a sleep
+ this.seePlayer.position.x = history.position.x;
+ this.seePlayer.position.y = history.position.y;
+ this.seePlayer.yes = true;
+ //draw the history location found for testing purposes
+ // ctx.beginPath();
+ // ctx.moveTo(this.position.x, this.position.y);
+ // ctx.lineTo(history.position.x, history.position.y);
+ // ctx.lineWidth = 5;
+ // ctx.strokeStyle = "#000";
+ // ctx.stroke();
+ break
+ }
+ }
+ }
+ }
+ },
seePlayerCheck() {
if (!(simulation.cycle % this.seePlayerFreq)) {
if (
this.distanceToPlayer2() < this.seeAtDistance2 &&
- Matter.Query.ray(map, this.position, this.mPosRange()).length === 0 &&
- // Matter.Query.ray(body, this.position, this.mPosRange()).length === 0 &&
+ Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 &&
+ // Matter.Query.ray(body, this.position, this.playerPosRandomY()).length === 0 &&
!m.isCloak
) {
this.foundPlayer();
@@ -335,7 +361,7 @@ const mobs = {
seePlayerByDistOrLOS() {
if (!(simulation.cycle % this.seePlayerFreq)) {
if (
- (this.distanceToPlayer2() < this.seeAtDistance2 || (Matter.Query.ray(map, this.position, this.mPosRange()).length === 0 && Matter.Query.ray(body, this.position, this.mPosRange()).length === 0)) &&
+ (this.distanceToPlayer2() < this.seeAtDistance2 || (Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 && Matter.Query.ray(body, this.position, this.playerPosRandomY()).length === 0)) &&
!m.isCloak
) {
this.foundPlayer();
@@ -366,8 +392,8 @@ const mobs = {
if (!(simulation.cycle % this.seePlayerFreq) && (this.seePlayer.recall || this.isLookingAtPlayer(this.lookRange))) {
if (
this.distanceToPlayer2() < this.seeAtDistance2 &&
- Matter.Query.ray(map, this.position, this.mPosRange()).length === 0 &&
- // Matter.Query.ray(body, this.position, this.mPosRange()).length === 0 &&
+ Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 &&
+ // Matter.Query.ray(body, this.position, this.playerPosRandomY()).length === 0 &&
!m.isCloak
) {
this.foundPlayer();
@@ -387,7 +413,7 @@ const mobs = {
ctx.fill();
}
},
- mPosRange() {
+ playerPosRandomY() {
return {
x: player.position.x, // + (Math.random() - 0.5) * 50,
y: player.position.y + (Math.random() - 0.5) * 110
@@ -412,7 +438,7 @@ const mobs = {
// this.force = Vector.mult(Vector.normalise(Vector.sub(this.hackedTarget.position, this.position)), this.mass * 0.0015)
// }
// },
- laserBeam() {
+ harmZone() {
if (this.seePlayer.yes) {
ctx.setLineDash([125 * Math.random(), 125 * Math.random()]);
// ctx.lineDashOffset = 6*(simulation.cycle % 215);
@@ -879,8 +905,8 @@ const mobs = {
if (
!(simulation.cycle % this.fireFreq) &&
Math.abs(this.position.x - this.seePlayer.position.x) < 400 && //above player
- Matter.Query.ray(map, this.position, this.mPosRange()).length === 0 && //see player
- Matter.Query.ray(body, this.position, this.mPosRange()).length === 0
+ Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 && //see player
+ Matter.Query.ray(body, this.position, this.playerPosRandomY()).length === 0
) {
spawn.bomb(this.position.x, this.position.y + this.radius * 0.7, 9 + Math.ceil(this.radius / 15), 5);
//add spin and speed
diff --git a/js/player.js b/js/player.js
index ac050cd..7f02a13 100644
--- a/js/player.js
+++ b/js/player.js
@@ -1462,7 +1462,8 @@ const m = {
},
fieldUpgrades: [{
name: "field emitter",
- description: "use energy to deflect mobs,
grab power ups, and throw blocks
regen 6 energy per second",
+ description: "regen 6 energy per second
use it to deflect mobs and throw blocks
energy regen disabled if immune to harm",
+ // description: "use energy to deflect mobs,
grab power ups, and throw blocks
regen 6 energy/s, when not immune to harm",
effect: () => {
m.hold = function() {
if (m.isHolding) {
diff --git a/js/spawn.js b/js/spawn.js
index a984af9..9f56c62 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -1,7 +1,7 @@
//main object for spawning things in a level
const spawn = {
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture", "growBossCulture"],
- randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture"]) {
+ randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss"]) {
// other bosses: suckerBoss, laserBoss, tetherBoss, //these need a particular level to work so they are not included in the random pool
spawn[options[Math.floor(Math.random() * options.length)]](x, y)
},
@@ -17,8 +17,8 @@ const spawn = {
"launcher", "launcher",
"springer", "springer",
"pulsar", "pulsar",
+ "sneaker", "sneaker",
"sucker",
- "chaser",
"sniper",
"spinner",
"grower",
@@ -26,9 +26,8 @@ const spawn = {
"focuser",
"spawner",
"ghoster",
- "sneaker",
],
- allowedGroupList: ["chaser", "spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "stabber", "sniper", "pulsar", "grenadier"],
+ allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "stabber", "sniper", "pulsar", "grenadier"],
setSpawnList() { //this is run at the start of each new level to determine the possible mobs for the level
//each level has 2 mobs: one new mob and one from the last level
spawn.pickList.splice(0, 1);
@@ -366,8 +365,10 @@ const spawn = {
Matter.Body.setVelocity(body[i], Vector.add(body[i].velocity, pushUp));
}
//damage all mobs
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (mob[i] !== this) mob[i].damage(Infinity, true);
+ for (let j = 0; j < 8; j++) { //in case some mobs leave things after they die
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (mob[i] !== this) mob[i].damage(Infinity, true);
+ }
}
//draw stuff
@@ -1016,23 +1017,23 @@ const spawn = {
this.checkStatus();
};
},
- chaser(x, y, radius = 35 + Math.ceil(Math.random() * 40)) {
- mobs.spawn(x, y, 8, radius, "rgb(255,150,100)"); //"#2c9790"
- let me = mob[mob.length - 1];
- // Matter.Body.setDensity(me, 0.0007); //extra dense //normal is 0.001 //makes effective life much lower
- me.friction = 0.1;
- me.frictionAir = 0;
- me.accelMag = 0.001 * Math.sqrt(simulation.accelScale);
- me.g = me.accelMag * 0.6; //required if using 'gravity'
- me.memory = 50;
- spawn.shield(me, x, y);
- me.do = function() {
- this.gravity();
- this.seePlayerCheck();
- this.checkStatus();
- this.attraction();
- };
- },
+ // chaser(x, y, radius = 35 + Math.ceil(Math.random() * 40)) {
+ // mobs.spawn(x, y, 8, radius, "rgb(255,150,100)"); //"#2c9790"
+ // let me = mob[mob.length - 1];
+ // // Matter.Body.setDensity(me, 0.0007); //extra dense //normal is 0.001 //makes effective life much lower
+ // me.friction = 0.1;
+ // me.frictionAir = 0;
+ // me.accelMag = 0.001 * Math.sqrt(simulation.accelScale);
+ // me.g = me.accelMag * 0.6; //required if using 'gravity'
+ // me.memory = 180;
+ // spawn.shield(me, x, y);
+ // me.do = function() {
+ // this.gravity();
+ // this.seePlayerByHistory(15);
+ // this.checkStatus();
+ // this.attraction();
+ // };
+ // },
grower(x, y, radius = 15) {
mobs.spawn(x, y, 7, radius, "hsl(144, 15%, 50%)");
let me = mob[mob.length - 1];
@@ -1653,7 +1654,7 @@ const spawn = {
this.checkStatus();
this.attraction();
this.repulsion();
- this.laserBeam();
+ this.harmZone();
};
},
historyBoss(x, y, radius = 30) {
@@ -1968,6 +1969,63 @@ const spawn = {
}
};
},
+ blinkBoss(x, y) {
+ mobs.spawn(x, y, 5, 50, "rgb(215,80,190)"); //"rgb(221,102,119)"
+ let me = mob[mob.length - 1];
+ Matter.Body.rotate(me, Math.PI * 0.1);
+ Matter.Body.setDensity(me, 0.01); //extra dense //normal is 0.001 //makes effective life much larger
+ me.isBoss = true;
+ me.damageReduction = 0.25;
+ me.frictionStatic = 0;
+ me.friction = 0;
+ me.memory = 240
+ me.seePlayerFreq = 60
+ me.delay = 20 + 20 * simulation.CDScale;
+ me.nextBlinkCycle = me.delay;
+ me.blinkRange = 235
+ me.grenadeDelay = 30 + 50 * simulation.CDScale
+ me.pulseRadius = 2 * Math.min(550, 250 + simulation.difficulty * 3)
+ spawn.shield(me, x, y, 1);
+ me.onDamage = function() {
+ // this.cd = simulation.cycle + this.delay;
+ };
+ me.onDeath = function() {
+ const offAngle = Math.PI * Math.random()
+ for (let i = 0, len = 3; i < len; i++) {
+ spawn.grenade(this.position.x, this.position.y, this.grenadeDelay);
+ const who = mob[mob.length - 1]
+ const speed = 5 * simulation.accelScale;
+ const angle = 2 * Math.PI * i / len + offAngle
+ Matter.Body.setVelocity(who, {
+ x: speed * Math.cos(angle),
+ y: speed * Math.sin(angle)
+ });
+ }
+ }
+ me.do = function() {
+ this.seePlayerByHistory()
+ if (this.nextBlinkCycle < simulation.cycle && this.seePlayer.yes) { //teleport towards the player
+ this.nextBlinkCycle = simulation.cycle + this.delay;
+ const dist = Vector.sub(this.seePlayer.position, this.position);
+ const distMag = Vector.magnitude(dist);
+ ctx.beginPath();
+ ctx.moveTo(this.position.x, this.position.y);
+ if (distMag < this.blinkRange) { //if player is inside teleport range
+ Matter.Body.setPosition(this, this.seePlayer.position);
+ } else {
+ Matter.Body.translate(this, Vector.mult(Vector.normalise(dist), this.blinkRange));
+ }
+ spawn.grenade(this.position.x, this.position.y, this.grenadeDelay, this.pulseRadius); //spawn at new location
+ ctx.lineTo(this.position.x, this.position.y);
+ ctx.lineWidth = this.radius * 2.1;
+ ctx.strokeStyle = this.fill; //"rgba(0,0,0,0.5)"; //'#000'
+ ctx.stroke();
+ Matter.Body.setVelocity(this, { x: 0, y: 0 });
+ this.torque += (0.00004 + 0.00003 * Math.random()) * this.inertia * (Math.round(Math.random()) * 2 - 1) //randomly spin around after firing
+ }
+ this.checkStatus();
+ };
+ },
pulsarBoss(x, y, radius = 90) {
mobs.spawn(x, y, 3, radius, "#a0f");
let me = mob[mob.length - 1];
@@ -2461,6 +2519,7 @@ const spawn = {
}
};
},
+
striker(x, y, radius = 14 + Math.ceil(Math.random() * 25)) {
mobs.spawn(x, y, 5, radius, "rgb(221,102,119)");
let me = mob[mob.length - 1];
@@ -2480,8 +2539,8 @@ const spawn = {
if (!(simulation.cycle % this.seePlayerFreq)) { // this.seePlayerCheck(); from mobs
if (
this.distanceToPlayer2() < this.seeAtDistance2 &&
- Matter.Query.ray(map, this.position, this.mPosRange()).length === 0 &&
- // Matter.Query.ray(body, this.position, this.mPosRange()).length === 0 &&
+ Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 &&
+ // Matter.Query.ray(body, this.position, this.playerPosRandomY()).length === 0 &&
!m.isCloak
) {
this.foundPlayer();
@@ -2493,35 +2552,33 @@ const spawn = {
}
this.checkStatus();
this.attraction();
- if (this.cd < simulation.cycle) {
- if (this.seePlayer.recall) {
- const dist = Vector.sub(this.seePlayer.position, this.position);
- const distMag = Vector.magnitude(dist);
- this.cd = simulation.cycle + this.delay;
- ctx.beginPath();
- ctx.moveTo(this.position.x, this.position.y);
- if (distMag < 400) {
- Matter.Body.translate(this, Vector.mult(Vector.normalise(dist), distMag - 20 - radius));
- } else {
- Matter.Body.translate(this, Vector.mult(Vector.normalise(dist), 300));
- }
- ctx.lineTo(this.position.x, this.position.y);
- ctx.lineWidth = radius * 2.1;
- ctx.strokeStyle = this.fill; //"rgba(0,0,0,0.5)"; //'#000'
- ctx.stroke();
- Matter.Body.setVelocity(this, {
- x: this.velocity.x * 0.5,
- y: this.velocity.y * 0.5
- });
+ if (this.cd < simulation.cycle && this.seePlayer.recall) {
+ const dist = Vector.sub(this.seePlayer.position, this.position);
+ const distMag = Vector.magnitude(dist);
+ this.cd = simulation.cycle + this.delay;
+ ctx.beginPath();
+ ctx.moveTo(this.position.x, this.position.y);
+ if (distMag < 400) {
+ Matter.Body.translate(this, Vector.mult(Vector.normalise(dist), distMag - 20 - radius));
+ } else {
+ Matter.Body.translate(this, Vector.mult(Vector.normalise(dist), 300));
}
+ ctx.lineTo(this.position.x, this.position.y);
+ ctx.lineWidth = radius * 2.1;
+ ctx.strokeStyle = this.fill; //"rgba(0,0,0,0.5)"; //'#000'
+ ctx.stroke();
+ Matter.Body.setVelocity(this, {
+ x: this.velocity.x * 0.5,
+ y: this.velocity.y * 0.5
+ });
}
};
},
- sneaker(x, y, radius = 15 + Math.ceil(Math.random() * 25)) {
+ sneaker(x, y, radius = 15 + Math.ceil(Math.random() * 10)) {
mobs.spawn(x, y, 5, radius, "transparent");
let me = mob[mob.length - 1];
- Matter.Body.setDensity(me, 0.001); //extra dense //normal is 0.001 //makes effective life much larger
- me.accelMag = 0.0012 * Math.sqrt(simulation.accelScale);
+ Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
+ me.accelMag = 0.001 * Math.sqrt(simulation.accelScale);
me.frictionAir = 0.01;
me.g = 0.0002; //required if using 'gravity'
me.stroke = "transparent"; //used for drawSneaker
@@ -2530,16 +2587,16 @@ const spawn = {
me.canTouchPlayer = false; //used in drawSneaker
me.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player
me.showHealthBar = false;
- // me.memory = 420;
+ me.memory = 240;
me.do = function() {
this.gravity();
- this.seePlayerCheck();
+ this.seePlayerByHistory(15);
this.checkStatus();
this.attraction();
//draw
if (!m.isBodiesAsleep) {
- if (this.seePlayer.yes) {
- if (this.alpha < 1) this.alpha += 0.01 / simulation.CDScale;
+ if (this.seePlayer.recall) {
+ if (this.alpha < 1) this.alpha += 0.003 + 0.003 / simulation.CDScale;
} else {
if (this.alpha > 0) this.alpha -= 0.03;
}
@@ -2562,7 +2619,7 @@ const spawn = {
ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.fillStyle = `rgba(0,0,0,${this.alpha * this.alpha})`;
ctx.fill();
- } else if (this.canTouchPlayer) {
+ } else if (this.canTouchPlayer) { //stealth
this.canTouchPlayer = false;
this.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player
}
@@ -3111,15 +3168,13 @@ const spawn = {
Matter.Body.setDensity(me, 0.004 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.onDeath = function() { //helps collisions functions work better after vertex have been changed
for (let i = 0; i < 6; i++) {
- spawn.grenade(this.position.x, this.position.y, 2, 4, 75 * simulation.CDScale);
+ spawn.grenade(this.position.x, this.position.y, 75 * simulation.CDScale);
const who = mob[mob.length - 1]
- // who.collisionFilter.category = 0
- who.collisionFilter.mask = cat.player | cat.map;
const speed = 4 * simulation.accelScale;
const angle = 2 * Math.PI * i / 6
Matter.Body.setVelocity(who, {
- x: this.velocity.x + speed * Math.cos(angle),
- y: this.velocity.y + speed * Math.sin(angle)
+ x: speed * Math.cos(angle),
+ y: speed * Math.sin(angle)
});
}
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
@@ -3128,10 +3183,8 @@ const spawn = {
me.onDamage = function() {
if (this.grenadeLimiter < 240) {
this.grenadeLimiter += 60
- spawn.grenade(this.position.x, this.position.y, 2, 4, 80 + Math.floor(60 * Math.random()));
+ spawn.grenade(this.position.x, this.position.y, 80 + Math.floor(60 * Math.random()));
const who = mob[mob.length - 1]
- // who.collisionFilter.category = 0
- who.collisionFilter.mask = cat.player | cat.map;
const velocity = Vector.mult(Vector.normalise(Vector.sub(player.position, who.position)), 3 * Math.sqrt(simulation.accelScale) + 4 * Math.random())
Matter.Body.setVelocity(who, {
x: this.velocity.x + velocity.x,
@@ -3167,7 +3220,7 @@ const spawn = {
y: 0
};
me.onDeath = function() { //helps collisions functions work better after vertex have been changed
- spawn.grenade(this.position.x, this.position.y, 2, 4, 75 * simulation.CDScale);
+ spawn.grenade(this.position.x, this.position.y, 75 * simulation.CDScale);
// mob[mob.length - 1].collisionFilter.category = 0
mob[mob.length - 1].collisionFilter.mask = cat.player | cat.map;
}
@@ -3224,8 +3277,8 @@ const spawn = {
}
};
},
- grenade(x, y, radius = 2, sides = 4, lifeSpan = 90 + Math.ceil(60 / simulation.accelScale)) {
- mobs.spawn(x, y, sides, radius, "rgb(215,0,190)"); //rgb(215,80,190)
+ grenade(x, y, lifeSpan = 90 + Math.ceil(60 / simulation.accelScale), pulseRadius = Math.min(550, 250 + simulation.difficulty * 3)) {
+ mobs.spawn(x, y, 4, 2, "rgb(215,0,190)"); //rgb(215,80,190)
let me = mob[mob.length - 1];
me.stroke = "transparent";
me.onHit = function() {
@@ -3241,28 +3294,28 @@ const spawn = {
me.leaveBody = false;
me.isDropPowerUp = false;
me.isBadTarget = true;
- me.pulseRadius = Math.min(550, 250 + simulation.difficulty * 3)
me.onDeath = function() {
//damage player if in range
- if (Vector.magnitude(Vector.sub(player.position, this.position)) < this.pulseRadius && m.immuneCycle < m.cycle) {
+ if (Vector.magnitude(Vector.sub(player.position, this.position)) < pulseRadius && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
m.damage(0.02 * simulation.dmgScale);
}
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
- radius: this.pulseRadius,
+ radius: pulseRadius,
color: "rgba(255,0,220,0.3)",
time: simulation.drawTime
});
};
me.showHealthBar = false;
me.collisionFilter.category = cat.mobBullet;
- me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
+ // me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
+ me.collisionFilter.mask = 0
me.do = function() {
this.timeLimit();
ctx.beginPath(); //draw explosion outline
- ctx.arc(this.position.x, this.position.y, this.pulseRadius * (1.01 - this.timeLeft / this.lifeSpan), 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay
+ ctx.arc(this.position.x, this.position.y, pulseRadius * (1.01 - this.timeLeft / this.lifeSpan), 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay
ctx.fillStyle = "rgba(255,0,220,0.05)";
ctx.fill();
};
@@ -3507,8 +3560,8 @@ const spawn = {
// if (!(simulation.cycle % this.seePlayerFreq)) {
// if (
// this.distanceToPlayer2() < this.seeAtDistance2 &&
- // Matter.Query.ray(map, this.position, this.mPosRange()).length === 0 &&
- // Matter.Query.ray(body, this.position, this.mPosRange()).length === 0 &&
+ // Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 &&
+ // Matter.Query.ray(body, this.position, this.playerPosRandomY()).length === 0 &&
// !m.isCloak
// ) {
// this.foundPlayer();
@@ -3552,7 +3605,7 @@ const spawn = {
this.attraction();
};
},
- snakeBoss(x, y, radius = 75) { //snake boss with a laser head
+ snakeBoss(x, y, radius = 60) { //snake boss with a laser head
const color1 = "#f27"
mobs.spawn(x, y, 8, radius, color1); //"rgb(55,170,170)"
let me = mob[mob.length - 1];
@@ -3561,7 +3614,7 @@ const spawn = {
me.accelMag = 0.00075 * simulation.accelScale;
me.memory = 250;
me.laserRange = 500;
- Matter.Body.setDensity(me, 0.001 + 0.0001 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
+ Matter.Body.setDensity(me, 0.0016 + 0.0001 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
for (let i = 0; i < mob.length; i++) { //wake up tail mobs
@@ -3573,10 +3626,11 @@ const spawn = {
}
};
me.do = function() {
- this.seePlayerCheck();
+ // this.seePlayerCheck();
+ this.seePlayerByHistory()
this.checkStatus();
this.attraction();
- this.laserBeam();
+ this.harmZone();
};
//snake tail
diff --git a/js/tech.js b/js/tech.js
index 80ed29d..b337e3e 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -1018,6 +1018,7 @@
maxCount: 3,
count: 0,
frequency: 1,
+ frequencyDefault: 1,
isBotTech: true,
allowed() {
return !tech.sporesOnDeath && !tech.nailsDeathMob && !tech.isExplodeMob && !tech.isMobBlockFling && !tech.iceIXOnDeath
@@ -1036,6 +1037,7 @@
maxCount: 1,
count: 0,
frequency: 1,
+ frequencyDefault: 1,
isBotTech: true,
allowed() {
return tech.botSpawner
@@ -1054,6 +1056,7 @@
maxCount: 9,
count: 0,
frequency: 1,
+ frequencyDefault: 1,
isBot: true,
isBotTech: true,
allowed() {
@@ -1078,6 +1081,7 @@
maxCount: 1,
count: 0,
frequency: 2,
+ frequencyDefault: 2,
isBotTech: true,
allowed() {
return tech.nailBotCount > 1 && !b.hasBotUpgrade()
@@ -1103,6 +1107,7 @@
maxCount: 9,
count: 0,
frequency: 1,
+ frequencyDefault: 1,
isBot: true,
isBotTech: true,
allowed() {
@@ -1127,6 +1132,7 @@
maxCount: 1,
count: 0,
frequency: 2,
+ frequencyDefault: 2,
isBotTech: true,
allowed() {
return tech.foamBotCount > 1 && !b.hasBotUpgrade()
@@ -1152,6 +1158,7 @@
maxCount: 9,
count: 0,
frequency: 1,
+ frequencyDefault: 1,
isBot: true,
isBotTech: true,
allowed() {
@@ -1176,6 +1183,7 @@
maxCount: 1,
count: 0,
frequency: 2,
+ frequencyDefault: 2,
isBotTech: true,
allowed() {
return tech.boomBotCount > 1 && !b.hasBotUpgrade()
@@ -1201,6 +1209,7 @@
maxCount: 9,
count: 0,
frequency: 1,
+ frequencyDefault: 1,
isBot: true,
isBotTech: true,
allowed() {
@@ -1225,6 +1234,7 @@
maxCount: 1,
count: 0,
frequency: 2,
+ frequencyDefault: 2,
isBotTech: true,
allowed() {
return tech.laserBotCount > 1 && !b.hasBotUpgrade()
@@ -1250,7 +1260,7 @@
maxCount: 9,
count: 0,
frequency: 1,
-
+ frequencyDefault: 1,
isBot: true,
isBotTech: true,
allowed() {
@@ -1275,6 +1285,7 @@
maxCount: 1,
count: 0,
frequency: 2,
+ frequencyDefault: 2,
isBotTech: true,
allowed() {
return tech.orbitBotCount > 1 && !b.hasBotUpgrade()
@@ -1310,6 +1321,7 @@
maxCount: 9,
count: 0,
frequency: 1,
+ frequencyDefault: 1,
isBot: true,
isBotTech: true,
allowed() {
@@ -1334,6 +1346,7 @@
maxCount: 1,
count: 0,
frequency: 2,
+ frequencyDefault: 2,
isBotTech: true,
allowed() {
return tech.dynamoBotCount > 1 && !b.hasBotUpgrade()
@@ -1359,6 +1372,7 @@
maxCount: 1,
count: 0,
frequency: 2,
+ frequencyDefault: 2,
isBotTech: true,
allowed() {
return powerUps.research.count > 2 || build.isExperimentSelection
@@ -1379,6 +1393,7 @@
maxCount: 1,
count: 0,
frequency: 1,
+ frequencyDefault: 1,
isBotTech: true,
allowed() {
return (b.totalBots() > 1 && powerUps.research.count > 0) || build.isExperimentSelection
@@ -1407,6 +1422,7 @@
maxCount: 1,
count: 0,
frequency: 2,
+ frequencyDefault: 2,
isBotTech: true,
allowed() {
return b.totalBots() > 3 && !tech.isEnergyHealth
@@ -1425,6 +1441,7 @@
maxCount: 1,
count: 0,
frequency: 2,
+ frequencyDefault: 2,
isBotTech: true,
allowed() {
return b.totalBots() > 3
@@ -1443,6 +1460,7 @@
maxCount: 1,
count: 0,
frequency: 2,
+ frequencyDefault: 2,
isBotTech: true,
// isNonRefundable: true,
isBadRandomOption: true,
@@ -3454,7 +3472,7 @@
},
{
name: "ceramic needles",
- description: `your needles pierce shields
directly damaging shielded mobs`,
+ description: `needles pierce shields
directly damaging shielded mobs`,
isGunTech: true,
maxCount: 1,
count: 0,
@@ -3506,7 +3524,7 @@
},
{
name: "rivet diameter",
- description: `your rivets are 20% larger
increases mass and physical damage`,
+ description: `rivets are 20% larger
increases mass and physical damage`,
isGunTech: true,
maxCount: 9,
count: 0,
@@ -3769,7 +3787,7 @@
},
{
name: "shotgun slug",
- description: "the shotgun fires a huge dense bullet",
+ description: "shotgun lobs 1 huge bullet",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -3788,7 +3806,7 @@
},
{
name: "nail-shot",
- description: "the shotgun fires a burst of nails",
+ description: "shotgun fires 17 nails",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -3807,7 +3825,7 @@
},
{
name: "worm-shot",
- description: "the shotgun fires 3-4 worms", //
worms seek out nearby mobs
+ description: "shotgun hatches 3-4 mob seeking worms", //
worms seek out nearby mobs
isGunTech: true,
maxCount: 1,
count: 0,
@@ -3826,7 +3844,7 @@
},
{
name: "foam-shot",
- description: "the shotgun fires 13 foam bubbles",
+ description: "shotgun sprays 13 sticky foam bubbles",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -3845,7 +3863,7 @@
},
{
name: "ice-shot",
- description: "the shotgun fires 18 ice IX crystals",
+ description: "shotgun grows 18 freezing ice IX crystals",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -3864,7 +3882,7 @@
},
{
name: "needle-shot",
- description: "the shotgun fires 12 mob piercing needles",
+ description: "shotgun propels 12 mob piercing needles",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -3956,7 +3974,7 @@
},
{
name: "super sized",
- description: `your super balls are 20% larger
increases mass and physical damage`,
+ description: `super balls are 20% larger
increases mass and physical damage`,
isGunTech: true,
maxCount: 9,
count: 0,
@@ -4569,7 +4587,7 @@
},
{
name: "irradiated drones",
- description: "irradiate the space around your drones
reduce ammo/efficiency by 75%",
+ description: "the space around drones is irradiated
reduce ammo/efficiency by 75%",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -4880,7 +4898,7 @@
},
{
name: "diffraction grating",
- description: `your laser gains a diverging beam`,
+ description: `laser gains a diverging beam`,
isGunTech: true,
maxCount: 9,
count: 0,
@@ -5048,8 +5066,8 @@
isFieldTech: true,
maxCount: 1,
count: 0,
- frequency: 2,
- frequencyDefault: 2,
+ frequency: 3,
+ frequencyDefault: 3,
allowed() {
return (m.fieldUpgrades[m.fieldMode].name === "standing wave harmonics" || m.fieldUpgrades[m.fieldMode].name === "pilot wave") && (build.isExperimentSelection || powerUps.research.count > 1)
},
@@ -5193,8 +5211,8 @@
isFieldTech: true,
maxCount: 1,
count: 0,
- frequency: 2,
- frequencyDefault: 2,
+ frequency: 3,
+ frequencyDefault: 3,
allowed() {
return (m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" || m.fieldUpgrades[m.fieldMode].name === "negative mass field") && (build.isExperimentSelection || powerUps.research.count > 3)
},
@@ -5508,7 +5526,8 @@
isFieldTech: true,
maxCount: 1,
count: 0,
- frequency: 2,
+ frequency: 3,
+ frequencyDefault: 3,
isBot: true,
isBotTech: true,
allowed() {
@@ -5613,8 +5632,8 @@
isFieldTech: true,
maxCount: 1,
count: 0,
- frequency: 2,
- frequencyDefault: 2,
+ frequency: 3,
+ frequencyDefault: 3,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "time dilation" && (build.isExperimentSelection || powerUps.research.count > 2)
},
@@ -5699,8 +5718,8 @@
isFieldTech: true,
maxCount: 1,
count: 0,
- frequency: 2,
- frequencyDefault: 2,
+ frequency: 3,
+ frequencyDefault: 3,
allowed() {
return (m.fieldUpgrades[m.fieldMode].name === "metamaterial cloaking" || m.fieldUpgrades[m.fieldMode].name === "pilot wave") && (build.isExperimentSelection || powerUps.research.count > 0)
},
@@ -5802,8 +5821,8 @@
isFieldTech: true,
maxCount: 1,
count: 0,
- frequency: 2,
- frequencyDefault: 2,
+ frequency: 3,
+ frequencyDefault: 3,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "wormhole" && (build.isExperimentSelection || powerUps.research.count > 2) && tech.duplicationChance() < 1
},
diff --git a/todo.txt b/todo.txt
index 3ae1763..0aef0a1 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,16 +1,12 @@
******************************************************** NEXT PATCH ********************************************************
-shotgun balance
- ice-shot: less spread, higher damage, more crystals
- needle-shot: more needles, higher damage, less spread
- foam-shot: 1 more bubble
-
-power up selection and pause menu elements scroll individually now
- it looks great on my computer, but different operating systems and browsers are unpredictable
- let me know if text is hidden or if it doesn't scroll for you and what OS and browser you're on
******************************************************** TODO ********************************************************
+block shattering
+ get code from planetesimals
+ https://codepen.io/lilgreenland/pen/jrMvaB?editors=0010
+
mob that grows or gets a shield when player is near
and charges when player is near
charge triggers an escape mode
@@ -174,10 +170,6 @@ movement fluidity
wall grab?
maybe remove falling damage and block damage?
-redblobgames.com/articles/visibility
- https://github.com/Silverwolf90/2d-visibility/tree/master/src
- could apply to explosions, neutron bomb, player LOS
-
have a mob apply a positive status effect on other mobs,
heal?
make it yellow
@@ -198,6 +190,7 @@ n-gon outreach ideas
blocks on buttons teleport into the button endlessly if they are being slowly floated away
maybe add a cooldown?
+ can't reproduce
ants marching outline doesn't sync right on safari anymore.
@@ -340,13 +333,6 @@ mob: molecule shapes - 2 separate mobs joined by a bond
spin when attacking player?
increase constraint length when attacking
-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
- write find in spawn undo exploder, but commented out
-
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