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
This commit is contained in:
landgreen
2021-08-08 06:05:24 -07:00
parent c3b96f749e
commit 387d30eff5
10 changed files with 333 additions and 210 deletions

View File

@@ -96,20 +96,11 @@ const b = {
outOfAmmo() { //triggers after firing when you have NO ammo
simulation.makeTextLog(`${b.guns[b.activeGun].name}.<span class='color-gun'>ammo</span><span class='color-symbol'>:</span> 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: {

View File

@@ -18,6 +18,7 @@ const color = { //light
block: "rgba(140,140,140,0.85)",
blockS: "#222",
map: "#444",
bullet: "#000"
}
// const color = { //dark

View File

@@ -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")

View File

@@ -2607,9 +2607,9 @@ const m = {
},
{
name: "wormhole",
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract <strong class='color-block'>blocks</strong> and power ups<br><strong>9%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract <strong class='color-block'>blocks</strong> and power ups<br><strong>8%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
effect: function() {
m.duplicateChance = 0.09
m.duplicateChance = 0.08
powerUps.setDo(); //needed after adjusting duplication chance
m.hold = function() {

View File

@@ -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 += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>field</h3>`
text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice1})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice1].name}</div> ${m.fieldUpgrades[choice1].description}</div>`
if (!tech.isDeterminism) {
choice2 = pick(m.fieldUpgrades, choice1)
choice2 = powerUps.field.pick(m.fieldUpgrades, choice1)
if (choice2 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice2})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice2].name}</div> ${m.fieldUpgrades[choice2].description}</div>`
choice3 = pick(m.fieldUpgrades, choice1, choice2)
choice3 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2)
if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice3})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice3].name}</div> ${m.fieldUpgrades[choice3].description}</div>`
}
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 += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice4})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice4].name}</div> ${m.fieldUpgrades[choice4].description}</div>`
let choice5 = pick(m.fieldUpgrades, choice1, choice2, choice3, choice4)
let choice5 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2, choice3, choice4)
if (choice5 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice5})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice5].name}</div> ${m.fieldUpgrades[choice5].description}</div>`
powerUps.field.choiceLog.push(choice4)
powerUps.field.choiceLog.push(choice5)
@@ -540,6 +539,7 @@ const powerUps = {
return choose
}
}
let text = ""
if (!tech.isDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft("tech",true)'>✕</div>`
text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>tech</h3>`
@@ -566,6 +566,21 @@ const powerUps = {
powerUps.tech.choiceLog.push(choice3)
// if (powerUps.research.count) text += `<div class="choose-grid-module" onclick="powerUps.research.use('tech')"><div class="grid-title"><div class="circle-grid research"></div> &nbsp; research <span class="research-select">${powerUps.research.count}</span></div></div>`
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 += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choiceGun})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choiceGun].name}</div> ${b.guns[choiceGun].description}</div>`
} else {
//bonus field in tech menu
let choiceField = powerUps.field.pick(m.fieldUpgrades)
powerUps.field.choiceLog.push(choiceField)
text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choiceField})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choiceField].name}</div> ${m.fieldUpgrades[choiceField].description}</div>`
}
}
if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
tech.junkResearchNumber = Math.floor(5 * Math.random())
text += `<div class="choose-grid-module" onclick="powerUps.research.use('tech')"><div class="grid-title"> <span style="position:relative;">`
@@ -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 += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>gun</h3>`
text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice1})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice1].name}</div> ${b.guns[choice1].description}</div>`
if (!tech.isDeterminism) {
choice2 = pick(b.guns, choice1)
choice2 = powerUps.gun.pick(b.guns, choice1)
if (choice2 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice2})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice2].name}</div> ${b.guns[choice2].description}</div>`
choice3 = pick(b.guns, choice1, choice2)
choice3 = powerUps.gun.pick(b.guns, choice1, choice2)
if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice3})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice3].name}</div> ${b.guns[choice3].description}</div>`
}
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 += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice4})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice4].name}</div> ${b.guns[choice4].description}</div>`
let choice5 = pick(b.guns, choice1, choice2, choice3, choice4)
let choice5 = powerUps.gun.pick(b.guns, choice1, choice2, choice3, choice4)
if (choice5 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice5})">
<div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice5].name}</div> ${b.guns[choice5].description}</div>`
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;
}

View File

@@ -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,

View File

@@ -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(`<span class="lore-text">undefined</span> <span class='color-symbol'>=</span> ${lore.techCount}/${lore.techGoal}`)
} else if (count === 1020) {
simulation.makeTextLog(`Composite.clear(engine.composite) <em>//simulation successful</em>`);
simulation.makeTextLog(`Engine.clear(engine) <em>//simulation successful</em>`);
} 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

