spawns
experiment and junk tech: decomposers - mobs leave behind spawns when they die 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)
This commit is contained in:
36
js/bullet.js
36
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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -331,7 +331,8 @@ const build = {
|
||||
// text += `<div class="pause-grid-module"><div class="grid-title"><div class="circle-grid junk"></div> ${tech.tech[i].name} ${isCount}</div>${tech.tech[i].description}</div></div>`
|
||||
techID.innerHTML = `<div class="grid-title"><div class="circle-grid junk"></div> ${tech.tech[i].name} ${isCount}</div>${tech.tech[i].description}</div>`
|
||||
} else if (tech.tech[i].isExperimentalMode) {
|
||||
techID.innerHTML = `${tech.tech[i].description}</div>`
|
||||
// techID.innerHTML = `${tech.tech[i].description}</div>`
|
||||
text += `<div id="tech-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'tech')"><div class="grid-title">${tech.tech[i].name}</div> ${tech.tech[i].description}</div>`
|
||||
} else {
|
||||
techID.innerHTML = `<div class="grid-title"><div class="circle-grid tech"></div> ${tech.tech[i].name} ${isCount}</div>${tech.tech[i].description}</div>`
|
||||
}
|
||||
|
||||
63
js/level.js
63
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();
|
||||
|
||||
35
js/mob.js
35
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) {
|
||||
|
||||
17
js/player.js
17
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"
|
||||
|
||||
@@ -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();
|
||||
|
||||
482
js/spawn.js
482
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() {
|
||||
|
||||
61
js/tech.js
61
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: "<strong>17%</strong> decreased <strong><em>delay</em></strong> after firing<br>for each <strong class='color-g'>gun</strong> in your inventory",
|
||||
description: "<strong>14%</strong> decreased <strong><em>delay</em></strong> after firing<br>for each <strong class='color-g'>gun</strong> 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: "<strong style='color: #f55;'>experiment:</strong> mobs can see you all the time",
|
||||
description: "<strong style='color: #f55;'>experiment:</strong> 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: "<strong style='color: #f55;'>experiment:</strong> after they die<br>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 <strong>mobs</strong> leave behind <strong>spawns</strong>",
|
||||
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: "<strong>experiment:</strong> mobs can see you all the time",
|
||||
description: "<strong>mobs</strong> 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
|
||||
}
|
||||
45
todo.txt
45
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
|
||||
|
||||
Reference in New Issue
Block a user