sprayBoss

new sprayBoss on reactor level
  shows up 50% of the time
  unbalanced right now, so give me feedback
This commit is contained in:
landgreen
2022-02-13 06:48:23 -08:00
parent 67a6ee29d1
commit 8b3a4c0cb9
10 changed files with 218 additions and 86 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -1371,7 +1371,7 @@ const b = {
requestAnimationFrame(() => { who.isShielded = true }); requestAnimationFrame(() => { who.isShielded = true });
} }
if (tech.fragments) { if (tech.fragments) {
b.targetedNail(this.vertices[2], tech.fragments * 4) b.targetedNail(this.vertices[2], tech.fragments * 3)
if (!isReturn) this.endCycle = 0; if (!isReturn) this.endCycle = 0;
} }
if (!who.isBadTarget) { if (!who.isBadTarget) {
@@ -5650,7 +5650,7 @@ const b = {
Matter.Body.setVelocity(this, { x: -0.4 * this.velocity.x, y: -0.4 * this.velocity.y }); Matter.Body.setVelocity(this, { x: -0.4 * this.velocity.x, y: -0.4 * this.velocity.y });
} else { } else {
if (tech.fragments && this.speed > 10) { if (tech.fragments && this.speed > 10) {
b.targetedNail(this.position, tech.fragments * 17) b.targetedNail(this.position, tech.fragments * 13)
this.endCycle = 0 //triggers despawn this.endCycle = 0 //triggers despawn
} }
} }

View File

@@ -154,6 +154,11 @@ window.addEventListener('load', () => {
} }
if (property === "level") document.getElementById("starting-level").value = Math.max(Number(set[property]) - 1, 0) if (property === "level") document.getElementById("starting-level").value = Math.max(Number(set[property]) - 1, 0)
if (property === "noPower") document.getElementById("no-power-ups").checked = Number(set[property]) if (property === "noPower") document.getElementById("no-power-ups").checked = Number(set[property])
// if (property === "seed") {
// document.getElementById("seed").placeholder = Math.initialSeed = String(set[property])
// Math.seed = Math.abs(Math.hash(Math.initialSeed))
// level.populateLevels()
// }
} }
} else if (localSettings.isTrainingNotAttempted && localSettings.runCount < 30) { //make training button more obvious for new players } else if (localSettings.isTrainingNotAttempted && localSettings.runCount < 30) { //make training button more obvious for new players
// document.getElementById("training-button").style.border = "0px #333 solid"; // document.getElementById("training-button").style.border = "0px #333 solid";
@@ -555,6 +560,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
}, },
shareURL(isCustom = false) { shareURL(isCustom = false) {
let url = "https://landgreen.github.io/sidescroller/index.html?" let url = "https://landgreen.github.io/sidescroller/index.html?"
url += `&seed=${Math.initialSeed}`
let count = 0; let count = 0;
for (let i = 0; i < b.inventory.length; i++) { for (let i = 0; i < b.inventory.length; i++) {
if (b.guns[b.inventory[i]].have) { if (b.guns[b.inventory[i]].have) {
@@ -585,16 +591,12 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
navigator.clipboard.writeText(url).then(function() { navigator.clipboard.writeText(url).then(function() {
/* clipboard successfully set */ /* clipboard successfully set */
if (isCustom) { if (isCustom) {
setTimeout(function() { setTimeout(function() { alert('n-gon build URL copied to clipboard.\nPaste into browser address bar.') }, 300);
alert('n-gon build URL copied to clipboard.\nPaste into browser address bar.')
}, 300);
} }
}, function() { }, function() {
/* clipboard write failed */ /* clipboard write failed */
if (isCustom) { if (isCustom) {
setTimeout(function() { setTimeout(function() { alert('copy failed') }, 300);
alert('copy failed')
}, 300);
} }
console.log('copy failed') console.log('copy failed')
}); });

View File

@@ -14,22 +14,23 @@ const level = {
levels: [], levels: [],
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
// m.immuneCycle = Infinity //you can't take damage
// localSettings.levelsClearedLastGame = 10
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// m.setField("standing wave") // m.setField("standing wave")
// b.giveGuns("harpoon") // b.giveGuns("harpoon")
// for (let i = 0; i < 100; i++) tech.giveTech("slow light") // for (let i = 0; i < 100; i++) tech.giveTech("slow light")
// tech.giveTech("recycling") // tech.giveTech("tungsten carbide")
// for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech"); // for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech");
// tech.giveTech("tinsellated flagella") // tech.giveTech("tinsellated flagella")
// for (let i = 0; i < 3; i++) tech.giveTech("undefined") // for (let i = 0; i < 3; i++) tech.giveTech("undefined")
// tech.giveTech("nail-bot") // tech.giveTech("decoherence")
// for (let i = 10; i < tech.tech.length; i++) { tech.tech[i].isBanished = true }
// powerUps.research.changeRerolls(100000)
// for (let i = 0; i < 1; i++) tech.giveTech("reticulum") // for (let i = 0; i < 1; i++) tech.giveTech("reticulum")
// for (let i = 0; i < 2; i++) tech.giveTech("laser-bot") // for (let i = 0; i < 2; i++) tech.giveTech("laser-bot")
// tech.tech[297].frequency = 100 // tech.tech[297].frequency = 100
// m.immuneCycle = Infinity //you can't take damage
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// simulation.enableConstructMode() //used to build maps in testing mode // simulation.enableConstructMode() //used to build maps in testing mode
// level.reactor(); // level.reactor();
// level.testing(); //not in rotation, used for testing // level.testing(); //not in rotation, used for testing
@@ -220,7 +221,7 @@ const level = {
simulation.clearNow = true; //triggers in simulation.clearMap to remove all physics bodies and setup for new map simulation.clearNow = true; //triggers in simulation.clearMap to remove all physics bodies and setup for new map
} }
}, },
populateLevels() { populateLevels() { //run a second time if URL is loaded
if (document.getElementById("seed").value) { if (document.getElementById("seed").value) {
Math.initialSeed = String(document.getElementById("seed").value) Math.initialSeed = String(document.getElementById("seed").value)
Math.seed = Math.abs(Math.hash(Math.initialSeed)) //update randomizer seed in case the player changed it Math.seed = Math.abs(Math.hash(Math.initialSeed)) //update randomizer seed in case the player changed it
@@ -250,7 +251,9 @@ const level = {
} }
} }
//set seeded random lists of mobs and bosses //set seeded random lists of mobs and bosses
spawn.mobTypeSpawnOrder = []
for (let i = 0; i < level.levels.length; i++) spawn.mobTypeSpawnOrder.push(spawn.fullPickList[Math.floor(Math.seededRandom(0, spawn.fullPickList.length))]) for (let i = 0; i < level.levels.length; i++) spawn.mobTypeSpawnOrder.push(spawn.fullPickList[Math.floor(Math.seededRandom(0, spawn.fullPickList.length))])
spawn.bossTypeSpawnOrder = []
for (let i = 0; i < level.levels.length * 2; i++) spawn.bossTypeSpawnOrder.push(spawn.randomBossList[Math.floor(Math.seededRandom(0, spawn.randomBossList.length))]) for (let i = 0; i < level.levels.length * 2; i++) spawn.bossTypeSpawnOrder.push(spawn.randomBossList[Math.floor(Math.seededRandom(0, spawn.randomBossList.length))])
}, },
flipHorizontal() { flipHorizontal() {
@@ -2609,25 +2612,33 @@ const level = {
document.body.style.backgroundColor = "#d0d5df" //"#d8dadf"; document.body.style.backgroundColor = "#d0d5df" //"#d8dadf";
// powerUps.spawnStartingPowerUps(1475, -1175); // powerUps.spawnStartingPowerUps(1475, -1175);
// spawn.debris(750, -2200, 3700, 16); //16 debris per level // spawn.debris(750, -2200, 3700, 16); //16 debris per level
spawn.mapRect(-1525, -2825, 1250, 3925); spawn.mapRect(-1525, -2825, 1250, 4925);
spawn.mapRect(-400, -2025, 625, 925); spawn.mapRect(-400, -2025, 625, 925);
spawn.mapRect(-400, -750, 625, 1200); spawn.mapRect(-400, -750, 625, 1200);
spawn.mapRect(-425, 0, 4200, 1100); // spawn.mapVertex(200, 0, "-200 0 -100 -100 100 -100 200 0");
spawn.bodyRect(225, -100, 100, 100, 0.5);
spawn.bodyRect(225, -200, 75, 100, 0.5);
spawn.bodyRect(325, -70, 150, 70, 1);
spawn.bodyRect(-275, -850, 75, 100, 0.4);
spawn.bodyRect(1525, -100, 100, 100, 0.3);
spawn.bodyRect(2325, -50, 125, 50, 0.3);
spawn.bodyRect(2375, -100, 50, 50, 0.3);
for (let i = 0; i < 3; ++i) powerUps.spawn(400 + 2000 * Math.random(), -25, "ammo");
spawn.mapRect(-425, 0, 4200, 2100);
spawn.mapRect(175, -1250, 50, 300); spawn.mapRect(175, -1250, 50, 300);
spawn.mapRect(-475, -2825, 4250, 1025); spawn.mapRect(-475, -2825, 4250, 1025);
// spawn.mapRect(1200, -1300, 600, 800); // spawn.mapRect(1200, -1300, 600, 800);
const a = 400 //side length const a = 400 //side length
const c = 100 //corner offset const c = 100 //corner offset
spawn.mapVertex(1487, -900, `${-a} ${-a+c} ${-a+c} ${-a} ${a-c} ${-a} ${a} ${-a+c} ${a} ${a-c} ${a-c} ${a} ${-a+c} ${a} ${-a} ${a-c}`); //square with edges cut off spawn.mapVertex(1487, -900, `${-a} ${-a+c} ${-a+c} ${-a} ${a-c} ${-a} ${a} ${-a+c} ${a} ${a-c} ${a-c} ${a} ${-a+c} ${a} ${-a} ${a-c}`); //square with edges cut off
//exit //exit
spawn.mapRect(3300, -2825, 1125, 3925); spawn.mapRect(3300, -2825, 1125, 4925);
spawn.mapRect(2750, -2150, 1025, 1775); spawn.mapRect(2750, -2150, 1025, 1775);
spawn.mapRect(2750, -475, 50, 300); spawn.mapRect(2750, -475, 50, 300);
// spawn.bodyRect(1540, -1110, 300, 25, 0.9); // spawn.bodyRect(1540, -1110, 300, 25, 0.9);
// spawn.randomSmallMob(1300, -70); // spawn.randomSmallMob(1300, -70);
// spawn.randomMob(2650, -975, 0.8); // spawn.randomMob(2650, -975, 0.8);
@@ -2651,6 +2662,8 @@ const level = {
let isSpawnedBoss = false let isSpawnedBoss = false
level.custom = () => { level.custom = () => {
// player.force.y -= player.mass * simulation.g * 0.4; //float player
if (isDoorsLocked) { if (isDoorsLocked) {
if (!isFightOver && !(simulation.cycle % 120)) { //once a second if (!isFightOver && !(simulation.cycle % 120)) { //once a second
let isFoundBoss = false let isFoundBoss = false
@@ -2665,7 +2678,6 @@ const level = {
doorIn.isClosing = false doorIn.isClosing = false
doorOut.isClosing = false doorOut.isClosing = false
powerUps.spawnBossPowerUp(2900, -100) powerUps.spawnBossPowerUp(2900, -100)
for (let i = 0; i < 3; ++i) powerUps.spawn(2900 + 30 * i, -300, "ammo");
} }
} }
@@ -2688,12 +2700,19 @@ const level = {
doorOut.isClosing = true doorOut.isClosing = true
if (!isSpawnedBoss) { if (!isSpawnedBoss) {
isSpawnedBoss = true isSpawnedBoss = true
for (let i = 0, len = simulation.difficulty / 20; i < len; ++i) spawn.bounceBoss(1487 + 300 * i, -1525, 80, false); if (Math.random() > 0.5) {
for (let i = 0, len = Math.min(simulation.difficulty / 20, 5); i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false);
} else {
for (let i = 0, len = Math.min(simulation.difficulty / 10, 10); i < len; ++i) spawn.sprayBoss(2400 - 150 * i, -225, 30, false)
}
// for (let i = 0, len = 3 + simulation.difficulty / 20; i < len; ++i) spawn.mantisBoss(1487 + 300 * i, -1525, 35, false)
} }
} }
doorIn.openClose(); doorIn.openClose();
doorOut.openClose(); doorOut.openClose();
ctx.fillStyle = "#d5ebef"
ctx.fillRect(2750, -375, 550, 375)
level.enter.draw(); level.enter.draw();
level.exit.drawAndCheck(); level.exit.drawAndCheck();
}; };
@@ -2704,6 +2723,10 @@ const level = {
// } // }
doorIn.draw(); doorIn.draw();
doorOut.draw(); doorOut.draw();
ctx.fillStyle = "rgba(0,0,0,0.05)"
ctx.fillRect(-275, -1100, 500, 350);
// ctx.fillStyle = "rgba(0,255,255,0.1)"
// ctx.fillRect(2750, -375, 550, 375)
}; };
// if (simulation.difficulty > 1) spawn.randomLevelBoss(2200, -1300); // if (simulation.difficulty > 1) spawn.randomLevelBoss(2200, -1300);
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned

View File

@@ -1180,7 +1180,7 @@ const mobs = {
powerUps.spawn(this.position.x, this.position.y, "tech", false) powerUps.spawn(this.position.x, this.position.y, "tech", false)
// if (0.5 < Math.random()) powerUps.spawn(this.position.x, this.position.y, "tech", false) // if (0.5 < Math.random()) powerUps.spawn(this.position.x, this.position.y, "tech", false)
} else { } else {
const amount = 0.005 const amount = 0.0045
if (tech.isEnergyHealth) { if (tech.isEnergyHealth) {
if (m.maxEnergy > amount) { if (m.maxEnergy > amount) {
tech.healMaxEnergyBonus -= amount tech.healMaxEnergyBonus -= amount

View File

@@ -304,7 +304,14 @@ const powerUps = {
const banishLength = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2 const banishLength = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2
for (let i = 0; i < banishLength; i++) { for (let i = 0; i < banishLength; i++) {
const index = powerUps.tech.choiceLog.length - i - 1 const index = powerUps.tech.choiceLog.length - i - 1
if (powerUps.tech.choiceLog[index] !== undefined) tech.tech[powerUps.tech.choiceLog[index]].isBanished = true if (powerUps.tech.choiceLog[index] && tech.tech[powerUps.tech.choiceLog[index]]) {
tech.tech[powerUps.tech.choiceLog[index]].isBanished = true
} else { //if no tech options available eject banish tech
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].name === "decoherence") powerUps.ejectTech(i)
}
powerUps.endDraft("tech");
}
} }
simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`) simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`)
} }
@@ -397,7 +404,18 @@ const powerUps = {
const banishLength = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2 const banishLength = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2
for (let i = 0; i < banishLength; i++) { for (let i = 0; i < banishLength; i++) {
const index = powerUps.tech.choiceLog.length - i - 1 const index = powerUps.tech.choiceLog.length - i - 1
if (powerUps.tech.choiceLog[index] !== undefined || powerUps.tech.choiceLog[index] !== null) tech.tech[powerUps.tech.choiceLog[index]].isBanished = true // console.log(index)
// console.log(powerUps.tech.choiceLog.length)
// console.log(powerUps.tech.choiceLog[index])
// console.log(tech.tech[powerUps.tech.choiceLog[index]])
if (powerUps.tech.choiceLog[index] && tech.tech[powerUps.tech.choiceLog[index]]) {
tech.tech[powerUps.tech.choiceLog[index]].isBanished = true
} else { //if no tech options available eject banish tech
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].name === "decoherence") powerUps.ejectTech(i)
}
powerUps.endDraft("tech");
}
} }
simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`) simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`)
} }
@@ -686,6 +704,7 @@ const powerUps = {
if (!tech.isSuperDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft("tech",true)'>✕</div>` if (!tech.isSuperDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft("tech",true)'>✕</div>`
text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>tech</h3>` text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>tech</h3>`
let choice1 = pick() let choice1 = pick()
console.log(choice1)
let choice2 = null let choice2 = null
let choice3 = null let choice3 = null
if (choice1 !== null) { if (choice1 !== null) {
@@ -776,12 +795,6 @@ const powerUps = {
document.getElementById("choose-grid").innerHTML = text document.getElementById("choose-grid").innerHTML = text
powerUps.showDraft(); powerUps.showDraft();
} else if (tech.isBanish) { //if no tech options available eject banish tech
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].name === "decoherence") powerUps.ejectTech(i)
}
// simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - powerUps.tech.banishLog.length)}`)
powerUps.endDraft("tech");
} }
} }
} }

