diff --git a/.DS_Store b/.DS_Store
index d3548a0..7abd6ee 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/js/bullet.js b/js/bullet.js
index 7a43b1d..04a6504 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -208,7 +208,7 @@ const b = {
fireCD: 1,
setFireCD() {
b.fireCD = tech.fireRate * tech.slowFire * tech.researchHaste * tech.aimDamage / tech.fastTime
- if (tech.isFireRateForGuns) b.fireCD *= Math.pow(0.83, b.inventory.length)
+ if (tech.isFireRateForGuns) b.fireCD *= Math.pow(0.86, b.inventory.length)
if (tech.isFireNotMove) b.fireCD *= 0.33
},
fireAttributes(dir, rotate = true) {
@@ -1102,7 +1102,7 @@ const b = {
// const futurePos = this.lockedOn ? :Vector.add(this.position, Vector.mult(this.velocity, 50))
for (let i = 0, len = mob.length; i < len; ++i) {
if (
- mob[i].alive && mob[i].dropPowerUp &&
+ mob[i].alive && mob[i].isDropPowerUp &&
Matter.Query.ray(map, this.position, mob[i].position).length === 0
// && Matter.Query.ray(body, this.position, mob[i].position).length === 0
) {
@@ -1605,7 +1605,7 @@ const b = {
for (let i = 0, len = mob.length; i < len; ++i) {
if (
Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)) < 2000000 &&
- mob[i].dropPowerUp &&
+ mob[i].isDropPowerUp &&
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0
) {
@@ -1771,7 +1771,7 @@ const b = {
if (!(simulation.cycle % this.lookFrequency)) { //find mob targets
for (let i = 0, len = mob.length; i < len; ++i) {
if (Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)) < 500000 &&
- mob[i].dropPowerUp &&
+ // mob[i].isDropPowerUp &&
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
this.endCycle = 0 //end life if mob is near and visible
@@ -1847,7 +1847,7 @@ const b = {
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) {
+ if (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) {
@@ -1877,7 +1877,7 @@ const b = {
// 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) {
+ // if (mob[i].isDropPowerUp && 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);
@@ -1948,7 +1948,7 @@ const b = {
mobs.statusSlow(who, 180)
this.endCycle = simulation.cycle
// if (tech.isHeavyWater) mobs.statusDoT(who, 0.15, 300)
- if (tech.iceEnergy && !who.shield && !who.isShielded && who.dropPowerUp && who.alive) {
+ if (tech.iceEnergy && !who.shield && !who.isShielded && who.isDropPowerUp && who.alive) {
setTimeout(function() {
if (!who.alive) {
m.energy += tech.iceEnergy * 0.8
@@ -1968,7 +1968,7 @@ const b = {
let closeDist = Infinity;
for (let i = 0, len = mob.length; i < len; ++i) {
if (
- mob[i].dropPowerUp &&
+ mob[i].isDropPowerUp &&
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0
) {
@@ -2070,7 +2070,7 @@ const b = {
let closeDist = Infinity;
for (let i = 0, len = mob.length; i < len; ++i) {
if (
- mob[i].dropPowerUp &&
+ mob[i].isDropPowerUp &&
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0
) {
@@ -2283,7 +2283,7 @@ const b = {
if (tech.isFoamAttract) {
for (let i = 0, len = mob.length; i < len; i++) {
- if (mob[i].dropPowerUp && Vector.magnitude(Vector.sub(mob[i].position, this.position)) < 375 && mob[i].alive && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
+ if (mob[i].isDropPowerUp && Vector.magnitude(Vector.sub(mob[i].position, this.position)) < 375 && mob[i].alive && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
this.force = Vector.mult(Vector.normalise(Vector.sub(mob[i].position, this.position)), this.mass * 0.004)
const slow = 0.9
Matter.Body.setVelocity(this, {
@@ -2304,14 +2304,14 @@ const b = {
targetedNail(position, num = 1, speed = 40 + 10 * Math.random(), range = 1200, isRandomAim = true) {
const targets = [] //target nearby mobs
for (let i = 0, len = mob.length; i < len; i++) {
- if (mob[i].dropPowerUp) {
- const dist = Vector.magnitude(Vector.sub(position, mob[i].position));
- if (dist < range &&
- Matter.Query.ray(map, position, mob[i].position).length === 0 &&
- Matter.Query.ray(body, position, mob[i].position).length === 0) {
- targets.push(Vector.add(mob[i].position, Vector.mult(mob[i].velocity, dist / 60))) //predict where the mob will be in a few cycles
- }
+ // if (mob[i].isDropPowerUp) {
+ const dist = Vector.magnitude(Vector.sub(position, mob[i].position));
+ if (dist < range &&
+ Matter.Query.ray(map, position, mob[i].position).length === 0 &&
+ Matter.Query.ray(body, position, mob[i].position).length === 0) {
+ targets.push(Vector.add(mob[i].position, Vector.mult(mob[i].velocity, dist / 60))) //predict where the mob will be in a few cycles
}
+ // }
}
for (let i = 0; i < num; i++) {
if (targets.length > 0) { // aim near a random target in array
@@ -2859,7 +2859,7 @@ const b = {
let closeDist = this.range;
for (let i = 0, len = mob.length; i < len; ++i) {
const DIST = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius;
- if (DIST < closeDist && mob[i].dropPowerUp &&
+ if (DIST < closeDist && mob[i].isDropPowerUp &&
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
closeDist = DIST;
diff --git a/js/engine.js b/js/engine.js
index a5c02d7..87d11d4 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -138,7 +138,7 @@ function collisionChecks(event) {
y: mob[k].velocity.y - 8 * Math.sin(angle)
});
- if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].dropPowerUp && m.energy > 0.34 * m.maxEnergy) {
+ if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.34 * m.maxEnergy) {
m.energy -= 0.33 * m.maxEnergy
m.immuneCycle = 0; //player doesn't go immune to collision damage
mob[k].death();
@@ -184,7 +184,7 @@ function collisionChecks(event) {
let dmg = 0.05 * b.dmgScale * v * obj.mass * tech.throwChargeRate;
if (mob[k].isShielded) dmg *= 0.35
mob[k].damage(dmg, true);
- if (tech.isBlockPowerUps && !mob[k].alive && mob[k].dropPowerUp) {
+ if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp) {
let type = tech.isEnergyNoAmmo ? "heal" : "ammo"
if (Math.random() < 0.4) {
type = "heal"
diff --git a/js/index.js b/js/index.js
index 234ca92..1cccdb7 100644
--- a/js/index.js
+++ b/js/index.js
@@ -331,7 +331,8 @@ const build = {
// text += `
${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
`
techID.innerHTML = ` ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}`
} else if (tech.tech[i].isExperimentalMode) {
- techID.innerHTML = `${tech.tech[i].description}`
+ // techID.innerHTML = `${tech.tech[i].description}`
+ text += `${tech.tech[i].name}
${tech.tech[i].description}
`
} else {
techID.innerHTML = ` ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}`
}
diff --git a/js/level.js b/js/level.js
index 32d9bc0..07e686d 100644
--- a/js/level.js
+++ b/js/level.js
@@ -12,7 +12,7 @@ const level = {
start() {
if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.enableConstructMode() //used to build maps in testing mode
- // level.difficultyIncrease(50)
+ // level.difficultyIncrease(11)
// simulation.zoomScale = 1000;
// simulation.setZoom();
// m.setField("nano-scale manufacturing")
@@ -772,6 +772,33 @@ const level = {
mapB.portalPair = mapA
return [portalA, portalB, mapA, mapB]
},
+ drip(x, yMin, yMax, period = 100, color = "hsla(160, 100%, 35%, 0.5)") {
+ return {
+ x: x,
+ y: yMin,
+ period: period,
+ dropCycle: 0,
+ speed: 0,
+ draw() {
+ if (!m.isBodiesAsleep) {
+ if (this.dropCycle < simulation.cycle) { //reset
+ this.dropCycle = simulation.cycle + this.period + Math.floor(40 * Math.random())
+ this.y = yMin
+ this.speed = 1
+ } else { //fall
+ this.speed += 0.35 //acceleration from gravity
+ this.y += this.speed
+ }
+ }
+ if (this.y < yMax) { //draw
+ ctx.fillStyle = color //"hsla(160, 100%, 35%,0.75)"
+ ctx.beginPath();
+ ctx.arc(this.x, this.y, 8, 0, 2 * Math.PI);
+ ctx.fill();
+ }
+ }
+ }
+ },
hazard(x, y, width, height, damage = 0.003, color = "hsla(160, 100%, 35%,0.75)") {
return {
min: {
@@ -1086,18 +1113,18 @@ const level = {
// spawn.ghoster(2900, -500)
// spawn.launcherBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400)
- // spawn.striker(1600, -500)
+ // spawn.striker(4600, -500)
// spawn.laserTargetingBoss(1700, -120)
// spawn.bomberBoss(1400, -500)
// spawn.sniper(1800, -120)
// spawn.streamBoss(1600, -500)
// spawn.orbitalBoss(1600, -500)
- // spawn.cellBossCulture(1600, -500)
+ spawn.spawnerBossCulture(1600, -500)
// spawn.shieldingBoss(1600, -500)
// spawn.beamer(1200, -500)
// spawn.shield(mob[mob.length - 1], 1800, -120, 1);
- spawn.nodeGroup(1200, -500, "pulsar")
+ // spawn.nodeGroup(1200, -500, "pulsar")
// spawn.snakeBoss(1200, -500)
// spawn.powerUpBoss(2900, -500)
// spawn.randomMob(1600, -500)
@@ -1714,29 +1741,13 @@ const level = {
const balance3 = level.spinner(2608, 1900, 584, 25, 0.001) //falling
const balance4 = level.spinner(9300, 2205, 25, 380, 0.001) //exit
- const drip = {
- x: 7150,
- y: 0,
- speed: 0
- }
+ const drip1 = level.drip(6100, 1900, 2900, 100)
+ const drip2 = level.drip(7300, 1900, 2900, 150)
+ const drip3 = level.drip(8750, 1900, 2900, 70)
level.custom = () => {
- const dripCycle = (simulation.cycle % 200) //drips
- if (dripCycle < 70) {
- if (!m.isBodiesAsleep) {
- if (dripCycle === 0) {
- drip.y = 1900
- drip.x = 4600 + 4400 * Math.random()
- drip.speed = 1
- }
- drip.speed += 0.35 //acceleration from gravity
- drip.y += drip.speed
- }
- // if (drip.y > 2900) console.log(dripCycle)
- ctx.fillStyle = "hsla(160, 100%, 35%, 0.5)" //"hsla(160, 100%, 35%,0.75)"
- ctx.beginPath();
- ctx.arc(drip.x, drip.y, 8, 0, 2 * Math.PI);
- ctx.fill();
- }
+ drip1.draw();
+ drip2.draw();
+ drip3.draw();
button.query();
button.draw();
diff --git a/js/mob.js b/js/mob.js
index 5902131..d5a9c34 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -307,6 +307,12 @@ const mobs = {
this.seePlayer.position.y = player.position.y;
}
},
+ // alwaysSeePlayerIfRemember() {
+ // if (!m.isCloak && this.seePlayer.recall) {
+ // this.seePlayer.position.x = player.position.x;
+ // this.seePlayer.position.y = player.position.y;
+ // }
+ // },
seePlayerCheck() {
if (!(simulation.cycle % this.seePlayerFreq)) {
if (
@@ -980,7 +986,7 @@ const mobs = {
explode(mass = this.mass) {
if (m.immuneCycle < m.cycle) {
m.damage(Math.min(Math.max(0.02 * Math.sqrt(mass), 0.01), 0.35) * simulation.dmgScale);
- this.dropPowerUp = false;
+ this.isDropPowerUp = false;
this.death(); //death with no power up or body
}
},
@@ -988,7 +994,7 @@ const mobs = {
if (!m.isBodiesAsleep) {
this.timeLeft--;
if (this.timeLeft < 0) {
- this.dropPowerUp = false;
+ this.isDropPowerUp = false;
this.death(); //death with no power up
}
}
@@ -1014,9 +1020,9 @@ const mobs = {
if (this.isBoss) dmg *= 0.25
//energy and heal drain should be calculated after damage boosts
- if (tech.energySiphon && dmg !== Infinity && this.dropPowerUp) m.energy += Math.min(this.health, dmg) * tech.energySiphon
+ if (tech.energySiphon && dmg !== Infinity && this.isDropPowerUp) m.energy += Math.min(this.health, dmg) * tech.energySiphon
- if (tech.healthDrain && dmg !== Infinity && this.dropPowerUp) {
+ if (tech.healthDrain && dmg !== Infinity && this.isDropPowerUp) {
m.addHealth(Math.min(this.health, dmg) * tech.healthDrain)
if (m.health > m.maxHealth) m.health = m.maxHealth
}
@@ -1036,12 +1042,24 @@ const mobs = {
// to use declare custom method in mob spawn
},
leaveBody: true,
- dropPowerUp: true,
+ isDropPowerUp: true,
death() {
this.onDeath(this); //custom death effects
this.removeConsBB();
this.alive = false; //triggers mob removal in mob[i].replace(i)
- if (this.dropPowerUp) {
+
+ if (this.isDropPowerUp) {
+ if (tech.deathSpawnsFromBoss || (tech.deathSpawns && this.isDropPowerUp)) {
+ const spawns = tech.deathSpawns + tech.deathSpawnsFromBoss
+ const len = Math.min(12, spawns * Math.ceil(Math.random() * simulation.difficulty * spawns))
+ for (let i = 0; i < len; i++) {
+ spawn.spawns(this.position.x + (Math.random() - 0.5) * radius * 2.5, this.position.y + (Math.random() - 0.5) * radius * 2.5);
+ Matter.Body.setVelocity(mob[mob.length - 1], {
+ x: this.velocity.x + (Math.random() - 0.5) * 10,
+ y: this.velocity.x + (Math.random() - 0.5) * 10
+ });
+ }
+ }
if (tech.isEnergyLoss) m.energy *= 0.75;
powerUps.spawnRandomPowerUp(this.position.x, this.position.y);
m.lastKillCycle = m.cycle; //tracks the last time a kill was made, mostly used in simulation.checks()
@@ -1055,7 +1073,10 @@ const mobs = {
}
if (tech.isBotSpawnerReset) {
for (let i = 0, len = bullet.length; i < len; i++) {
- if (bullet[i].botType && !bullet[i].isKeep) bullet[i].endCycle = simulation.cycle + 660 //10 seconds and 1 extra second for fun
+ if (bullet[i].botType && bullet[i].endCycle !== Infinity) {
+ console.log(bullet[i].endCycle)
+ bullet[i].endCycle = simulation.cycle + 660 //10 seconds and 1 extra second for fun
+ }
}
}
if (Math.random() < tech.botSpawner) {
diff --git a/js/player.js b/js/player.js
index 52dc45b..bd97ab4 100644
--- a/js/player.js
+++ b/js/player.js
@@ -348,6 +348,7 @@ const m = {
// tech.removeLoreTechFromPool();
// tech.addLoreTechToPool();
// tech.removeJunkTechFromPool();
+ tech.cancelCount = 0;
tech.armorFromPowerUps = 0;
tech.totalCount = 0;
const randomBotCount = b.totalBots()
@@ -1317,7 +1318,7 @@ const m = {
x: player.velocity.x - (20 * unit.x) / massRoot,
y: player.velocity.y - (20 * unit.y) / massRoot
});
- if (who.dropPowerUp && player.speed < 12) {
+ if (who.isDropPowerUp && player.speed < 12) {
const massRootCap = Math.sqrt(Math.min(10, Math.max(0.4, who.mass))); // masses above 12 can start to overcome the push back
Matter.Body.setVelocity(player, {
x: 0.9 * player.velocity.x + 0.6 * unit.x * massRootCap,
@@ -1880,6 +1881,14 @@ const m = {
simulation.isTimeSkipping = true;
m.cycle++;
simulation.gravity();
+ if (tech.isFireMoveLock && input.fire) {
+ // Matter.Body.setVelocity(player, {
+ // x: 0,
+ // y: -55 * player.mass * simulation.g //undo gravity before it is added
+ // });
+ player.force.x = 0
+ player.force.y = 0
+ }
Engine.update(engine, simulation.delta);
// level.checkZones();
// level.checkQuery();
@@ -2125,7 +2134,7 @@ const m = {
// //draw outline of shield
// ctx.fillStyle = `rgba(140,217,255,0.5)`
// ctx.fill()
- // } else if (tech.superposition && inPlayer[i].dropPowerUp) {
+ // } else if (tech.superposition && inPlayer[i].isDropPowerUp) {
// // inPlayer[i].damage(0.4 * b.dmgScale); //damage mobs inside the player
// // m.energy += 0.005;
@@ -2919,7 +2928,7 @@ const m = {
y: mob[k].velocity.y - 8 * Math.sin(angle)
});
- if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].dropPowerUp && m.energy > 0.34 * m.maxEnergy) {
+ if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.34 * m.maxEnergy) {
m.energy -= 0.33 * m.maxEnergy
m.immuneCycle = 0; //player doesn't go immune to collision damage
mob[k].death();
@@ -2965,7 +2974,7 @@ const m = {
let dmg = 0.05 * b.dmgScale * v * obj.mass * tech.throwChargeRate;
if (mob[k].isShielded) dmg *= 0.35
mob[k].damage(dmg, true);
- if (tech.isBlockPowerUps && !mob[k].alive && mob[k].dropPowerUp) {
+ if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp) {
let type = tech.isEnergyNoAmmo ? "heal" : "ammo"
if (Math.random() < 0.4) {
type = "heal"
diff --git a/js/simulation.js b/js/simulation.js
index a3dfd59..ee6b480 100644
--- a/js/simulation.js
+++ b/js/simulation.js
@@ -710,6 +710,7 @@ const simulation = {
let holdTarget; //if player is holding something this remembers it before it gets deleted
if (m.holdingTarget) holdTarget = m.holdingTarget;
+ tech.deathSpawnsFromBoss = 0;
simulation.fallHeight = 3000;
m.fireCDcycle = 0
m.drop();
diff --git a/js/spawn.js b/js/spawn.js
index 5d06edd..1d88b80 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -83,7 +83,7 @@ const spawn = {
}
}
},
- randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss"]) {
+ randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture"]) {
// 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)
},
@@ -472,7 +472,7 @@ const spawn = {
//tether to other blocks
ctx.beginPath();
for (let i = 0, len = mob.length; i < len; i++) {
- if (mob[i].isGrouper && mob[i] != this && mob[i].dropPowerUp) { //don't tether to self, bullets, shields, ...
+ if (mob[i].isGrouper && mob[i] != this && mob[i].isDropPowerUp) { //don't tether to self, bullets, shields, ...
const distance2 = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position))
if (distance2 < this.groupingRangeMax) {
if (!mob[i].seePlayer.recall) mob[i].seePlayerCheck(); //wake up sleepy mobs
@@ -529,7 +529,7 @@ const spawn = {
me.seePlayerFreq = Math.floor(11 + 7 * Math.random())
me.seeAtDistance2 = 1400000;
me.cellMassMax = 70
- me.collisionFilter.mask = cat.player | cat.bullet //| cat.map | cat.body
+ me.collisionFilter.mask = cat.player | cat.bullet | cat.body //| cat.map | cat.body
Matter.Body.setDensity(me, 0.00035) // normal density is 0.001 // this reduces life by half and decreases knockback
const k = 642 //k=r^2/m
me.split = function() {
@@ -584,10 +584,103 @@ const spawn = {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
} else {
this.leaveBody = false;
- this.dropPowerUp = false;
+ this.isDropPowerUp = false;
}
}
},
+ spawnerBossCulture(x, y, radius = 50, num = 8 + Math.min(20, simulation.difficulty * 0.4)) {
+ tech.deathSpawnsFromBoss += 0.4
+ const spawnID = Math.random()
+ for (let i = 0; i < num; i++) spawn.spawnerBoss(x, y, radius, spawnID)
+ },
+ spawnerBoss(x, y, radius, spawnID) {
+ mobs.spawn(x + Math.random(), y + Math.random(), 4, radius, "rgba(255,60,0,0.3)") //);
+ let me = mob[mob.length - 1];
+ me.isBoss = true;
+ me.isSpawnBoss = true;
+ me.spawnID = spawnID
+ me.accelMag = 0.0002 * simulation.accelScale;
+ me.memory = Infinity;
+ me.showHealthBar = false;
+ me.isVerticesChange = true
+ me.frictionAir = 0.012
+ me.seePlayerFreq = Math.floor(11 + 7 * Math.random())
+ me.seeAtDistance2 = 200000 //1400000;
+ me.cellMassMax = 70
+ me.stroke = "transparent"
+ me.collisionFilter.mask = cat.player | cat.bullet | cat.body //| cat.map //"rgba(255,60,0,0.3)"
+ // Matter.Body.setDensity(me, 0.0014) // normal density is 0.001
+ Matter.Body.setAngularVelocity(me, 0.12 * (Math.random() - 0.5))
+ // spawn.shield(me, x, y, 1);
+
+ me.onHit = function() { //run this function on hitting player
+ this.explode();
+ };
+ me.doAwake = function() {
+ if (!m.isBodiesAsleep) {
+ this.alwaysSeePlayer();
+ this.checkStatus();
+ this.attraction();
+
+ // if (this.seePlayer.recall && this.mass < this.cellMassMax) { //grow cell radius
+ // const scale = 1 + 0.0002 * this.cellMassMax / this.mass;
+ // Matter.Body.scale(this, scale, scale);
+ // this.radius = Math.sqrt(this.mass * k / Math.PI)
+ // }
+ if (!(simulation.cycle % this.seePlayerFreq)) { //move away from other mobs
+ const repelRange = 40
+ const attractRange = 240
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (mob[i].isSpawnBoss && mob[i].id !== this.id) {
+ const sub = Vector.sub(this.position, mob[i].position)
+ const dist = Vector.magnitude(sub)
+ if (dist < repelRange) {
+ this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.002)
+ } else if (dist > attractRange) {
+ this.force = Vector.mult(Vector.normalise(sub), -this.mass * 0.002)
+ }
+ }
+ }
+ }
+ }
+ }
+ me.do = function() {
+ this.checkStatus();
+ if (this.seePlayer.recall) {
+ this.do = this.doAwake
+ //awaken other spawnBosses
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (mob[i].isSpawnBoss && mob[i].spawnID === this.spawnID) mob[i].seePlayer.recall = 1
+ }
+ }
+ };
+ me.onDeath = function() {
+ this.isSpawnBoss = false;
+ let count = 0 //count other cells by id
+ // console.log(this.spawnID)
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (mob[i].isSpawnBoss && mob[i].spawnID === this.spawnID) count++
+ }
+ if (count < 1) { //only drop a power up if this is the last cell
+ powerUps.spawnBossPowerUp(this.position.x, this.position.y)
+ tech.deathSpawnsFromBoss -= 0.4
+ } else {
+ this.leaveBody = false;
+ this.isDropPowerUp = false;
+ }
+
+ const spawns = tech.deathSpawns + tech.deathSpawnsFromBoss
+ const len = Math.min(12, spawns * Math.ceil(Math.random() * simulation.difficulty * spawns))
+ for (let i = 0; i < len; i++) {
+ spawn.spawns(this.position.x + (Math.random() - 0.5) * radius * 2.5, this.position.y + (Math.random() - 0.5) * radius * 2.5);
+ Matter.Body.setVelocity(mob[mob.length - 1], {
+ x: this.velocity.x + (Math.random() - 0.5) * 10,
+ y: this.velocity.x + (Math.random() - 0.5) * 10
+ });
+ }
+
+ }
+ },
powerUpBoss(x, y, vertices = 9, radius = 130) {
mobs.spawn(x, y, vertices, radius, "transparent");
let me = mob[mob.length - 1];
@@ -596,10 +689,9 @@ const spawn = {
me.seeAtDistance2 = 1000000;
me.accelMag = 0.0005 * simulation.accelScale;
Matter.Body.setDensity(me, 0.00035); //normal is 0.001
- me.collisionFilter.mask = cat.bullet | cat.player
+ me.collisionFilter.mask = cat.bullet | cat.player | cat.body
me.memory = Infinity;
me.seePlayerFreq = 30
-
me.lockedOn = null;
if (vertices === 9) {
//on primary spawn
@@ -616,17 +708,15 @@ const spawn = {
};
me.onDeath = function() {
this.leaveBody = false;
- this.dropPowerUp = false;
if (vertices > 3) {
+ this.isDropPowerUp = false;
spawn.powerUpBoss(this.position.x, this.position.y, vertices - 1)
Matter.Body.setVelocity(mob[mob.length - 1], {
x: this.velocity.x,
y: this.velocity.y
})
}
- for (let i = 0; i < powerUp.length; i++) {
- powerUp[i].collisionFilter.mask = cat.map | cat.powerUp
- }
+ for (let i = 0; i < powerUp.length; i++) powerUp[i].collisionFilter.mask = cat.map | cat.powerUp
};
me.do = function() {
this.stroke = `hsl(0,0%,${80+25*Math.sin(simulation.cycle*0.01)}%)`
@@ -829,7 +919,7 @@ const spawn = {
me.seeAtDistance2 = (me.eventHorizon + 400) * (me.eventHorizon + 400); //vision limit is event horizon
me.accelMag = 0.0001 * simulation.accelScale;
me.frictionAir = 0.025;
- me.collisionFilter.mask = cat.player | cat.bullet
+ me.collisionFilter.mask = cat.player | cat.bullet | cat.body
me.memory = Infinity;
Matter.Body.setDensity(me, 0.008); //extra dense //normal is 0.001 //makes effective life much larger
me.do = function() {
@@ -906,7 +996,7 @@ const spawn = {
me.eventHorizon = 1100; //required for black hole
me.seeAtDistance2 = (me.eventHorizon + 1200) * (me.eventHorizon + 1200); //vision limit is event horizon
me.accelMag = 0.00003 * simulation.accelScale;
- me.collisionFilter.mask = cat.player | cat.bullet
+ me.collisionFilter.mask = cat.player | cat.bullet | cat.body
// me.frictionAir = 0.005;
me.memory = 1600;
Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger
@@ -1132,7 +1222,7 @@ const spawn = {
this.fill = `rgba(0,0,0,${0.4+0.6*Math.random()})`
this.stroke = "#014"
this.isShielded = false;
- this.dropPowerUp = true;
+ this.isDropPowerUp = true;
this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob; //can't touch bullets
ctx.beginPath();
@@ -1160,7 +1250,7 @@ const spawn = {
// ctx.stroke();
} else {
this.isShielded = true;
- this.dropPowerUp = false;
+ this.isDropPowerUp = false;
this.seePlayer.recall = false
this.fill = "transparent"
this.stroke = "transparent"
@@ -1192,7 +1282,7 @@ const spawn = {
},
historyBoss(x, y, radius = 30) {
if (tech.dynamoBotCount > 0) {
- spawn.randomLevelBoss(x, y, ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss"])
+ spawn.randomLevelBoss(x, y, ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture"])
return
}
mobs.spawn(x, y, 0, radius, "transparent");
@@ -1204,7 +1294,7 @@ const spawn = {
me.delayLimit = 60 + Math.floor(60 * Math.random());
me.followDelay = 600 - Math.floor(60 * Math.random())
me.stroke = "transparent"; //used for drawGhost
- me.collisionFilter.mask = cat.bullet
+ me.collisionFilter.mask = cat.bullet | cat.body
me.memory = Infinity
me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
@@ -1505,83 +1595,85 @@ const spawn = {
}
me.fire = function() {
this.checkStatus();
- if (!m.isBodiesAsleep && !m.isCloak && !this.isStunned) {
- if (this.isFiring) {
- if (this.fireCycle > this.fireDelay) { //fire
- this.isFiring = false
- this.fireCycle = 0
- this.torque += (0.00008 + 0.00007 * Math.random()) * this.inertia * (Math.round(Math.random()) * 2 - 1) //randomly spin around after firing
- //is player in beam path
- if (Matter.Query.ray([player], this.fireTarget, this.position).length) {
+ if (!m.isBodiesAsleep) {
+ if (!m.isCloak && !this.isStunned) {
+ if (this.isFiring) {
+ if (this.fireCycle > this.fireDelay) { //fire
+ this.isFiring = false
+ this.fireCycle = 0
+ this.torque += (0.00008 + 0.00007 * Math.random()) * this.inertia * (Math.round(Math.random()) * 2 - 1) //randomly spin around after firing
+ //is player in beam path
+ if (Matter.Query.ray([player], this.fireTarget, this.position).length) {
+ unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
+ this.fireTarget = Vector.add(this.vertices[1], unit)
+ }
+ //damage player if in range
+ if (Vector.magnitude(Vector.sub(player.position, this.fireTarget)) < this.pulseRadius && m.immuneCycle < m.cycle) {
+ m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
+ m.damage(0.045 * simulation.dmgScale);
+ }
+ simulation.drawList.push({ //add dmg to draw queue
+ x: this.fireTarget.x,
+ y: this.fireTarget.y,
+ radius: this.pulseRadius,
+ color: "rgba(120,0,255,0.6)",
+ time: simulation.drawTime
+ });
+ ctx.beginPath();
+ ctx.moveTo(this.vertices[1].x, this.vertices[1].y)
+ ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
+ ctx.lineWidth = 20;
+ ctx.strokeStyle = "rgba(120,0,255,0.2)";
+ ctx.stroke();
+ ctx.lineWidth = 4;
+ ctx.strokeStyle = "rgba(120,0,255,1)";
+ ctx.stroke();
+ } else { //delay before firing
+ this.fireCycle++
+ //draw explosion outline
+ ctx.beginPath();
+ ctx.arc(this.fireTarget.x, this.fireTarget.y, this.pulseRadius, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay
+ ctx.fillStyle = "rgba(120,0,255,0.05)";
+ ctx.fill();
+ //draw path from mob to explosion
+ ctx.beginPath();
+ ctx.moveTo(this.vertices[1].x, this.vertices[1].y)
+ ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
+ ctx.setLineDash([40 * Math.random(), 200 * Math.random()]);
+ ctx.lineWidth = 2;
+ ctx.strokeStyle = "rgba(120,0,255,0.2)";
+ ctx.stroke();
+ ctx.setLineDash([0, 0]);
+ }
+ } else { //aim at player
+ this.fireCycle++
+ this.fireDir = Vector.normalise(Vector.sub(m.pos, this.position)); //set direction to turn to fire
+ //rotate towards fireAngle
+ const angle = this.angle + Math.PI / 2;
+ const c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
+ const threshold = 0.04;
+ if (c > threshold) {
+ this.torque += 0.0000015 * this.inertia;
+ } else if (c < -threshold) {
+ this.torque -= 0.0000015 * this.inertia;
+ } else if (this.fireCycle > 45) { //fire
unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
this.fireTarget = Vector.add(this.vertices[1], unit)
- }
- //damage player if in range
- if (Vector.magnitude(Vector.sub(player.position, this.fireTarget)) < this.pulseRadius && m.immuneCycle < m.cycle) {
- m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
- m.damage(0.045 * simulation.dmgScale);
- }
- simulation.drawList.push({ //add dmg to draw queue
- x: this.fireTarget.x,
- y: this.fireTarget.y,
- radius: this.pulseRadius,
- color: "rgba(120,0,255,0.6)",
- time: simulation.drawTime
- });
- ctx.beginPath();
- ctx.moveTo(this.vertices[1].x, this.vertices[1].y)
- ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
- ctx.lineWidth = 20;
- ctx.strokeStyle = "rgba(120,0,255,0.2)";
- ctx.stroke();
- ctx.lineWidth = 4;
- ctx.strokeStyle = "rgba(120,0,255,1)";
- ctx.stroke();
- } else { //delay before firing
- this.fireCycle++
- //draw explosion outline
- ctx.beginPath();
- ctx.arc(this.fireTarget.x, this.fireTarget.y, this.pulseRadius, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay
- ctx.fillStyle = "rgba(120,0,255,0.05)";
- ctx.fill();
- //draw path from mob to explosion
- ctx.beginPath();
- ctx.moveTo(this.vertices[1].x, this.vertices[1].y)
- ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
- ctx.setLineDash([40 * Math.random(), 200 * Math.random()]);
- ctx.lineWidth = 2;
- ctx.strokeStyle = "rgba(120,0,255,0.2)";
- ctx.stroke();
- ctx.setLineDash([0, 0]);
- }
- } else { //aim at player
- this.fireCycle++
- this.fireDir = Vector.normalise(Vector.sub(m.pos, this.position)); //set direction to turn to fire
- //rotate towards fireAngle
- const angle = this.angle + Math.PI / 2;
- const c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
- const threshold = 0.04;
- if (c > threshold) {
- this.torque += 0.0000015 * this.inertia;
- } else if (c < -threshold) {
- this.torque -= 0.0000015 * this.inertia;
- } else if (this.fireCycle > 45) { //fire
- unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
- this.fireTarget = Vector.add(this.vertices[1], unit)
- if (Vector.magnitude(Vector.sub(m.pos, this.fireTarget)) < 1000) { //if's possible for this to be facing 180 degrees away from the player, this makes sure that doesn't occur
- Matter.Body.setAngularVelocity(this, 0)
- this.fireLockCount = 0
- this.isFiring = true
- this.fireCycle = 0
+ if (Vector.magnitude(Vector.sub(m.pos, this.fireTarget)) < 1000) { //if's possible for this to be facing 180 degrees away from the player, this makes sure that doesn't occur
+ Matter.Body.setAngularVelocity(this, 0)
+ this.fireLockCount = 0
+ this.isFiring = true
+ this.fireCycle = 0
+ }
}
}
+ //gently return to starting location
+ const sub = Vector.sub(this.homePosition, this.position)
+ const dist = Vector.magnitude(sub)
+ if (dist > 250) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.0002)
+ } else {
+ this.isFiring = false
}
- //gently return to starting location
- const sub = Vector.sub(this.homePosition, this.position)
- const dist = Vector.magnitude(sub)
- if (dist > 250) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.0002)
- } else {
- this.isFiring = false
}
};
},
@@ -1622,88 +1714,90 @@ const spawn = {
me.do = function() {
this.seePlayerByLookingAt();
this.checkStatus();
- if (!m.isBodiesAsleep && this.seePlayer.recall) {
- if (this.isFiring) {
- if (this.fireCycle > this.fireDelay) { //fire
- if (!this.canSeeTarget()) return
- this.isFiring = false
- this.fireCycle = 0
- this.torque += (0.00002 + 0.0002 * Math.random()) * this.inertia * (Math.round(Math.random()) * 2 - 1) //randomly spin around after firing
- //is player in beam path
- if (Matter.Query.ray([player], this.fireTarget, this.position).length) {
+ if (!m.isBodiesAsleep) {
+ if (this.seePlayer.recall) {
+ if (this.isFiring) {
+ if (this.fireCycle > this.fireDelay) { //fire
+ if (!this.canSeeTarget()) return
+ this.isFiring = false
+ this.fireCycle = 0
+ this.torque += (0.00002 + 0.0002 * Math.random()) * this.inertia * (Math.round(Math.random()) * 2 - 1) //randomly spin around after firing
+ //is player in beam path
+ if (Matter.Query.ray([player], this.fireTarget, this.position).length) {
+ unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
+ this.fireTarget = Vector.add(this.vertices[1], unit)
+ }
+ //damage player if in range
+ if (Vector.magnitude(Vector.sub(player.position, this.fireTarget)) < this.pulseRadius && m.immuneCycle < m.cycle) {
+ m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
+ m.damage(0.03 * simulation.dmgScale);
+ }
+ simulation.drawList.push({ //add dmg to draw queue
+ x: this.fireTarget.x,
+ y: this.fireTarget.y,
+ radius: this.pulseRadius,
+ color: "rgba(255,0,100,0.6)",
+ time: simulation.drawTime
+ });
+ ctx.beginPath();
+ ctx.moveTo(this.vertices[1].x, this.vertices[1].y)
+ ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
+ ctx.lineWidth = 20;
+ ctx.strokeStyle = "rgba(255,0,100,0.2)";
+ ctx.stroke();
+ ctx.lineWidth = 4;
+ ctx.strokeStyle = "rgba(255,0,100,1)";
+ ctx.stroke();
+ } else { //delay before firing
+ this.fireCycle++
+ if (!(simulation.cycle % 3)) {
+ if (!this.canSeeTarget()) return //if can't see stop firing
+ }
+ //draw explosion outline
+ ctx.beginPath();
+ ctx.arc(this.fireTarget.x, this.fireTarget.y, this.pulseRadius, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay
+ ctx.fillStyle = "rgba(255,0,100,0.05)";
+ ctx.fill();
+ //draw path from mob to explosion
+ ctx.beginPath();
+ ctx.moveTo(this.vertices[1].x, this.vertices[1].y)
+ ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
+ ctx.setLineDash([40 * Math.random(), 200 * Math.random()]);
+ ctx.lineWidth = 2;
+ ctx.strokeStyle = "rgba(255,0,100,0.2)";
+ ctx.stroke();
+ ctx.setLineDash([0, 0]);
+ }
+ } else { //aim at player
+ this.fireCycle++
+ // this.fireDir = ; //set direction to turn to fire
+ const angle = this.angle + Math.PI / 2;
+ const dot = Vector.dot({
+ x: Math.cos(angle),
+ y: Math.sin(angle)
+ }, Vector.normalise(Vector.sub(this.seePlayer.position, this.position)))
+ const threshold = 0.04;
+ if (dot > threshold) { //rotate towards fireAngle
+ this.torque += 0.0000015 * this.inertia;
+ } else if (dot < -threshold) {
+ this.torque -= 0.0000015 * this.inertia;
+ } else if (this.fireCycle > 60) { // aim
unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
this.fireTarget = Vector.add(this.vertices[1], unit)
+ if (!this.canSeeTarget()) return
+ Matter.Body.setAngularVelocity(this, 0)
+ this.fireLockCount = 0
+ this.isFiring = true
+ this.fireCycle = 0
}
- //damage player if in range
- if (Vector.magnitude(Vector.sub(player.position, this.fireTarget)) < this.pulseRadius && m.immuneCycle < m.cycle) {
- m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
- m.damage(0.03 * simulation.dmgScale);
- }
- simulation.drawList.push({ //add dmg to draw queue
- x: this.fireTarget.x,
- y: this.fireTarget.y,
- radius: this.pulseRadius,
- color: "rgba(255,0,100,0.6)",
- time: simulation.drawTime
- });
- ctx.beginPath();
- ctx.moveTo(this.vertices[1].x, this.vertices[1].y)
- ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
- ctx.lineWidth = 20;
- ctx.strokeStyle = "rgba(255,0,100,0.2)";
- ctx.stroke();
- ctx.lineWidth = 4;
- ctx.strokeStyle = "rgba(255,0,100,1)";
- ctx.stroke();
- } else { //delay before firing
- this.fireCycle++
- if (!(simulation.cycle % 3)) {
- if (!this.canSeeTarget()) return //if can't see stop firing
- }
- //draw explosion outline
- ctx.beginPath();
- ctx.arc(this.fireTarget.x, this.fireTarget.y, this.pulseRadius, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay
- ctx.fillStyle = "rgba(255,0,100,0.05)";
- ctx.fill();
- //draw path from mob to explosion
- ctx.beginPath();
- ctx.moveTo(this.vertices[1].x, this.vertices[1].y)
- ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
- ctx.setLineDash([40 * Math.random(), 200 * Math.random()]);
- ctx.lineWidth = 2;
- ctx.strokeStyle = "rgba(255,0,100,0.2)";
- ctx.stroke();
- ctx.setLineDash([0, 0]);
- }
- } else { //aim at player
- this.fireCycle++
- // this.fireDir = ; //set direction to turn to fire
- const angle = this.angle + Math.PI / 2;
- const dot = Vector.dot({
- x: Math.cos(angle),
- y: Math.sin(angle)
- }, Vector.normalise(Vector.sub(this.seePlayer.position, this.position)))
- const threshold = 0.04;
- if (dot > threshold) { //rotate towards fireAngle
- this.torque += 0.0000015 * this.inertia;
- } else if (dot < -threshold) {
- this.torque -= 0.0000015 * this.inertia;
- } else if (this.fireCycle > 60) { // aim
- unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
- this.fireTarget = Vector.add(this.vertices[1], unit)
- if (!this.canSeeTarget()) return
- Matter.Body.setAngularVelocity(this, 0)
- this.fireLockCount = 0
- this.isFiring = true
- this.fireCycle = 0
}
+ //gently return to starting location
+ const sub = Vector.sub(this.homePosition, this.position)
+ const dist = Vector.magnitude(sub)
+ if (dist > 350) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.0002)
+ } else {
+ this.isFiring = false
}
- //gently return to starting location
- const sub = Vector.sub(this.homePosition, this.position)
- const dist = Vector.magnitude(sub)
- if (dist > 350) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.0002)
- } else {
- this.isFiring = false
}
};
},
@@ -2054,7 +2148,7 @@ const spawn = {
me.alpha = 1; //used in drawGhost
me.canTouchPlayer = false; //used in drawGhost
// me.leaveBody = false;
- me.collisionFilter.mask = cat.bullet
+ me.collisionFilter.mask = cat.bullet | cat.body
me.showHealthBar = false;
me.memory = 480;
me.do = function() {
@@ -2165,7 +2259,7 @@ const spawn = {
me.memory = Infinity;
// me.memory = 300;
// Matter.Body.setDensity(me, 0.0015); //extra dense //normal is 0.001
- me.collisionFilter.mask = cat.player | cat.bullet
+ me.collisionFilter.mask = cat.player | cat.bullet | cat.body
spawn.shield(me, x, y, 1);
@@ -2271,7 +2365,7 @@ const spawn = {
me.frictionAir = 0;
me.restitution = 0.8;
me.leaveBody = false;
- me.dropPowerUp = false;
+ me.isDropPowerUp = false;
me.showHealthBar = false;
me.collisionFilter.category = cat.mobBullet;
@@ -2322,7 +2416,7 @@ const spawn = {
me.frictionAir = 0;
me.restitution = 1;
me.leaveBody = false;
- me.dropPowerUp = false;
+ me.isDropPowerUp = false;
me.showHealthBar = false;
me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
@@ -2460,14 +2554,14 @@ const spawn = {
me.frictionAir = 0;
me.restitution = 0;
me.leaveBody = false;
- me.dropPowerUp = false;
+ me.isDropPowerUp = false;
me.showHealthBar = false;
me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
me.do = function() {
this.timeLimit();
if (Matter.Query.collides(this, map).length > 0 || Matter.Query.collides(this, body).length > 0 && this.speed < 3) {
- this.dropPowerUp = false;
+ this.isDropPowerUp = false;
this.death(); //death with no power up
}
};
@@ -2552,6 +2646,7 @@ const spawn = {
me.frictionStatic = 0;
me.friction = 0;
me.frictionAir = 0.5;
+ me.homePosition = { x: x, y: y };
spawn.shield(me, x, y, 1);
spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random())
@@ -2582,10 +2677,9 @@ const spawn = {
this.cycle = 0
ctx.beginPath();
for (let i = 0; i < mob.length; i++) {
- if (!mob[i].isShielded && !mob[i].shield && mob[i].dropPowerUp && mob[i].alive) {
+ if (!mob[i].isShielded && !mob[i].shield && mob[i].isDropPowerUp && mob[i].alive) {
ctx.moveTo(this.position.x, this.position.y)
ctx.lineTo(mob[i].position.x, mob[i].position.y)
-
spawn.shield(mob[i], mob[i].position.x, mob[i].position.y, 1, true);
}
}
@@ -2593,6 +2687,10 @@ const spawn = {
// ctx.lineCap = "round";
ctx.strokeStyle = "rgba(200,200,255,0.9)"
ctx.stroke();
+ //return to starting location
+ const sub = Vector.sub(this.homePosition, this.position)
+ const dist = Vector.magnitude(sub)
+ if (dist > 350) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.05)
}
}
};
@@ -2690,7 +2788,7 @@ const spawn = {
me.frictionAir = 0.01 //* (0.8 + 0.4 * Math.random());
me.restitution = 0.5;
me.leaveBody = false;
- me.dropPowerUp = false;
+ me.isDropPowerUp = false;
me.showHealthBar = false;
me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
@@ -2706,7 +2804,7 @@ const spawn = {
let me = mob[mob.length - 1];
me.g = 0.0004; //required if using 'gravity'
me.leaveBody = false;
- // me.dropPowerUp = false;
+ // me.isDropPowerUp = false;
me.onDeath = function() { //run this function on death
for (let i = 0; i < Math.ceil(this.mass * 0.15 + Math.random() * 2.5); ++i) {
spawn.spawns(this.position.x + (Math.random() - 0.5) * radius * 2.5, this.position.y + (Math.random() - 0.5) * radius * 2.5);
@@ -2724,25 +2822,33 @@ const spawn = {
this.attraction();
};
},
- spawns(x, y, radius = 15 + Math.ceil(Math.random() * 5)) {
+ spawns(x, y, radius = 15) {
mobs.spawn(x, y, 4, radius, "rgb(255,0,0)");
let me = mob[mob.length - 1];
me.onHit = function() {
//run this function on hitting player
this.explode();
};
+ // me.stroke = "transparent"
+ me.collisionFilter.mask = cat.player | cat.bullet | cat.body | cat.map
+ me.showHealthBar = false;
Matter.Body.setDensity(me, 0.0005); //normal is 0.001
me.g = 0.0001; //required if using 'gravity'
- me.accelMag = 0.0003 * simulation.accelScale;
+ me.accelMag = 0.00008 * simulation.accelScale;
me.memory = 30;
me.leaveBody = false;
+ me.isDropPowerUp = false;
me.seePlayerFreq = Math.round((80 + 50 * Math.random()) * simulation.lookFreqScale);
- me.frictionAir = 0.002;
+ me.frictionAir = 0.004;
me.do = function() {
this.gravity();
this.seePlayerCheck();
this.checkStatus();
this.attraction();
+
+ // this.alwaysSeePlayer();
+ // this.checkStatus();
+ // this.attraction();
};
},
// exploder(x, y, radius = 40 + Math.ceil(Math.random() * 50)) {
@@ -2859,7 +2965,7 @@ const spawn = {
// //run this function on hitting player
// this.explode();
// };
- me.collisionFilter.mask = cat.bullet | cat.player | cat.mob
+ me.collisionFilter.mask = cat.bullet | cat.player | cat.mob | cat.body
me.accelMag = 0.0004 * simulation.accelScale;
me.leaveBody = false;
me.frictionAir = 0.02;
@@ -2943,7 +3049,7 @@ const spawn = {
this.fill = `rgba(220,220,255,${0.3 + 0.6 *this.health})`
};
me.leaveBody = false;
- me.dropPowerUp = false;
+ me.isDropPowerUp = false;
me.showHealthBar = false;
me.shieldTargetID = target.id
@@ -3000,7 +3106,7 @@ const spawn = {
}
};
me.leaveBody = false;
- me.dropPowerUp = false;
+ me.isDropPowerUp = false;
me.showHealthBar = false;
mob[mob.length - 1] = mob[mob.length - 1 - nodes];
mob[mob.length - 1 - nodes] = me;
@@ -3023,7 +3129,7 @@ const spawn = {
me.stroke = "transparent";
Matter.Body.setDensity(me, 0.1); //normal is 0.001
me.leaveBody = false;
- me.dropPowerUp = false;
+ me.isDropPowerUp = false;
me.showHealthBar = false;
// me.isShielded = true
me.collisionFilter.category = cat.mobBullet;
@@ -3062,7 +3168,7 @@ const spawn = {
me.memory = Infinity;
me.frictionAir = 0.01;
me.accelMag = 0.00004 * simulation.accelScale;
- me.collisionFilter.mask = cat.player | cat.bullet
+ me.collisionFilter.mask = cat.player | cat.bullet | cat.body
spawn.shield(me, x, y, 1);
const rangeInnerVsOuter = Math.random()
@@ -3240,7 +3346,7 @@ const spawn = {
me.frictionStatic = 1;
me.friction = 1;
me.frictionAir = 0.01;
- me.dropPowerUp = false;
+ me.isDropPowerUp = false;
me.showHealthBar = false;
me.do = function() {
@@ -3307,7 +3413,7 @@ const spawn = {
me.frictionStatic = 1;
me.friction = 1;
me.frictionAir = 0.01;
- me.dropPowerUp = false;
+ me.isDropPowerUp = false;
me.showHealthBar = false;
me.do = function() {
@@ -3357,7 +3463,7 @@ const spawn = {
me.frictionStatic = 1;
me.friction = 1;
me.frictionAir = 0.01;
- me.dropPowerUp = false;
+ me.isDropPowerUp = false;
me.showHealthBar = false;
me.do = function() {
@@ -3406,7 +3512,7 @@ const spawn = {
// me.frictionStatic = 1;
// me.friction = 1;
me.frictionAir = 0.01;
- me.dropPowerUp = false;
+ me.isDropPowerUp = false;
me.showHealthBar = false;
me.do = function() {
@@ -3455,7 +3561,7 @@ const spawn = {
// me.frictionStatic = 1;
// me.friction = 1;
me.frictionAir = 0.01;
- me.dropPowerUp = false;
+ me.isDropPowerUp = false;
me.showHealthBar = false;
me.do = function() {
diff --git a/js/tech.js b/js/tech.js
index df49cc6..a1c15f9 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -154,7 +154,7 @@
if (tech.is100Duplicate && tech.duplicationChance() > 0.99) {
tech.is100Duplicate = false
const range = 1000
- const bossOptions = ["historyBoss", "cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss"]
+ const bossOptions = ["historyBoss", "cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture"]
spawn.randomLevelBoss(m.pos.x + range, m.pos.y, bossOptions);
spawn.randomLevelBoss(m.pos.x, m.pos.y + range, bossOptions);
spawn.randomLevelBoss(m.pos.x - range, m.pos.y, bossOptions);
@@ -230,7 +230,7 @@
},
{
name: "active cooling",
- description: "17% decreased delay after firing
for each gun in your inventory",
+ description: "14% decreased delay after firing
for each gun in your inventory",
maxCount: 1,
count: 0,
frequency: 2,
@@ -2641,13 +2641,13 @@
},
requires: "below 100% duplication chance, below level 5, not determinism",
effect() {
+ // tech.cancelCount = 0
tech.isCancelDuplication = true
- tech.cancelCount = 0
simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw
},
remove() {
- tech.isCancelDuplication = false
// tech.cancelCount = 0
+ tech.isCancelDuplication = false
if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal
}
},
@@ -5015,7 +5015,7 @@
effect() {
setInterval(() => {
for (let i = 0; i < mob.length; i++) {
- if (!mob[i].isShielded && !mob[i].shield && mob[i].dropPowerUp) spawn.shield(mob[i], mob[i].position.x, mob[i].position.y, 1, true);
+ if (!mob[i].isShielded && !mob[i].shield && mob[i].isDropPowerUp) spawn.shield(mob[i], mob[i].position.x, mob[i].position.y, 1, true);
}
}, 5000); //every 5 seconds
},
@@ -5048,7 +5048,7 @@
},
{
name: "panopticon",
- description: "experiment: mobs can see you all the time",
+ description: "experiment: mobs can always see you",
maxCount: 1,
count: 0,
frequency: 0,
@@ -5062,7 +5062,7 @@
effect() {
setInterval(() => {
for (let i = 0; i < mob.length; i++) {
- if (!mob[i].shield && mob[i].dropPowerUp) {
+ if (!mob[i].shield && mob[i].isDropPowerUp) {
mob[i].locatePlayer()
mob[i].seePlayer.yes = true;
}
@@ -5071,6 +5071,26 @@
},
remove() {}
},
+ {
+ name: "decomposers",
+ description: "experiment: after they die
mobs leave behind spawns",
+ maxCount: 1,
+ count: 0,
+ frequency: 0,
+ isBadRandomOption: true,
+ isExperimentalMode: true,
+ allowed() {
+ return build.isExperimentSelection
+ },
+ requires: "",
+ effect() {
+ tech.deathSpawns = 0.2
+ },
+ remove() {
+ tech.deathSpawns = 0
+ }
+ },
+
//**************************************************
//************************************************** JUNK
//************************************************** tech
@@ -5093,9 +5113,29 @@
// },
// remove() {}
// },
+ {
+ name: "decomposers",
+ description: "after they die mobs leave behind spawns",
+ maxCount: 1,
+ count: 0,
+ frequency: 0,
+ isExperimentHide: true,
+ isNonRefundable: true,
+ isJunk: true,
+ allowed() {
+ return build.isExperimentSelection
+ },
+ requires: "",
+ effect() {
+ tech.deathSpawns = 0.2
+ },
+ remove() {
+ tech.deathSpawns = 0
+ }
+ },
{
name: "panopticon",
- description: "experiment: mobs can see you all the time",
+ description: "mobs can always see you",
maxCount: 1,
count: 0,
frequency: 0,
@@ -5109,7 +5149,7 @@
effect() {
setInterval(() => {
for (let i = 0; i < mob.length; i++) {
- if (!mob[i].shield && mob[i].dropPowerUp) {
+ if (!mob[i].shield && mob[i].isDropPowerUp) {
mob[i].locatePlayer()
mob[i].seePlayer.yes = true;
}
@@ -6365,5 +6405,6 @@
isNoHeals: null,
frequencyResonance: null,
isAlwaysFire: null,
- isDroneRespawn: null
+ isDroneRespawn: null,
+ deathSpawns: null
}
\ No newline at end of file
diff --git a/todo.txt b/todo.txt
index a20f323..cc8ad71 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,16 +1,19 @@
******************************************************** NEXT PATCH ********************************************************
-
-experiment and junk: panopticon - mobs can see you all the time
-scrap bots now have a 33% chance to spawn for 10 seconds after killing a mob
- (was 20% chance for 20 seconds)
-tech: scrap refit - killing a mob resets your functional scrap bots back to 10 seconds of operation
+experiment and junk tech: decomposers - mobs leave behind spawns when they die
-several damage tech have reduced damage by about 10%
-spores do 20% more damage, but last 1 second shorter
+new levelBoss - a cluster of larger spawns
+ while it's alive all mobs other leave behind spawns
+
+added block collisions to most no collide mobs
+ (this should buff block throwing and pilot wave)
******************************************************** BUGS ********************************************************
+Copied build urls broke. You get the guns but none of the tech
+
+spawns are forming node groups, but why??
+
you have to press z once to get copy to work for simulation.enableConstructMode() sometimes
not sure how to reproduce, but it happens often on the first draw
@@ -39,6 +42,34 @@ fix door.isOpen actually meaning isClosed?
******************************************************** TODO ********************************************************
+tech plasma field - plasma field becomes an aoe damage field with the same radius
+ 200% more energy drain, 100% more damage
+ draw a square (or two) that rapidly spins
+
+blocking produces ice-IX
+ at the block location?
+ how to get bullets to not hit the blocked mob
+ spawn at player head?
+ only applies to blocking with a cool down
+ nano-scale?
+ standing wave harmonics
+ maybe just a chance to proc for perfect diamagnetism
+
+laser beam splitter should only increase by 1,2,3,4 not 1,3,5
+
+tech field: while _____ is active take 100% more harm and do 100% more damage
+ while firing
+ or while plasma field is active
+
+make a boss that increases tech.deathSpawns while it is alive
+ tech.deathSpawns += 2
+ on death tech.deathSpawns -= 2
+ how to make it clear that the bos is producing the spawns?
+ boss is make of many spawn-like mobs
+ but they need to have a different color from spawns
+ similar to how cellBoss works
+ with stronger flocking/attracting forces
+
quantum foam: hold fire to charge up foam, release fire to let go an amount relative to hold long you held fire
foam gun fires a bullet that tracks how long mouse is down
when mouse is up it streams out a hose of foam based on how long foam was down