frequency

some tech now has 2x,3x,4x frequency of showing up
  (most tech is at 1x, a few are at 2x if they have a rare requirement to unlock)
reworked junk and lore tech systems
  (might be some new bugs)

tech that used to just summon a power up now also increases tech frequency
removed the 4 perpetual techs

maybe fixed immune boss bug on detours level
This commit is contained in:
landgreen
2021-03-02 04:24:23 -08:00
parent e3ef0f00e3
commit 9e98ceb4e1
10 changed files with 677 additions and 420 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -3922,11 +3922,10 @@ const b = {
ammoPack: 36, ammoPack: 36,
have: false, have: false,
fire() { fire() {
if (tech.foamFutureFire) {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 15 : 5) * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 15 : 5) * b.fireCD); // cool down
const radius = (m.crouch ? 10 + 5 * Math.random() : 4 + 6 * Math.random()) + (tech.isAmmoFoamSize && this.ammo < 300) * 12 const radius = (m.crouch ? 10 + 5 * Math.random() : 4 + 6 * Math.random()) + (tech.isAmmoFoamSize && this.ammo < 300) * 12
const SPEED = 18 - radius * 0.4; const SPEED = 18 - radius * 0.4;
const dir = m.angle + 0.2 * (Math.random() - 0.5) const dir = m.angle + 0.15 * (Math.random() - 0.5)
const velocity = { const velocity = {
x: SPEED * Math.cos(dir), x: SPEED * Math.cos(dir),
y: SPEED * Math.sin(dir) y: SPEED * Math.sin(dir)
@@ -3935,35 +3934,22 @@ const b = {
x: m.pos.x + 30 * Math.cos(m.angle), x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle) y: m.pos.y + 30 * Math.sin(m.angle)
} }
if (tech.foamFutureFire) {
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: position.x, x: position.x,
y: position.y, y: position.y,
radius: 5, radius: 5,
color: "rgba(0,0,0,0.1)", color: "rgba(0,0,0,0.1)",
time: 18 * tech.foamFutureFire time: 15 * tech.foamFutureFire
}); });
setTimeout(() => { setTimeout(() => {
if (!simulation.paused) { if (!simulation.paused) {
b.foam(position, velocity, radius) b.foam(position, Vector.rotate(velocity, 0.5 * (Math.random() - 0.5)), radius)
bullet[bullet.length - 1].damage = (1 + 1.53 * tech.foamFutureFire) * (tech.isFastFoam ? 0.048 : 0.012) //double damage bullet[bullet.length - 1].damage = (1 + 1.43 * tech.foamFutureFire) * (tech.isFastFoam ? 0.048 : 0.012) //double damage
} }
}, 300 * tech.foamFutureFire); }, 250 * tech.foamFutureFire);
} else { } else {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 15 : 5) * b.fireCD); // cool down b.foam(position, Vector.rotate(velocity, 0.5 * (Math.random() - 0.5)), radius)
const radius = (m.crouch ? 10 + 5 * Math.random() : 4 + 6 * Math.random()) + (tech.isAmmoFoamSize && this.ammo < 300) * 12
const SPEED = 18 - radius * 0.4;
const dir = m.angle + 0.2 * (Math.random() - 0.5)
const velocity = {
x: SPEED * Math.cos(dir),
y: SPEED * Math.sin(dir)
}
const position = {
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
}
b.foam(position, velocity, radius)
} }
} }
}, },

View File