View File

@@ -944,7 +944,6 @@ const simulation = {
if (m.lastKillCycle + 300 > m.cycle) { //effects active for 5 seconds after killing a mob if (m.lastKillCycle + 300 > m.cycle) { //effects active for 5 seconds after killing a mob
if (tech.isEnergyRecovery && m.immuneCycle < m.cycle) m.energy += m.maxEnergy * 0.05 if (tech.isEnergyRecovery && m.immuneCycle < m.cycle) m.energy += m.maxEnergy * 0.05
console.log(`lastKill = ${m.lastKillCycle}, cycle = ${m.cycle}, health = ${m.health}, maxHealth = ${m.maxHealth}`)
if (tech.isHealthRecovery) m.addHealth(0.01 * m.maxHealth) if (tech.isHealthRecovery) m.addHealth(0.01 * m.maxHealth)
} }

View File

@@ -1,10 +1,10 @@
//main object for spawning things in a level //main object for spawning things in a level
const spawn = { const spawn = {
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture", "growBossCulture"], nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture", "growBossCulture"],
// other bosses: suckerBoss, laserBoss, tetherBoss, //these need a particular level to work so they are not included in the random pool // other bosses: suckerBoss, laserBoss, tetherBoss, mantisBoss, bounceBoss, sprayBoss //these need a particular level to work so they are not included in the random pool
randomBossList: ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", randomBossList: ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
"powerUpBoss", "powerUpBossBaby", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", "powerUpBoss", "powerUpBossBaby", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss",
"snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "mantisBoss", "slashBoss" "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss"
], ],
bossTypeSpawnOrder: [], //preset list of boss names calculated at the start of a run by the randomSeed bossTypeSpawnOrder: [], //preset list of boss names calculated at the start of a run by the randomSeed
bossTypeSpawnIndex: 0, //increases as the boss type cycles bossTypeSpawnIndex: 0, //increases as the boss type cycles
@@ -19,26 +19,15 @@ const spawn = {
pickList: ["starter", "starter"], pickList: ["starter", "starter"],
fullPickList: [ fullPickList: [
"hopper", "hopper", "hopper", "hopper", "hopper", "hopper",
"slasher", "slasher", "slasher", "slasher", "hopper",
"stabber", "stabber", "stabber",
"springer", "springer", "springer",
"shooter", "shooter", "shooter", "shooter",
"grenadier", "grenadier", "grenadier", "grenadier",
"striker", "striker", "striker", "striker",
"laser", "laser", "laser", "laser",
"stabber", "stabber",
"springer", "springer",
"pulsar", "pulsar", "pulsar", "pulsar",
"launcher", "launcher", "launcherOne", "exploder", "sneaker", "sucker", "sniper", "spinner", "grower", "beamer", "focuser", "spawner", "ghoster",
"launcherOne",
"exploder",
"sneaker",
"sucker",
"sniper",
"spinner",
"grower",
"beamer",
"focuser",
"spawner",
"ghoster",
], ],
mobTypeSpawnOrder: [], //preset list of mob names calculated at the start of a run by the randomSeed mobTypeSpawnOrder: [], //preset list of mob names calculated at the start of a run by the randomSeed
mobTypeSpawnIndex: 0, //increases as the mob type cycles mobTypeSpawnIndex: 0, //increases as the mob type cycles
@@ -1950,7 +1939,7 @@ const spawn = {
spawn.groupShield(targets, x, y, sideLength + 1 * radius + nodes * 5 - 25); spawn.groupShield(targets, x, y, sideLength + 1 * radius + nodes * 5 - 25);
spawn.allowShields = true; spawn.allowShields = true;
}, },
mantisBoss(x, y, radius = 35) { mantisBoss(x, y, radius = 35, isSpawnBossPowerUp = true) {
mobs.spawn(x, y, 5, radius, "#6ba"); mobs.spawn(x, y, 5, radius, "#6ba");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.babyList = [] //list of mobs that are apart of this boss me.babyList = [] //list of mobs that are apart of this boss
@@ -2140,7 +2129,7 @@ const spawn = {
me.onDeath = function() { me.onDeath = function() {
this.removeCons(); this.removeCons();
powerUps.spawnBossPowerUp(this.position.x, this.position.y) if (isSpawnBossPowerUp) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
for (let i = 0; i < this.babyList.length; i++) { for (let i = 0; i < this.babyList.length; i++) {
if (this.babyList[i].alive) { if (this.babyList[i].alive) {
this.babyList[i].collisionFilter.mask = cat.map | cat.bullet | cat.player this.babyList[i].collisionFilter.mask = cat.map | cat.bullet | cat.player
@@ -3537,7 +3526,98 @@ const spawn = {
ctx.setLineDash([]); ctx.setLineDash([]);
} }
}, },
bounceBoss(x, y, radius = 80, isSpawnBossPOwerUp = true) { sprayBoss(x, y, radius = 30, isSpawnBossPowerUp = true) {
mobs.spawn(x, y, 16, radius, "rgb(255,255,255)");
let me = mob[mob.length - 1];
me.isBoss = true;
me.inertia = Infinity; //no rotation
// me.accelMag = 0.00008 + 0.00007 * simulation.accelScale;
me.burstFireFreq = 20 + Math.floor(20 * simulation.CDScale)
me.burstTotalPhases = 4 + Math.floor(2 / simulation.CDScale)
me.noFireTotalCycles = 390
me.frictionStatic = 0;
me.friction = 0;
me.frictionAir = 0;
me.restitution = 1
spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random(), 1)
Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.12 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.onDeath = function() {
if (isSpawnBossPowerUp) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
me.onDamage = function() {};
//draw radial lines from verticies showing future bullet paths?
me.radialLines = function() {
ctx.beginPath();
for (let i = 0, len = this.vertices.length; i < len; i++) {
ctx.moveTo(this.vertices[i].x, this.vertices[i].y)
const unit = Vector.add(Vector.mult(Vector.normalise(Vector.sub(this.vertices[i], this.position)), 1000), this.vertices[i])
ctx.lineTo(unit.x, unit.y)
// console.log(unit, this.vertices, this.position)
}
ctx.lineWidth = 10
ctx.strokeStyle = "rgb(200,0,200,0.03)"
ctx.stroke();
}
me.phaseCycle = 0
me.normalDoStuff = function() {
// this.seePlayerByHistory();
// this.attraction();
this.checkStatus();
me.seePlayer.recall = 1
//maintain speed //faster in the vertical to help avoid repeating patterns
if (this.speed < 0.01) {
Matter.Body.setVelocity(this, Vector.mult(Vector.normalise(Vector.sub(player.position, this.position)), 0.1));
} else {
if (Math.abs(this.velocity.y) < 15) Matter.Body.setVelocity(this, { x: this.velocity.x, y: this.velocity.y * 1.07 });
if (Math.abs(this.velocity.x) < 11) Matter.Body.setVelocity(this, { x: this.velocity.x * 1.07, y: this.velocity.y });
}
}
me.noFire = function() {
this.normalDoStuff();
this.phaseCycle++
if (this.phaseCycle > this.noFireTotalCycles) { //start burst fire mode
this.phaseCycle = -2
this.do = this.burstFire
this.frictionAir = 1
if (!this.isShielded) spawn.shield(this, this.position.x, this.position.y, 1);
}
};
me.burstFire = function() {
this.normalDoStuff();
this.radialLines()
if (!(simulation.cycle % this.burstFireFreq)) {
this.phaseCycle++
if (this.phaseCycle > this.burstTotalPhases) { //start spiral fire mode
this.phaseCycle = -7
this.do = this.noFire
this.frictionAir = 0;
Matter.Body.setVelocity(this, Vector.rotate({ x: 20, y: 0 }, 2 * Math.PI * Math.random()));
if (this.isShielded) { //remove shield
for (let i = 0; i < mob.length; i++) {
if (mob[i].shield) mob[i].death()
}
}
}
if (this.phaseCycle > -1) {
Matter.Body.rotate(this, 0.08)
for (let i = 0, len = this.vertices.length; i < len; i++) { //fire a bullet from each vertex
spawn.sniperBullet(this.vertices[i].x, this.vertices[i].y, 8, 4);
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[i])), -26)
Matter.Body.setVelocity(mob[mob.length - 1], {
x: velocity.x,
y: velocity.y
});
}
}
}
};
me.do = me.noFire
Matter.Body.setVelocity(me, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) });
},
bounceBoss(x, y, radius = 80, isSpawnBossPowerUp = true) {
mobs.spawn(x, y, 0, radius, "rgb(255,255,255)") // "rgb(201,202,225)"); mobs.spawn(x, y, 0, radius, "rgb(255,255,255)") // "rgb(201,202,225)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
Matter.Body.rotate(me, 2 * Math.PI * Math.random()); Matter.Body.rotate(me, 2 * Math.PI * Math.random());
@@ -3563,7 +3643,7 @@ const spawn = {
this.damageReduction = 0 this.damageReduction = 0
} }
}; };
if (isSpawnBossPOwerUp) me.onDeath = function() { powerUps.spawnBossPowerUp(this.position.x, this.position.y) }; if (isSpawnBossPowerUp) me.onDeath = function() { powerUps.spawnBossPowerUp(this.position.x, this.position.y) };
me.cycle = 0 me.cycle = 0
me.nextHealthThreshold = 0.75 me.nextHealthThreshold = 0.75
me.fireCount = 0 me.fireCount = 0
@@ -4411,8 +4491,7 @@ const spawn = {
} }
}; };
}, },
sniperBullet(x, y, radius = 9, sides = 4) { sniperBullet(x, y, radius = 9, sides = 4) { //bullets
//bullets
mobs.spawn(x, y, sides, radius, "rgb(255,0,155)"); mobs.spawn(x, y, sides, radius, "rgb(255,0,155)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.stroke = "transparent"; me.stroke = "transparent";
@@ -4431,10 +4510,23 @@ const spawn = {
me.showHealthBar = false; me.showHealthBar = false;
me.collisionFilter.category = cat.mobBullet; me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet; me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
me.onDeath = function() {
if (simulation.difficulty > 11) { //explode AoE
const radius = 100 + simulation.difficulty + 60 * Math.random()
if (m.immuneCycle < m.cycle && Vector.magnitude(Vector.sub(this.position, player.position)) < radius) m.damage(0.0004 * radius * simulation.dmgScale);
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: radius,
color: "rgba(255,0,155,0.5)",
time: simulation.drawTime
});
}
};
me.do = function() { me.do = function() {
// this.gravity(); // this.gravity();
this.timeLimit(); this.timeLimit();
if (Matter.Query.collides(this, map).length > 0 || Matter.Query.collides(this, body).length > 0 && this.speed < 3) { if (Matter.Query.collides(this, map).length > 0 || Matter.Query.collides(this, body).length > 0 && this.speed < 10) {
this.isDropPowerUp = false; this.isDropPowerUp = false;
this.death(); //death with no power up this.death(); //death with no power up
} }

View File

@@ -221,7 +221,7 @@ const tech = {
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance()) if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
if (tech.isLowEnergyDamage) dmg *= 1 + 0.7 * Math.max(0, 1 - m.energy) if (tech.isLowEnergyDamage) dmg *= 1 + 0.7 * Math.max(0, 1 - m.energy)
if (tech.isMaxEnergyTech) dmg *= 1.5 if (tech.isMaxEnergyTech) dmg *= 1.5
if (tech.isEnergyNoAmmo) dmg *= 1.66 if (tech.isEnergyNoAmmo) dmg *= 1.70
if (tech.isDamageForGuns) dmg *= 1 + 0.12 * b.inventory.length if (tech.isDamageForGuns) dmg *= 1 + 0.12 * b.inventory.length
if (tech.isLowHealthDmg) dmg *= 1 + Math.max(0, 1 - m.health) * 0.5 if (tech.isLowHealthDmg) dmg *= 1 + Math.max(0, 1 - m.health) * 0.5
if (tech.isHarmDamage && m.lastHarmCycle + 600 > m.cycle) dmg *= 3; if (tech.isHarmDamage && m.lastHarmCycle + 600 > m.cycle) dmg *= 3;
@@ -230,7 +230,7 @@ const tech = {
if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage
if (tech.isEnergyDamage) dmg *= 1 + m.energy * 0.125; if (tech.isEnergyDamage) dmg *= 1 + m.energy * 0.125;
if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.007 if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.007
if (tech.isRerollDamage) dmg *= 1 + 0.037 * powerUps.research.count if (tech.isRerollDamage) dmg *= 1 + 0.038 * powerUps.research.count
if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.25 if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.25
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2 if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2
if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.66, player.speed * 0.0165) if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.66, player.speed * 0.0165)
@@ -580,7 +580,7 @@ const tech = {
}, },
{ {
name: "exciton", name: "exciton",
description: `increase <strong class='color-d'>damage</strong> by <strong>66%</strong>, but<br>${powerUps.orb.ammo()} will no longer <strong>spawn</strong>`, description: `increase <strong class='color-d'>damage</strong> by <strong>70%</strong>, but<br>${powerUps.orb.ammo()} will no longer <strong>spawn</strong>`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2879,7 +2879,7 @@ const tech = {
}, },
{ {
name: "Bayesian statistics", name: "Bayesian statistics",
description: `increase <strong class='color-d'>damage</strong> by <strong>3.7%</strong><br>for each ${powerUps.orb.research(1)} in your inventory`, description: `increase <strong class='color-d'>damage</strong> by <strong>3.8%</strong><br>for each ${powerUps.orb.research(1)} in your inventory`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
@@ -3067,7 +3067,7 @@ const tech = {
}, },
{ {
name: "particle collider", name: "particle collider",
description: `<strong>clicking</strong> <strong class='color-m'>tech</strong> while <strong>paused</strong> <strong>ejects</strong> them<br><em><strong>4%</strong> chance to convert that tech into <strong class='color-f'>energy</strong></em>`, description: `<strong>clicking</strong> <strong class='color-m'>tech</strong> while paused <strong>ejects</strong> them<br><em><strong>4%</strong> chance to convert that tech into <strong class='color-f'>energy</strong></em>`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -3340,9 +3340,9 @@ const tech = {
frequencyDefault: 10, frequencyDefault: 10,
isNonRefundable: true, isNonRefundable: true,
allowed() { allowed() {
return tech.duplicationChance() > 0.99 return tech.duplicationChance() > 0.7
}, },
requires: "duplication chance above 99%", requires: "duplication chance above 70%",
effect() { effect() {
tech.is111Duplicate = true; tech.is111Duplicate = true;
tech.maxDuplicationEvent() tech.maxDuplicationEvent()
@@ -3522,7 +3522,7 @@ const tech = {
}, },
{ {
name: "reinforcement learning", name: "reinforcement learning",
description: "increase the <strong class='flicker'>frequency</strong> of finding copies of<br>recursive <strong class='color-m'>tech</strong> you already have by <strong>1000%</strong>", description: "increase the <strong class='flicker'>frequency</strong> of finding copies of<br>your current recursive <strong class='color-m'>tech</strong> by <strong>1000%</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -6723,7 +6723,7 @@ const tech = {
}, },
{ {
name: "no-cloning theorem", name: "no-cloning theorem",
description: `<strong>40%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>after a <strong>mob</strong> <strong>dies</strong>, lose <strong>2%</strong> <strong class='color-dup'>duplication</strong> chance`, description: `<strong>45%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>after a <strong>mob</strong> <strong>dies</strong>, lose <strong>2%</strong> <strong class='color-dup'>duplication</strong> chance`,
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -6734,7 +6734,7 @@ const tech = {
}, },
requires: "cloaking, time dilation", requires: "cloaking, time dilation",
effect() { effect() {
tech.cloakDuplication = 0.4 tech.cloakDuplication = 0.45
powerUps.setDupChance(); //needed after adjusting duplication chance powerUps.setDupChance(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.4); if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.4);
}, },
@@ -6745,7 +6745,7 @@ const tech = {
}, },
{ {
name: "symbiosis", name: "symbiosis",
description: "after a <strong>mob</strong> <strong>dies</strong>, lose <strong>0.5</strong> max <strong class='color-h'>health</strong><br><strong>bosses</strong> spawn <strong>1</strong> extra <strong class='color-m'>tech</strong> after they <strong>die</strong>", description: "after a <strong>mob</strong> <strong>dies</strong>, lose <strong>0.45</strong> max <strong class='color-h'>health</strong><br><strong>bosses</strong> spawn <strong>1</strong> extra <strong class='color-m'>tech</strong> after they <strong>die</strong>",
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,

View File

@@ -1,20 +1,21 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
harpoon's crouch is now a harpoon sized railgun new sprayBoss on reactor level
tech: halfwave rectifier now gives energy on harpoon/railgun charge and also stops harpoon from draining energy when it retracts shows up 50% of the time
toggling harpoon does 800 -> 600% more damage unbalanced right now, so give me feedback
perfect diamagnetism default field is a bit larger
bug fix with several periodic checks running off simulation time
they now run on player time and will be active during time dilation
fixed a bug where lore wasn't working
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
tech doing damage refunds up to 50% of damage take in last 10 seconds
use history to manage this?
tech: frozen mobs dies at 10% life
CPt disables the falling damage tech
make a seed/hash system that controls only the tech/guns/fields shown make a seed/hash system that controls only the tech/guns/fields shown
URL sharing could include a seed URL sharing could include a seed
seed will control: seed controls:
seeded random at start - random level boss, mob types list, level order, horizontal flip seeded random at start - random level boss, mob types list, level order, horizontal flip
seeded random during run - tech, gun, field choices seeded random during run - tech, gun, field choices
not seeded random - mob spawns, mob size, minor level differences, custom level boss choices, ammo rewards, tech effect randomness not seeded random - mob spawns, mob size, minor level differences, custom level boss choices, ammo rewards, tech effect randomness
@@ -22,11 +23,6 @@ make a seed/hash system that controls only the tech/guns/fields shown
make option for a daily seed: seed = day+year make option for a daily seed: seed = day+year
give 1 extra tech for doing the daily seeded run give 1 extra tech for doing the daily seeded run
make the option for the daily run, a secret exit in the intro level? make the option for the daily run, a secret exit in the intro level?
when you die
randomize seed
display new seed
show previous run seed
edit div in settings
tech upgrade to anthropic principle to make it trigger at 50% life and 0% once per map tech upgrade to anthropic principle to make it trigger at 50% life and 0% once per map
@@ -35,13 +31,20 @@ JUNK tech: https://bindingofisaacrebirth.fandom.com/wiki/Damocles
cloaking field doesn't show energy over max cloaking field doesn't show energy over max
junk tech or regular tech with this named
wiki: List of common misconceptions
run more profiles of n-gon to fix performance issues run more profiles of n-gon to fix performance issues
sprayBoss
reactor or everywhere?
reactor reactor
hopBoss life-like cellular automata boss
https://scratch.mit.edu/projects/77724260/
night/day?
boss on far right produces more "on" cells
tailBoss
story the last 5 seconds of position, draw damage circles over those positions, like a tail
limit mantis boss to only reactor?
laserBoss?
swoopBoss: hides in top center swoopBoss: hides in top center
take a lap around the map that you have to dodge take a lap around the map that you have to dodge
spawn mobs spawn mobs