View File

@@ -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 <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>25%</strong><br>increase <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>25%</strong>",
description: "increase <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>30%</strong><br>increase <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>30%</strong>",
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 <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>80%</strong>, but<br>you take <strong>400%</strong> more <strong class='color-harm'>harm</strong> from <strong class='color-e'>explosions</strong>",
description: "increase <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>80%</strong>, but<br>you take <strong>300%</strong> more <strong class='color-harm'>harm</strong> from <strong class='color-e'>explosions</strong>",
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: "<strong>22%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>but, after a <strong>collision</strong> eject <strong>1</strong> <strong class='color-m'>tech</strong>",
description: "<strong>20%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>but, after a <strong>collision</strong> eject <strong>1</strong> <strong class='color-m'>tech</strong>",
maxCount: 1,
count: 0,
frequency: 1,
@@ -3056,7 +3059,7 @@
},
{
name: "metastability",
description: "<strong>20%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong class='color-dup'>duplicates</strong> <strong class='color-e'>explode</strong> with a <strong>3</strong> second <strong>half-life</strong> ",
description: "<strong>17%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong class='color-dup'>duplicates</strong> <strong class='color-e'>explode</strong> with a <strong>3</strong> second <strong>half-life</strong> ",
maxCount: 1,
count: 0,
frequency: 1,
@@ -3243,24 +3246,6 @@
},
remove() {}
},
{
name: "unified field theory",
description: `in the <strong>pause</strong> menu, change your <strong class='color-f'>field</strong><br>by <strong>clicking</strong> on your <strong class='color-f'>field's</strong> 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: "</strong>double</strong> the <strong class='flicker'>frequency</strong> of finding <strong class='color-f'>field</strong> <strong class='color-m'>tech</strong><br>spawn a <strong class='color-f'>field</strong>",
@@ -3339,21 +3324,67 @@
remove() {}
},
{
name: "cardinality",
description: "<strong class='color-m'>tech</strong>, <strong class='color-f'>fields</strong>, and <strong class='color-g'>guns</strong> have <strong>5</strong> <strong>choices</strong>",
name: "unified field theory",
description: `spawn <strong>6</strong> <strong class='color-r'>research</strong>, and when <strong>paused</strong><br><strong>clicking</strong> the <strong class='color-f'>field</strong> box switches your <strong class='color-f'>field</strong>`,
// description: `in the <strong>pause</strong> menu, change your <strong class='color-f'>field</strong><br>by <strong>clicking</strong> on your <strong class='color-f'>field's</strong> 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: "<strong class='color-m'>tech</strong> have an extra <strong class='color-f'>field</strong> or <strong class='color-g'>gun</strong> <strong>choice</strong>", //<br><strong>+7</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool //<br>spawn <strong>2</strong> <strong class='color-r'>research</strong>
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: "<strong class='color-m'>tech</strong>, <strong class='color-f'>fields</strong>, and <strong class='color-g'>guns</strong> have <strong>5</strong> <strong>choices</strong><br><strong>+5</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> 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: "<strong class='color-p' style='letter-spacing: 2px;'>spores</strong> develop into <strong>1/2</strong> as many <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong><br><strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> do <strong>200%</strong> more <strong class='color-d'>damage</strong>",
description: "<strong class='color-p' style='letter-spacing: 2px;'>spores</strong> develop into <strong>1/2</strong> as many <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong><br><strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> do <strong>250%</strong> more <strong class='color-d'>damage</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -7365,7 +7396,7 @@
},
{
name: "re-arm",
description: "<strong>eject</strong> all your <strong class='color-g'>guns</strong>",
description: "remove all your <strong class='color-g'>guns</strong>,<br>and <strong>spawn</strong> 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
}