@@ -138,7 +138,7 @@ function collisionChecks(event) {
y: mob[k].velocity.y - 8 * Math.sin(angle) y: mob[k].velocity.y - 8 * Math.sin(angle)
}); });
if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && mob[k].dropPowerUp && m.energy > 0.34 * m.maxEnergy) { if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].dropPowerUp && m.energy > 0.34 * m.maxEnergy) {
m.energy -= 0.33 * m.maxEnergy m.energy -= 0.33 * m.maxEnergy
m.immuneCycle = 0; //player doesn't go immune to collision damage m.immuneCycle = 0; //player doesn't go immune to collision damage
mob[k].death(); mob[k].death();

View File

@@ -485,7 +485,9 @@ const build = {
removeOne(); removeOne();
} }
simulation.isCheating = true; simulation.isCheating = true;
tech.removeLoreTechFromPool(); for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].isLore) tech.tech[i].frequency = 0;
}
document.body.style.cursor = "none"; document.body.style.cursor = "none";
document.body.style.overflow = "hidden" document.body.style.overflow = "hidden"
document.getElementById("experiment-grid").style.display = "none" document.getElementById("experiment-grid").style.display = "none"
@@ -766,7 +768,13 @@ window.addEventListener("keydown", function(event) {
if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'inline' if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'inline'
if (!simulation.isCheating) { if (!simulation.isCheating) {
simulation.isCheating = true; simulation.isCheating = true;
tech.removeLoreTechFromPool(); lore.techCount = 0;
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].isLore) {
tech.tech[i].frequency = 0;
tech.tech[i].count = 0;
}
}
} }
simulation.makeTextLog( simulation.makeTextLog(
`<table class="pause-table"> `<table class="pause-table">

View File

@@ -12,7 +12,7 @@ const level = {
start() { start() {
if (level.levelsCleared === 0) { //this code only runs on the first level if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.enableConstructMode() //used to build maps in testing mode // simulation.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(5) // level.difficultyIncrease(25)
// simulation.zoomScale = 1000; // simulation.zoomScale = 1000;
// simulation.setZoom(); // simulation.setZoom();
// m.setField("nano-scale manufacturing") // m.setField("nano-scale manufacturing")
@@ -56,7 +56,6 @@ const level = {
// level.basement(); //fan level // level.basement(); //fan level
// level.stronghold() //fan level // level.stronghold() //fan level
for (let i = 0; i < 150; i++) tech.addLoreTechToPool();
// powerUps.directSpawn(simulation.mouseInGame.x, simulation.mouseInGame.y, "tech"); // powerUps.directSpawn(simulation.mouseInGame.x, simulation.mouseInGame.y, "tech");
// tech.giveTech("undefined") // tech.giveTech("undefined")
// lore.techCount = 7 // lore.techCount = 7
@@ -101,16 +100,16 @@ const level = {
const len = Math.floor((m.maxHealth - m.health) / 0.5) const len = Math.floor((m.maxHealth - m.health) / 0.5)
for (let i = 0; i < len; i++) powerUps.spawn(player.position.x + 60 * (Math.random() - 0.5), player.position.y + 60 * (Math.random() - 0.5), "heal", false); for (let i = 0; i < len; i++) powerUps.spawn(player.position.x + 60 * (Math.random() - 0.5), player.position.y + 60 * (Math.random() - 0.5), "heal", false);
} }
if (tech.isPerpetualReroll) powerUps.spawn(player.position.x + 60 * (Math.random() - 0.5), player.position.y + 60 * (Math.random() - 0.5), "research", false); // if (tech.isPerpetualReroll) powerUps.spawn(player.position.x + 60 * (Math.random() - 0.5), player.position.y + 60 * (Math.random() - 0.5), "research", false);
if (tech.isPerpetualAmmo) { // if (tech.isPerpetualAmmo) {
for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + 60 * (Math.random() - 0.5), player.position.y + 60 * (Math.random() - 0.5), "ammo", false); // for (let i = 0; i < 3; i++) powerUps.spawn(player.position.x + 60 * (Math.random() - 0.5), player.position.y + 60 * (Math.random() - 0.5), "ammo", false);
} // }
if (tech.isPerpetualHeal) { // if (tech.isPerpetualHeal) {
for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + 60 * (Math.random() - 0.5), player.position.y + 60 * (Math.random() - 0.5), "heal", false); // for (let i = 0; i < 3; i++) powerUps.spawn(player.position.x + 60 * (Math.random() - 0.5), player.position.y + 60 * (Math.random() - 0.5), "heal", false);
} // }
if (tech.isPerpetualStun) { // if (tech.isPerpetualStun) {
for (let i = 0; i < mob.length; i++) mobs.statusStun(mob[i], 780) // for (let i = 0; i < mob.length; i++) mobs.statusStun(mob[i], 780)
} // }
if (tech.isFlipFlopHarm && tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) { if (tech.isFlipFlopHarm && tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) {
tech.isFlipFlopOn = true tech.isFlipFlopOn = true
simulation.makeTextLog(`tech.isFlipFlopOn <span class='color-symbol'>=</span> true`); simulation.makeTextLog(`tech.isFlipFlopOn <span class='color-symbol'>=</span> true`);
@@ -4027,7 +4026,11 @@ const level = {
// if (simulation.difficulty > 4) spawn.nodeGroup(8000, 630, "spawns", 8, 20, 105); // if (simulation.difficulty > 4) spawn.nodeGroup(8000, 630, "spawns", 8, 20, 105);
// } else { // } else {
spawn.randomLevelBoss(8000, 630, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "bomberBoss", "orbitalBoss"]); spawn.randomLevelBoss(8000, 630, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "bomberBoss", "orbitalBoss"]);
let me = mob[mob.length - 1]; //find level boss index
let me
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].isBoss) me = mob[i]
}
me.onDeath = function() { me.onDeath = function() {
this.removeCons(); //remove constraint this.removeCons(); //remove constraint
spawnCouloirEnHaut() spawnCouloirEnHaut()
@@ -4036,7 +4039,10 @@ const level = {
// } // }
} else { } else {
spawn.randomLevelBoss(8000, 630, ["shooterBoss"]); spawn.randomLevelBoss(8000, 630, ["shooterBoss"]);
let me = mob[mob.length - 1]; let me
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].isBoss) me = mob[i]
}
me.onDeath = function() { me.onDeath = function() {
spawnCouloirEnHaut() spawnCouloirEnHaut()
doorSortieSalle.isOpen = false; doorSortieSalle.isOpen = false;

View File

@@ -310,9 +310,16 @@ const m = {
//remove all tech and count current tech total //remove all tech and count current tech total
let totalTech = 0; let totalTech = 0;
for (let i = 0, len = tech.tech.length; i < len; i++) { for (let i = 0, len = tech.tech.length; i < len; i++) {
if (!tech.tech[i].isLore) {
if (tech.tech[i].isJunk) {
tech.tech[i].frequency = 0
} else if (tech.tech[i].frequencyDefault) {
tech.tech[i].frequency = tech.tech[i].frequencyDefault
} else {
tech.tech[i].frequency = 1
}
if ( if (
!tech.tech[i].isNonRefundable && !tech.tech[i].isNonRefundable &&
!tech.tech[i].isLore &&
tech.tech[i].name !== "many-worlds" && tech.tech[i].name !== "many-worlds" &&
tech.tech[i].name !== "decoherence" tech.tech[i].name !== "decoherence"
) { ) {
@@ -322,10 +329,11 @@ const m = {
tech.tech[i].count = 0 tech.tech[i].count = 0
} }
} }
}
// lore.techCount = 0; // lore.techCount = 0;
// tech.removeLoreTechFromPool(); // tech.removeLoreTechFromPool();
// tech.addLoreTechToPool(); // tech.addLoreTechToPool();
tech.removeJunkTechFromPool(); // tech.removeJunkTechFromPool();
tech.armorFromPowerUps = 0; tech.armorFromPowerUps = 0;
tech.totalCount = 0; tech.totalCount = 0;
const randomBotCount = b.totalBots() const randomBotCount = b.totalBots()
@@ -508,7 +516,7 @@ const m = {
if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.33; if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.33;
if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.34 if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.34
if (tech.energyRegen === 0) dmg *= 0.34 if (tech.energyRegen === 0) dmg *= 0.34
if (tech.isTurret && m.crouch) dmg *= 0.5; if (tech.isTurret && m.crouch) dmg *= 0.55;
if (tech.isFireMoveLock && input.fire) dmg *= 0.4; if (tech.isFireMoveLock && input.fire) dmg *= 0.4;
if (tech.isEntanglement && b.inventory[0] === b.activeGun) { if (tech.isEntanglement && b.inventory[0] === b.activeGun) {
for (let i = 0, len = b.inventory.length; i < len; i++) dmg *= 0.87 // 1 - 0.15 for (let i = 0, len = b.inventory.length; i < len; i++) dmg *= 0.87 // 1 - 0.15
@@ -2833,7 +2841,7 @@ const m = {
y: mob[k].velocity.y - 8 * Math.sin(angle) y: mob[k].velocity.y - 8 * Math.sin(angle)
}); });
if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && mob[k].dropPowerUp && m.energy > 0.34 * m.maxEnergy) { if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].dropPowerUp && m.energy > 0.34 * m.maxEnergy) {
m.energy -= 0.33 * m.maxEnergy m.energy -= 0.33 * m.maxEnergy
m.immuneCycle = 0; //player doesn't go immune to collision damage m.immuneCycle = 0; //player doesn't go immune to collision damage
mob[k].death(); mob[k].death();

View File

@@ -288,18 +288,14 @@ const powerUps = {
let options = []; let options = [];
for (let i = 0; i < tech.tech.length; i++) { for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].count < tech.tech[i].maxCount && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4 && tech.tech[i].allowed()) { if (tech.tech[i].count < tech.tech[i].maxCount && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4 && tech.tech[i].allowed()) {
options.push(i); for (let j = 0, len = tech.tech[i].frequency; j < len; j++) options.push(i);
} }
} }
powerUps.tech.lastTotalChoices = options.length //this is recorded so that banish can know how many tech were available powerUps.tech.lastTotalChoices = options.length //this is recorded so that banish can know how many tech were available
if (tech.isBanish) { //remove banished tech from last selection if (tech.isBanish) { //remove banished tech from last selection
for (let i = 0; i < powerUps.tech.banishLog.length; i++) { for (let i = 0; i < powerUps.tech.banishLog.length; i++) {
for (let j = 0; j < options.length; j++) { for (let j = 0; j < options.length; j++) {
if (powerUps.tech.banishLog[i] === options[j]) { if (powerUps.tech.banishLog[i] === options[j]) options.splice(j, 1)
options.splice(j, 1)
break
}
} }
} }
} else { //remove repeats from last selection } else { //remove repeats from last selection
@@ -308,10 +304,7 @@ const powerUps = {
for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection
if (options.length > totalChoices) { if (options.length > totalChoices) {
for (let j = 0, len = options.length; j < len; j++) { for (let j = 0, len = options.length; j < len; j++) {
if (powerUps.tech.choiceLog[powerUps.tech.choiceLog.length - 1 - i] === options[j]) { if (powerUps.tech.choiceLog[powerUps.tech.choiceLog.length - 1 - i] === options[j]) options.splice(j, 1) //remove previous choice from option pool
options.splice(j, 1) //remove previous choice from option pool
break
}
} }
} }
} }

View File

@@ -105,13 +105,12 @@ const spawn = {
level.levels.push("null") level.levels.push("null")
level.exit.x = 5500; level.exit.x = 5500;
level.exit.y = -330; level.exit.y = -330;
simulation.makeTextLog(`<span class="lore-text">undefined</span> <span class='color-symbol'>=</span> ${lore.techCount}/${lore.techGoal}<br>level.levels.push("null")`); simulation.makeTextLog(`<span class="lore-text">undefined</span> <span class='color-symbol'>=</span> ${lore.techCount}/${lore.techGoal}<br>level.levels.push("<span class='lore-text'>null</span>")`);
//remove block map element so exit is clear //remove block map element so exit is clear
Matter.World.remove(engine.world, map[map.length - 1]); Matter.World.remove(engine.world, map[map.length - 1]);
map.splice(map.length - 1, 1); map.splice(map.length - 1, 1);
simulation.draw.setPaths(); //redraw map draw path simulation.draw.setPaths(); //redraw map draw path
} else { } else { //reset game
//reset game
let count = 0 let count = 0
function loop() { function loop() {
@@ -133,50 +132,15 @@ const spawn = {
if (!simulation.testing) requestAnimationFrame(loop); if (!simulation.testing) requestAnimationFrame(loop);
} }
requestAnimationFrame(loop); requestAnimationFrame(loop);
// setTimeout(() => {
// if (simulation.paused || simulation.testing) isEnding = false
// simulation.makeTextLog(`simulation.complete()`);
// let delay = 2000
// for (let i = 0; i < 1; i += 0.01 + 0.2 * Math.random() * Math.random()) {
// setTimeout(function() {
// if (!simulation.paused && !simulation.testing) simulation.makeTextLog(`simulation.analysis <span class='color-symbol'>=</span> ${(i).toFixed(3)}`);
// }, delay);
// delay += 1000
// }
// setTimeout(function() {
// if (isEnding) simulation.makeTextLog(`simulation.analysis <span class='color-symbol'>=</span> 1`);
// setTimeout(() => {
// if (isEnding) simulation.makeTextLog(`<span class="lore-text">undefined</span> <span class='color-symbol'>=</span> ${lore.techCount}/10`);
// setTimeout(() => {
// if (isEnding) {
// if (isEnding) simulation.makeTextLog(`World.clear(engine.world)`);
// setTimeout(() => { if (isEnding) m.death() }, 4000);
// }
// }, 3000);
// }, 2000);
// }, delay);
// }, 5000);
} }
//ramp up damage // for (let i = 0; i < 3; i++)
for (let i = 0; i < 3; i++) level.difficultyIncrease(simulation.difficultyMode) level.difficultyIncrease(simulation.difficultyMode) //ramp up damage
//remove power Ups, to avoid spamming console
//set game to the next highest difficulty level if not on why function removeAll(array) {
// if (simulation.difficultyMode < 6) { for (let i = 0; i < array.length; ++i) Matter.World.remove(engine.world, array[i]);
// if (simulation.difficultyMode === 0) { }
// simulation.difficultyMode = 1 removeAll(powerUp);
// } else if (simulation.difficultyMode === 1) { powerUp = [];
// simulation.difficultyMode = 2
// } else if (simulation.difficultyMode === 2) {
// simulation.difficultyMode = 4
// } else {
// simulation.difficultyMode = 6
// }
// document.getElementById("difficulty-select").value = simulation.difficultyMode
// localSettings.difficultyMode = simulation.difficultyMode
// localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
// simulation.makeTextLog(`<span class='color-var'>simulation</span>.difficultyMode<span class='color-symbol'>++</span>`);
// }
//pull in particles //pull in particles
for (let i = 0, len = body.length; i < len; ++i) { for (let i = 0, len = body.length; i < len; ++i) {
@@ -186,12 +150,7 @@ const spawn = {
} }
//damage all mobs //damage all mobs
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i] !== this) { if (mob[i] !== this) mob[i].damage(Infinity, true);
mob[i].damage(Infinity, true);
// const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, mob[i].position)), -65)
// Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, velocity));
}
} }
//draw stuff //draw stuff
@@ -204,7 +163,6 @@ const spawn = {
time: 5 * (len - i + 1) time: 5 * (len - i + 1)
}); });
} }
}; };
me.onDamage = function() {}; me.onDamage = function() {};
me.cycle = 420; me.cycle = 420;
@@ -1242,7 +1200,6 @@ const spawn = {
}; };
me.awake = function() { me.awake = function() {
this.checkStatus(); this.checkStatus();
//health bar needs to be here because the position is being set //health bar needs to be here because the position is being set
const h = this.radius * 0.3; const h = this.radius * 0.3;
const w = this.radius * 2; const w = this.radius * 2;
@@ -1267,8 +1224,8 @@ const spawn = {
ctx.setLineDash([125 * Math.random(), 125 * Math.random()]); ctx.setLineDash([125 * Math.random(), 125 * Math.random()]);
// ctx.lineDashOffset = 6*(simulation.cycle % 215); // ctx.lineDashOffset = 6*(simulation.cycle % 215);
if (this.distanceToPlayer() < this.laserRange) { if (this.distanceToPlayer() < this.laserRange) {
if (m.energy > 0.003) m.energy -= 0.003 if (m.energy > 0.002) m.energy -= 0.002
if (m.immuneCycle < m.cycle && m.energy < 0.1) m.damage(0.0003 * simulation.dmgScale); if (m.immuneCycle < m.cycle) m.damage(0.0001 * simulation.dmgScale);
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(eye.x, eye.y); ctx.moveTo(eye.x, eye.y);
ctx.lineTo(m.pos.x, m.pos.y); ctx.lineTo(m.pos.x, m.pos.y);
@@ -1295,7 +1252,6 @@ const spawn = {
Matter.Body.setPosition(this, { x: history.position.x, y: history.position.y - history.yOff + 24.2859 }) //bullets move with player Matter.Body.setPosition(this, { x: history.position.x, y: history.position.y - history.yOff + 24.2859 }) //bullets move with player
} }
} }
me.do = function() { me.do = function() {
if (this.seePlayer.recall || (!(simulation.cycle % this.seePlayerFreq) && this.distanceToPlayer2() < this.seeAtDistance2 && !m.isCloak)) { if (this.seePlayer.recall || (!(simulation.cycle % this.seePlayerFreq) && this.distanceToPlayer2() < this.seeAtDistance2 && !m.isCloak)) {
setTimeout(() => { setTimeout(() => {

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,14 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** NEXT PATCH ********************************************************
tech: flip-flip - does nothing, except toggle on collisions some tech now has 2x,3x,4x frequency of showing up
tech: NOR gate - when flip-flip is ON take 0 harm from collisions (most tech is at 1x, a few are at 2x if they have a rare requirement to unlock)
tech: NAND gate - when flip-flip is ON do 55.5% damage reworked junk and lore tech systems
tech: transistor - when flip-flop is ON regen 22 energy/s, when OFF drain 3.1 energy /s (might be some new bugs)
tech: shift registers - set flip-flop to ON with a new level
tech that used to just summon a power up now also increases tech frequency
removed the 4 perpetual techs
maybe fixed immune boss bug on detours level
******************************************************** BUGS ******************************************************** ******************************************************** BUGS ********************************************************
@@ -50,8 +54,6 @@ use the floor of portal sensor on the player? to unstuck player
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
flip-flop: 13% dup chance while ON
tech- foam is attracted to mobs tech- foam is attracted to mobs
use a gravitational attraction model? use a gravitational attraction model?
could foam be attracted to other foam bullets too? could foam be attracted to other foam bullets too?