From 387d30eff57ff49befda551eb0aeb882286abc34 Mon Sep 17 00:00:00 2001 From: landgreen Date: Sun, 8 Aug 2021 06:05:24 -0700 Subject: [PATCH] snakeSpitBoss new boss snakeSpitBoss - it's just snake boss but it shoots little pink seekers tech: cross disciplinary - get an extra gun or field option in tech menu now that you can scroll the selection menu can be longer unified field theory - now gives 6 research, in addition to letting you switch fields when paused cardinality renamed emergence - and gives some JUNK bug fix where game crashes if you beat the boss --- .DS_Store | Bin 6148 -> 6148 bytes js/bullet.js | 21 +++----- js/index.js | 1 + js/level.js | 20 +++----- js/player.js | 4 +- js/powerup.js | 124 +++++++++++++++++++++++++-------------------- js/simulation.js | 74 +++++++++++++-------------- js/spawn.js | 127 +++++++++++++++++++++++++++++++++++++++++++++-- js/tech.js | 108 ++++++++++++++++++++++++++-------------- todo.txt | 64 ++++++------------------ 10 files changed, 333 insertions(+), 210 deletions(-) diff --git a/.DS_Store b/.DS_Store index 64a7d78d6ac70fb098fbd9d3d693511873ca62ea..64266e951fec58380d4ac05d1aa8d15e08ce5a17 100644 GIT binary patch delta 22 dcmZoMXffEJ#mw~J=42gaUnc2-&DG4EA^=&P2WtQT delta 22 dcmZoMXffEJ#muz#&SV{CUnZ#uo2!{SMF3cn2WkKS diff --git a/js/bullet.js b/js/bullet.js index 526a2ff..00340bf 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -96,20 +96,11 @@ const b = { outOfAmmo() { //triggers after firing when you have NO ammo simulation.makeTextLog(`${b.guns[b.activeGun].name}.ammo: 0`); m.fireCDcycle = m.cycle + 30; //fire cooldown - if (tech.isAmmoFromHealth) { - if (tech.isEnergyHealth) { - tech.healMaxEnergyBonus -= 0.01 - m.setMaxEnergy(); - } else if (m.maxHealth > 0.01) { - tech.extraMaxHealth -= 0.01 //decrease max health - m.setMaxHealth(); - } + if (tech.isAmmoFromHealth && m.maxHealth > 0.01) { + tech.extraMaxHealth -= 0.01 //decrease max health + m.setMaxHealth(); for (let i = 0; i < 4; i++) powerUps.spawn(m.pos.x + 50 * (Math.random() - 0.5), m.pos.y + 50 * (Math.random() - 0.5), "ammo"); } - // if (tech.isAmmoFromHealth && m.maxHealth > 0.01) { - // tech.extraMaxHealth -= 0.01 //decrease max health - // m.setMaxHealth(); - // } }, refundAmmo() { //triggers after firing when you removed ammo for a gun, but didn't need to (like a rail gun misfire) if (tech.isCrouchAmmo && m.crouch) { @@ -342,7 +333,7 @@ const b = { //player damage if (Vector.magnitude(Vector.sub(where, player.position)) < radius) { - const DRAIN = (tech.isExplosionHarm ? 0.5 : 0.25) * (tech.isRadioactiveResistance ? 0.25 : 1) + const DRAIN = (tech.isExplosionHarm ? 0.7 : 0.25) * (tech.isRadioactiveResistance ? 0.25 : 1) // * (tech.isImmuneExplosion ? Math.min(1, Math.max(1 - m.energy * 0.7, 0)) : 1) if (m.immuneCycle < m.cycle) m.energy -= DRAIN if (m.energy < 0) { @@ -392,7 +383,7 @@ const b = { if (dist < radius) { if (tech.isImmuneExplosion) { const mitigate = Math.min(1, Math.max(1 - m.energy * 0.7, 0)) - m.damage(mitigate * radius * (tech.isExplosionHarm ? 0.0004 : 0.0001)); + m.damage(mitigate * radius * (tech.isExplosionHarm ? 0.0003 : 0.0001)); } else { m.damage(radius * (tech.isExplosionHarm ? 0.0004 : 0.0001)); } @@ -1859,7 +1850,7 @@ const b = { friction: 0, frictionAir: 0.025, thrust: (tech.isFastSpores ? 0.001 : 0.0005) * (1 + 0.5 * (Math.random() - 0.5)), - dmg: (tech.isMutualism ? 16.8 : 7) * 3, //bonus damage from tech.isMutualism //3 is extra damage as worm + dmg: (tech.isMutualism ? 16.8 : 7) * 2.5, //bonus damage from tech.isMutualism //2.5 is extra damage as worm lookFrequency: 100 + Math.floor(37 * Math.random()), classType: "bullet", collisionFilter: { diff --git a/js/index.js b/js/index.js index 700f87f..bd737d6 100644 --- a/js/index.js +++ b/js/index.js @@ -18,6 +18,7 @@ const color = { //light block: "rgba(140,140,140,0.85)", blockS: "#222", map: "#444", + bullet: "#000" } // const color = { //dark diff --git a/js/level.js b/js/level.js index bbb9477..6330f48 100644 --- a/js/level.js +++ b/js/level.js @@ -13,7 +13,7 @@ const level = { if (level.levelsCleared === 0) { //this code only runs on the first level // localSettings.levelsClearedLastGame = 10 // simulation.enableConstructMode() //used to build maps in testing mode - // level.difficultyIncrease(10) //30 is near max on hard //60 is near max on why + // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why // simulation.isHorizontalFlipped = true // tech.isFieldFree = true // m.setField("time dilation") @@ -1298,7 +1298,6 @@ const level = { spawn.randomMob(x + 2000 - 800, y + -125, mobSpawnChance); let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob - spawn.secondaryBossChance(x + 2000 - 650, y + -875) } else { powerUps.spawnStartingPowerUps(x + 1650, y + -400); spawn.mapRect(x + 1575, y + -625, 25, 375); //wall on top of wall @@ -1330,7 +1329,6 @@ const level = { spawn.randomMob(x + 800, y + -125, mobSpawnChance); let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob - spawn.secondaryBossChance(x + 650, y + -875) } }, (x = offset.x, y = offset.y) => { //spawn block and fire it @@ -1390,7 +1388,6 @@ const level = { spawn.randomMob(x + 2000 - 800, y + -125, mobSpawnChance); let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob - spawn.secondaryBossChance(x + 650, y + -875) } else { powerUps.spawnStartingPowerUps(x + 1650, y + -400); spawn.mapRect(x + 1575, y + -625, 25, 375); //wall on top of wall @@ -1447,7 +1444,6 @@ const level = { spawn.randomMob(x + 800, y + -125, mobSpawnChance); let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob - spawn.secondaryBossChance(x + 650, y - 875) } }, (x = offset.x, y = offset.y) => { //fire an "ammo clip" of blocks @@ -1518,7 +1514,6 @@ const level = { spawn.randomMob(x + 2000 - 800, y + -125, mobSpawnChance); let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob - spawn.secondaryBossChance(x + 650, y - 875) } else { powerUps.spawnStartingPowerUps(x + 1650, y + -400); spawn.mapRect(x + 1575, y + -625, 25, 375); //wall on top of wall @@ -1586,7 +1581,6 @@ const level = { spawn.randomMob(x + 800, y + -125, mobSpawnChance); let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob - spawn.secondaryBossChance(x + 650, y - 875) } } ] @@ -1884,7 +1878,8 @@ const level = { simulation.draw.setPaths() //update map graphics spawn.randomGroup(x + 300, y + -2200); spawn.randomGroup(x + 1625, y + -2200); - spawn.randomLevelBoss(x + 950, y + -2200); + spawn.randomLevelBoss(x + 700, y + -2300); + spawn.secondaryBossChance(x + 1250, y + -2300) } } ) @@ -1950,7 +1945,8 @@ const level = { spawn.randomMob(x + 225, y + -2275, mobSpawnChance); spawn.randomMob(x + 875, y + -2450, mobSpawnChance); spawn.randomMob(x + 1550, y + -2525, mobSpawnChance); - if (simulation.difficulty > 3) spawn.randomLevelBoss(x + 1075, y + -1500); + spawn.randomLevelBoss(x + 1075, y + -1500); + spawn.secondaryBossChance(x + 1200, y + -1000) simulation.draw.setPaths() //update map graphics } } @@ -2276,7 +2272,7 @@ const level = { // spawn.starter(1900, -500, 200) //big boy // spawn.growBossCulture(1900, -500) // spawn.blinkBoss(1900, -500) - // spawn.snakeBoss(1900, -500) + spawn.snakeSpitBoss(1900, -500) // spawn.growBossCulture(1900, -500) // spawn.sneaker(1900, -500) // spawn.historyBoss(1200, -500) @@ -2285,11 +2281,11 @@ const level = { // spawn.laserTargetingBoss(1700, -120) // spawn.bomberBoss(1400, -500) // spawn.hopBoss(1800, -120) - // spawn.streamBoss(1600, -500) + spawn.streamBoss(1600, -500) // spawn.powerUpBoss(1600, -500) // spawn.cellBossCulture(1600, -500) // spawn.laserTargetingBoss(1600, -500) - spawn.grenadierBoss(1200, -500) + // spawn.grenadierBoss(1200, -500) // spawn.shield(mob[mob.length - 1], 1800, -120, 1); // spawn.nodeGroup(1200, -500, "grenadier") diff --git a/js/player.js b/js/player.js index 92491bb..a0b201e 100644 --- a/js/player.js +++ b/js/player.js @@ -2607,9 +2607,9 @@ const m = { }, { name: "wormhole", - description: "use energy to tunnel through a wormhole
wormholes attract blocks and power ups
9% chance to duplicate spawned power ups", //
bullets may also traverse wormholes + description: "use energy to tunnel through a wormhole
wormholes attract blocks and power ups
8% chance to duplicate spawned power ups", //
bullets may also traverse wormholes effect: function() { - m.duplicateChance = 0.09 + m.duplicateChance = 0.08 powerUps.setDo(); //needed after adjusting duplication chance m.hold = function() { diff --git a/js/powerup.js b/js/powerup.js index e84eca8..22f4d6b 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -397,33 +397,32 @@ const powerUps = { size() { return 45; }, - choiceLog: [], //records all previous choice options - effect() { - function pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { - let options = []; - for (let i = 1; i < who.length; i++) { - if (i !== m.fieldMode && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) options.push(i); - } - //remove repeats from last selection - const totalChoices = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2 - if (powerUps.field.choiceLog.length > totalChoices || powerUps.field.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove - for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection - if (options.length > totalChoices) { - for (let j = 0, len = options.length; j < len; j++) { - if (powerUps.field.choiceLog[powerUps.field.choiceLog.length - 1 - i] === options[j]) { - options.splice(j, 1) //remove previous choice from option pool - break - } + pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { + let options = []; + for (let i = 1; i < who.length; i++) { + if (i !== m.fieldMode && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) options.push(i); + } + //remove repeats from last selection + const totalChoices = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2 + if (powerUps.field.choiceLog.length > totalChoices || powerUps.field.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove + for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection + if (options.length > totalChoices) { + for (let j = 0, len = options.length; j < len; j++) { + if (powerUps.field.choiceLog[powerUps.field.choiceLog.length - 1 - i] === options[j]) { + options.splice(j, 1) //remove previous choice from option pool + break } } } } - if (options.length > 0) { - return options[Math.floor(Math.random() * options.length)] - } } - - let choice1 = pick(m.fieldUpgrades) + if (options.length > 0) { + return options[Math.floor(Math.random() * options.length)] + } + }, + choiceLog: [], //records all previous choice options + effect() { + let choice1 = powerUps.field.pick(m.fieldUpgrades) let choice2 = -1 let choice3 = -1 if (choice1 > -1) { @@ -432,15 +431,15 @@ const powerUps = { text += `

field

` text += `
  ${m.fieldUpgrades[choice1].name}
${m.fieldUpgrades[choice1].description}
` if (!tech.isDeterminism) { - choice2 = pick(m.fieldUpgrades, choice1) + choice2 = powerUps.field.pick(m.fieldUpgrades, choice1) if (choice2 > -1) text += `
  ${m.fieldUpgrades[choice2].name}
${m.fieldUpgrades[choice2].description}
` - choice3 = pick(m.fieldUpgrades, choice1, choice2) + choice3 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2) if (choice3 > -1) text += `
  ${m.fieldUpgrades[choice3].name}
${m.fieldUpgrades[choice3].description}
` } if (tech.isExtraChoice) { - let choice4 = pick(m.fieldUpgrades, choice1, choice2, choice3) + let choice4 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2, choice3) if (choice4 > -1) text += `
  ${m.fieldUpgrades[choice4].name}
${m.fieldUpgrades[choice4].description}
` - let choice5 = pick(m.fieldUpgrades, choice1, choice2, choice3, choice4) + let choice5 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2, choice3, choice4) if (choice5 > -1) text += `
  ${m.fieldUpgrades[choice5].name}
${m.fieldUpgrades[choice5].description}
` powerUps.field.choiceLog.push(choice4) powerUps.field.choiceLog.push(choice5) @@ -540,6 +539,7 @@ const powerUps = { return choose } } + let text = "" if (!tech.isDeterminism) text += `
` text += `

tech

` @@ -566,6 +566,21 @@ const powerUps = { powerUps.tech.choiceLog.push(choice3) // if (powerUps.research.count) text += `
  research ${powerUps.research.count}
` + if (tech.isExtraGunField) { + if (Math.random() > 0.5) { + //bonus gun in tech menu + let choiceGun = powerUps.gun.pick(b.guns) + powerUps.gun.choiceLog.push(choiceGun) + text += `
  ${b.guns[choiceGun].name}
${b.guns[choiceGun].description}
` + } else { + //bonus field in tech menu + let choiceField = powerUps.field.pick(m.fieldUpgrades) + powerUps.field.choiceLog.push(choiceField) + text += `
  ${m.fieldUpgrades[choiceField].name}
${m.fieldUpgrades[choiceField].description}
` + } + } + + if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { tech.junkResearchNumber = Math.floor(5 * Math.random()) text += `
` @@ -598,36 +613,35 @@ const powerUps = { size() { return 35; }, - choiceLog: [], //records all previous choice options - effect() { - function pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { - let options = []; - for (let i = 0; i < who.length; i++) { - if (!who[i].have && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) { - options.push(i); - } + pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { + let options = []; + for (let i = 0; i < who.length; i++) { + if (!who[i].have && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) { + options.push(i); } + } - //remove repeats from last selection - const totalChoices = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2 - if (powerUps.gun.choiceLog.length > totalChoices || powerUps.gun.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove - for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection - if (options.length > totalChoices) { - for (let j = 0, len = options.length; j < len; j++) { - if (powerUps.gun.choiceLog[powerUps.gun.choiceLog.length - 1 - i] === options[j]) { - options.splice(j, 1) //remove previous choice from option pool - break - } + //remove repeats from last selection + const totalChoices = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2 + if (powerUps.gun.choiceLog.length > totalChoices || powerUps.gun.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove + for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection + if (options.length > totalChoices) { + for (let j = 0, len = options.length; j < len; j++) { + if (powerUps.gun.choiceLog[powerUps.gun.choiceLog.length - 1 - i] === options[j]) { + options.splice(j, 1) //remove previous choice from option pool + break } } } } - if (options.length > 0) { - return options[Math.floor(Math.random() * options.length)] - } } - - let choice1 = pick(b.guns) + if (options.length > 0) { + return options[Math.floor(Math.random() * options.length)] + } + }, + choiceLog: [], //records all previous choice options + effect() { + let choice1 = powerUps.gun.pick(b.guns) let choice2 = -1 let choice3 = -1 if (choice1 > -1) { @@ -636,15 +650,15 @@ const powerUps = { text += `

gun

` text += `
  ${b.guns[choice1].name}
${b.guns[choice1].description}
` if (!tech.isDeterminism) { - choice2 = pick(b.guns, choice1) + choice2 = powerUps.gun.pick(b.guns, choice1) if (choice2 > -1) text += `
  ${b.guns[choice2].name}
${b.guns[choice2].description}
` - choice3 = pick(b.guns, choice1, choice2) + choice3 = powerUps.gun.pick(b.guns, choice1, choice2) if (choice3 > -1) text += `
  ${b.guns[choice3].name}
${b.guns[choice3].description}
` } if (tech.isExtraChoice) { - let choice4 = pick(b.guns, choice1, choice2, choice3) + let choice4 = powerUps.gun.pick(b.guns, choice1, choice2, choice3) if (choice4 > -1) text += `
  ${b.guns[choice4].name}
${b.guns[choice4].description}
` - let choice5 = pick(b.guns, choice1, choice2, choice3, choice4) + let choice5 = powerUps.gun.pick(b.guns, choice1, choice2, choice3, choice4) if (choice5 > -1) text += `
  ${b.guns[choice5].name}
${b.guns[choice5].description}
` powerUps.gun.choiceLog.push(choice4) @@ -714,7 +728,7 @@ const powerUps = { powerUps.spawn(x, y, "ammo"); return; } - if (Math.random() < 0.001 * (3 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun up to 3 + if (Math.random() < 0.0007 * (3 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun up to 3 powerUps.spawn(x, y, "gun"); return; } @@ -723,7 +737,7 @@ const powerUps = { powerUps.spawn(x, y, "tech"); return; } - if (Math.random() < 0.003) { + if (Math.random() < 0.0015) { powerUps.spawn(x, y, "field"); return; } diff --git a/js/simulation.js b/js/simulation.js index 4f17b8a..e1c572e 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -680,47 +680,49 @@ const simulation = { }, clearNow: false, clearMap() { - if (tech.isLongitudinal) { - for (i = 0, len = b.guns.length; i < len; i++) { //find which gun - if (b.guns[i].name === "wave beam") { - b.guns[i].waves = []; //empty array of wave bullets - break; + if (m.alive) { + if (tech.isLongitudinal) { + for (i = 0, len = b.guns.length; i < len; i++) { //find which gun + if (b.guns[i].name === "wave beam") { + b.guns[i].waves = []; //empty array of wave bullets + break; + } } } - } - if (tech.isMineAmmoBack) { - let count = 0; - for (i = 0, len = bullet.length; i < len; i++) { //count mines left on map - if (bullet[i].bulletType === "mine") count++ - } - for (i = 0, len = b.guns.length; i < len; i++) { //find which gun is mine - if (b.guns[i].name === "mine") { - if (tech.isCrouchAmmo) count = Math.ceil(count / 2) - b.guns[i].ammo += count - simulation.updateGunHUD(); - break; + if (tech.isMineAmmoBack) { + let count = 0; + for (i = 0, len = bullet.length; i < len; i++) { //count mines left on map + if (bullet[i].bulletType === "mine") count++ + } + for (i = 0, len = b.guns.length; i < len; i++) { //find which gun is mine + if (b.guns[i].name === "mine") { + if (tech.isCrouchAmmo) count = Math.ceil(count / 2) + b.guns[i].ammo += count + simulation.updateGunHUD(); + break; + } } } - } - if (tech.isMutualism && !tech.isEnergyHealth) { - for (let i = 0; i < bullet.length; i++) { - if (bullet[i].isMutualismActive) { - m.health += 0.005 + 0.005 * tech.isSporeWorm - if (m.health > m.maxHealth) m.health = m.maxHealth; - m.displayHealth(); + if (tech.isMutualism && !tech.isEnergyHealth) { + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].isMutualismActive) { + m.health += 0.005 + 0.005 * tech.isSporeWorm + if (m.health > m.maxHealth) m.health = m.maxHealth; + m.displayHealth(); + } } } - } - if (tech.isEndLevelPowerUp) { - for (let i = 0; i < powerUp.length; i++) { - if (powerUp[i].name === "tech") { - tech.giveTech() - } else if (powerUp[i].name === "gun") { - if (!tech.isOneGun) b.giveGuns("random") - } else if (powerUp[i].name === "field") { - if (m.fieldMode === 0) m.setField(Math.ceil(Math.random() * (m.fieldUpgrades.length - 1))) //pick a random field, but not field 0 - } else { - powerUp[i].effect(); + if (tech.isEndLevelPowerUp) { + for (let i = 0; i < powerUp.length; i++) { + if (powerUp[i].name === "tech") { + tech.giveTech() + } else if (powerUp[i].name === "gun") { + if (!tech.isOneGun) b.giveGuns("random") + } else if (powerUp[i].name === "field") { + if (m.fieldMode === 0) m.setField(Math.ceil(Math.random() * (m.fieldUpgrades.length - 1))) //pick a random field, but not field 0 + } else { + powerUp[i].effect(); + } } } } @@ -755,7 +757,7 @@ const simulation = { removeAll(composite); composite = []; // if player was holding something this makes a new copy to hold - if (holdTarget) { + if (holdTarget && m.alive) { len = body.length; body[len] = Matter.Bodies.fromVertices(0, 0, holdTarget.vertices, { friction: holdTarget.friction, diff --git a/js/spawn.js b/js/spawn.js index dba630d..cb45e04 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -1,7 +1,7 @@ //main object for spawning things in a level const spawn = { nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture", "growBossCulture"], - randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss"]) { + randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", "snakeSpitBoss"]) { // 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) }, @@ -316,7 +316,7 @@ const spawn = { } else if (count === 780) { simulation.makeTextLog(`undefined = ${lore.techCount}/${lore.techGoal}`) } else if (count === 1020) { - simulation.makeTextLog(`Composite.clear(engine.composite) //simulation successful`); + simulation.makeTextLog(`Engine.clear(engine) //simulation successful`); } else if (count === 1260) { // tech.isImmortal = false; // m.death() @@ -331,7 +331,10 @@ const spawn = { // build.shareURL(false) setTimeout(function() { simulation.paused = true; - Composite.clear(engine.composite); + // simulation.clearMap(); + // Matter.Composite.clear(composite, keepStatic, [deep = false]) + // Composite.clear(engine.composite); + engine.world.bodies.forEach((body) => { Matter.Composite.remove(engine.world, body) }) Engine.clear(engine); simulation.splashReturn(); }, 6000); @@ -3640,6 +3643,124 @@ const spawn = { this.attraction(); }; }, + snakeSpitBoss(x, y, radius = 50) { //snake boss with a laser head + const nodes = Math.min(8 + Math.ceil(0.5 * simulation.difficulty), 40) + let angle = Math.PI + let mag = 300 + + const color1 = "rgb(245,180,255)" + mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, color1); //"rgb(55,170,170)" + let me = mob[mob.length - 1]; + me.isBoss = true; + me.accelMag = 0.0001 + 0.0002 * Math.sqrt(simulation.accelScale) + me.memory = 250; + me.laserRange = 500; + Matter.Body.setDensity(me, 0.0022 + 0.00022 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger + me.onDeath = function() { + powerUps.spawnBossPowerUp(this.position.x, this.position.y) + for (let i = 0; i < mob.length; i++) { //wake up tail mobs + if (mob[i].isSnakeTail && mob[i].alive) { + mob[i].isSnakeTail = false; + mob[i].do = mob[i].doActive + mob[i].removeConsBB(); + } + } + }; + me.canFire = false; + me.closestVertex1 = 0; + // me.closestVertex2 = 1; + me.cycle = 0 + me.damageReduction = 0.25 + me.do = function() { + // this.armor(); + this.seePlayerByHistory() + this.checkStatus(); + this.attraction(); + this.cycle++ + if (this.seePlayer.recall && ((this.cycle % 15) === 0) && !m.isBodiesAsleep) { + if (this.canFire) { + if (this.cycle > 120) { + this.cycle = 0 + this.canFire = false + // Matter.Body.setAngularVelocity(this, 0.1) + // const forceMag = 0.01 * this.mass; + // const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x); + // this.force.x -= 2 * forceMag * Math.cos(angle); + // this.force.y -= 2 * forceMag * Math.sin(angle); // - 0.0007 * this.mass; //antigravity + } + spawn.seeker(this.vertices[this.closestVertex1].x, this.vertices[this.closestVertex1].y, 6) + Matter.Body.setDensity(mob[mob.length - 1], 0.000001); //normal is 0.001 + const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[this.closestVertex1])), -10) + Matter.Body.setVelocity(mob[mob.length - 1], { + x: this.velocity.x + velocity.x, + y: this.velocity.y + velocity.y + }); + // spawn.seeker(this.vertices[this.closestVertex2].x, this.vertices[this.closestVertex2].y, 6) + // Matter.Body.setDensity(mob[mob.length - 1], 0.000001); //normal is 0.001 + // const velocity2 = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[this.closestVertex2])), -10) + // Matter.Body.setVelocity(mob[mob.length - 1], { + // x: this.velocity.x + velocity2.x, + // y: this.velocity.y + velocity2.y + // }); + } else if (this.cycle > 210) { + this.cycle = 0 + this.canFire = true + + //find closest 2 vertexes + let distance2 = Infinity + for (let i = 0; i < this.vertices.length; i++) { + const d = Vector.magnitudeSquared(Vector.sub(this.vertices[i], player.position)) + if (d < distance2) { + distance2 = d + // this.closestVertex2 = this.closestVertex1 + this.closestVertex1 = i + } + } + // if (this.closestVertex2 === this.closestVertex1) { + // this.closestVertex2++ + // if (this.closestVertex2 === this.vertices.length) this.closestVertex2 = 0 + // } + } + } + }; + //extra space to give head room + angle -= 0.1 + mag -= 10 + for (let i = 0; i < nodes; ++i) { + angle -= 0.15 + i * 0.008 + mag -= 5 + spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 20); + } + this.constrain2AdjacentMobs(nodes, Math.random() * 0.06 + 0.01); + + for (let i = mob.length - 1, len = i - nodes; i > len; i--) { //set alternating colors + if (i % 2) { + mob[i].fill = "#778" + } else { + mob[i].fill = color1 + } + } + //constraint with first 3 mobs in line + consBB[consBB.length] = Constraint.create({ + bodyA: mob[mob.length - nodes], + bodyB: mob[mob.length - 1 - nodes], + stiffness: 0.05 + }); + Composite.add(engine.world, consBB[consBB.length - 1]); + consBB[consBB.length] = Constraint.create({ + bodyA: mob[mob.length - nodes + 1], + bodyB: mob[mob.length - 1 - nodes], + stiffness: 0.05 + }); + Composite.add(engine.world, consBB[consBB.length - 1]); + consBB[consBB.length] = Constraint.create({ + bodyA: mob[mob.length - nodes + 2], + bodyB: mob[mob.length - 1 - nodes], + stiffness: 0.05 + }); + Composite.add(engine.world, consBB[consBB.length - 1]); + // spawn.shield(me, x, y, 1); + }, snakeBoss(x, y, radius = 50) { //snake boss with a laser head const nodes = Math.min(8 + Math.ceil(0.5 * simulation.difficulty), 40) let angle = Math.PI diff --git a/js/tech.js b/js/tech.js index 08b993a..760be54 100644 --- a/js/tech.js +++ b/js/tech.js @@ -193,7 +193,7 @@ return dmg * tech.slowFire * tech.aimDamage }, duplicationChance() { - return (tech.isPowerUpsVanish ? 0.2 : 0) + (tech.isStimulatedEmission ? 0.22 : 0) + tech.cancelCount * 0.048 + tech.duplicateChance + m.duplicateChance + tech.wormDuplicate + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0) + return (tech.isPowerUpsVanish ? 0.17 : 0) + (tech.isStimulatedEmission ? 0.2 : 0) + tech.cancelCount * 0.048 + tech.duplicateChance + m.duplicateChance + tech.wormDuplicate + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0) }, maxDuplicationEvent() { if (tech.is100Duplicate && tech.duplicationChance() > 0.99) { @@ -458,9 +458,9 @@ frequency: 1, frequencyDefault: 1, allowed() { - return !tech.isEnergyNoAmmo + return !tech.isEnergyNoAmmo && !tech.isEnergyHealth }, - requires: "exciton-lattice", + requires: "exciton-lattice, not mass-energy", effect: () => { tech.isAmmoFromHealth = true; }, @@ -773,7 +773,7 @@ }, { name: "ammonium nitrate", - description: "increase explosive damage by 25%
increase explosive radius by 25%", + description: "increase explosive damage by 30%
increase explosive radius by 30%", maxCount: 9, count: 0, frequency: 2, @@ -783,7 +783,7 @@ }, requires: "an explosive damage source, not iridium-192", effect: () => { - tech.explosiveRadius += 0.25; + tech.explosiveRadius += 0.3; }, remove() { tech.explosiveRadius = 1; @@ -809,7 +809,7 @@ }, { name: "acetone peroxide", - description: "increase explosive radius by 80%, but
you take 400% more harm from explosions", + description: "increase explosive radius by 80%, but
you take 300% more harm from explosions", maxCount: 1, count: 0, frequency: 2, @@ -2824,11 +2824,14 @@ requires: "not determinism, at least 3 research", effect() { tech.isBanish = true - for (let i = 0; i < 9; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "research", false); + for (let i = 0; i < 9; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false); }, remove() { - tech.isBanish = false - powerUps.tech.banishLog = [] //reset banish log + if (tech.isBanish) { + tech.isBanish = false + powerUps.tech.banishLog = [] //reset banish log + powerUps.research.changeRerolls(-10) + } } }, { @@ -3036,7 +3039,7 @@ }, { name: "stimulated emission", - description: "22% chance to duplicate spawned power ups
but, after a collision eject 1 tech", + description: "20% chance to duplicate spawned power ups
but, after a collision eject 1 tech", maxCount: 1, count: 0, frequency: 1, @@ -3056,7 +3059,7 @@ }, { name: "metastability", - description: "20% chance to duplicate spawned power ups
duplicates explode with a 3 second half-life ", + description: "17% chance to duplicate spawned power ups
duplicates explode with a 3 second half-life ", maxCount: 1, count: 0, frequency: 1, @@ -3243,24 +3246,6 @@ }, remove() {} }, - { - name: "unified field theory", - description: `in the pause menu, change your field
by clicking on your field's box`, - maxCount: 1, - count: 0, - frequency: 1, - frequencyDefault: 1, - allowed() { - return !tech.isSuperDeterminism - }, - requires: "not superdeterminism", - effect() { - tech.isGunSwitchField = true; - }, - remove() { - tech.isGunSwitchField = false; - } - }, { name: "vector fields", description: "double the frequency of finding field tech
spawn a field", @@ -3339,21 +3324,67 @@ remove() {} }, { - name: "cardinality", - description: "tech, fields, and guns have 5 choices", + name: "unified field theory", + description: `spawn 6 research, and when paused
clicking the field box switches your field`, + // description: `in the pause menu, change your field
by clicking on your field's box`, maxCount: 1, count: 0, - frequency: 2, - frequencyDefault: 2, + frequency: 1, + frequencyDefault: 1, + allowed() { + return !tech.isSuperDeterminism + }, + requires: "not superdeterminism", + effect() { + tech.isGunSwitchField = true; + for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false); + }, + remove() { + if (tech.isGunSwitchField) { + tech.isGunSwitchField = false; + powerUps.research.changeRerolls(-6) + } + } + }, + { + name: "cross disciplinary", + description: "tech have an extra field or gun choice", //
+7 JUNK to the potential tech pool //
spawn 2 research + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return !tech.isDeterminism + }, + requires: "not determinism", + effect: () => { + tech.isExtraGunField = true; + // for (let i = 0; i < 2; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false); + + }, + remove() { + tech.isExtraGunField = false; + // if (this.count > 0) powerUps.research.changeRerolls(-2) + } + }, + { + name: "emergence", + description: "tech, fields, and guns have 5 choices
+5 JUNK to the potential tech pool", + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, allowed() { return !tech.isDeterminism }, requires: "not determinism", effect: () => { tech.isExtraChoice = true; + tech.addJunkTechToPool(5) }, remove() { tech.isExtraChoice = false; + if (this.count > 0) tech.removeJunkTechFromPool(5) } }, { @@ -3367,7 +3398,7 @@ allowed() { return !tech.isExtraChoice && !tech.isCancelDuplication && !tech.isCancelRerolls }, - requires: "not cardinality, not futures or commodities exchanges", + requires: "not emergence, not futures or commodities exchanges", effect: () => { tech.isDeterminism = true; //if you change the number spawned also change it in Born rule @@ -4560,7 +4591,7 @@ }, { name: "nematodes", - description: "spores develop into 1/2 as many worms
worms do 200% more damage", + description: "spores develop into 1/2 as many worms
worms do 250% more damage", isGunTech: true, maxCount: 1, count: 0, @@ -7365,7 +7396,7 @@ }, { name: "re-arm", - description: "eject all your guns", + description: "remove all your guns,
and spawn new ones", maxCount: 9, count: 0, frequency: 0, @@ -7405,7 +7436,7 @@ }, requires: "at least 4 research", effect() { - for (let i = 0; i < powerUps.research.count; i++) powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "research"); + for (let i = 0; i < powerUps.research.count; i++) powerUps.directSpawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "research"); powerUps.research.count = 0 }, remove() {} @@ -7793,5 +7824,6 @@ isBlockRestitution: null, isZeno: null, isFieldFree: null, - wormSurviveDmg: null + wormSurviveDmg: null, + isExtraGunField: null } \ No newline at end of file diff --git a/todo.txt b/todo.txt index 536361f..9317de3 100644 --- a/todo.txt +++ b/todo.txt @@ -1,49 +1,26 @@ ******************************************************** NEXT PATCH ******************************************************** -missile-bot tech now removes your missile gun, but missile bot fires much faster - missile-bot now benefits from all missile tech +new boss snakeSpitBoss - it's just snake boss but it shoots little pink seekers -rail gun has a bit less ammo and fires a bit faster - in between how it is was in the last two patches -rail gun gets less energy from half-wave rectifier +tech: cross disciplinary - get an extra gun or field option in tech menu + now that you can scroll the selection menu can be longer + +unified field theory - now gives 6 research, in addition to letting you switch fields when paused +cardinality renamed emergence - and gives some JUNK + +bug fix where game crashes if you beat the boss ******************************************************** TODO ******************************************************** -dark mode - build color pallets in a photo editor by redrawing in game screenshots - what about just starting with setting the background to be a dark grey? - const color = { - map: - blocks: - background: - shadows: (0,0,0,0.1)? - bullets: - mob: - heal powerUps: - tech powerUps: - field powerUps: - gun powerUps: - damage circle: - harm circle: - } - -re-word the "reduce difficulty" text, so it's more clear what you get - -tech: Standing Wave: Shockwave. Use FIELD button to shrink your shield and charge up, release to unleash a Shockwave. - -make an area that prevents mob vision, like a bush you can hide in - a static block with non collide on most things? +drones can combine with other drones to get bigger? +drones that grab powers ups can grab more then one and get even bigger each time it would be helpful if there was a mechanism to recover mobs that fly off the map add a ceiling system and a left/right walls system similar to the floor checks but only for mobs make non moving bosses not move after getting hit shooter, shielding, -buff missiles? - do more with the missile bot - maybe they can release grenades after they explode, like CPT grenades? - make the crouch rapid fire a tech, and make the missiles fire faster, and use less ammo? -buff railgun +buff rail gun buff mines make the player get a buff after using wormhole @@ -52,6 +29,7 @@ using wormhole makes you immune to harm and drains energy until you run out disable incoming energy, by saving current energy and just setting energy in the next cycle to be lower then the saved value pink seeker boss is cool as heck, make an alt version of it +snake tail is cool, make an alt version of it block shattering get code from planetesimals @@ -62,6 +40,8 @@ pause should at least show the last in game console message in testing mode console log the body you click on +tech: Standing Wave: Shockwave. Use FIELD button to shrink your shield and charge up, release to unleash a Shockwave. + tech: quantized shields - harmonic standing wave field can only lose 33 energy per hit draw 1,2,3 levels of the field based on energy? the blocked value only scales up to 2x or 4x (33 energy) blocked @@ -80,9 +60,7 @@ tech plasma : plasma length increases then decreases as you hold down the field extra energy is drained when field is longer energy conservation 6% damage recovered as energy - there is space for a negative effect in the text - -Weak Anthropic Principle: you get a second chance at life, but .... + there is space for a negative effect in the text... tech: use the ability for power ups to have custom code (note: this code is half way done, it just needs to be completed) @@ -90,18 +68,6 @@ tech: use the ability for power ups to have custom code attracted to other power ups explode if they touch? -consider executables: - press F to do things - ideas: - -nail-gun, or .... - 1s after being fired your bullets turn: - towards the nearest mob - in your mouse direction - back towards the player - current location or location when fired? - explode when turning back - apply the new gun.do functions to other guns rail gun crouching missile?