diff --git a/.DS_Store b/.DS_Store index 30e8239..de3f348 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/js/index.js b/js/index.js index 4d3ca41..fbab545 100644 --- a/js/index.js +++ b/js/index.js @@ -1289,6 +1289,12 @@ if (localSettings.isAllowed && !localSettings.isEmpty) { } document.getElementById("banned").value = localSettings.banList + if (!localSettings.isLoreDoesNotNeedReset) { + localSettings.isLoreDoesNotNeedReset = true + localSettings.loreCount = 0; //this sets what conversation is heard + if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage + } + } else { console.log('setting default localSettings') const isAllowed = localSettings.isAllowed //don't overwrite isAllowed value @@ -1304,8 +1310,9 @@ if (localSettings.isAllowed && !localSettings.isEmpty) { isTrainingNotAttempted: true, levelsClearedLastGame: 0, loreCount: 0, + isLoreDoesNotNeedReset: false, isHuman: false, - key: undefined + key: undefined, }; input.setDefault() if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage diff --git a/js/level.js b/js/level.js index 407c39a..0f3ae2d 100644 --- a/js/level.js +++ b/js/level.js @@ -52,10 +52,11 @@ const level = { //lore testing // for (let i = 0; i < 3; i++) tech.giveTech("undefined") - // lore.techCount = 3 + // lore.techCount = 2 // simulation.isCheating = false //true; - localSettings.loreCount = 6; //this sets what conversation is heard - if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage + // level.levelsCleared = 10 + // localSettings.loreCount = 7; //this sets what conversation is heard + // if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage // level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation // level.null() // localSettings.isHuman = true @@ -3288,7 +3289,7 @@ const level = { //power ups don't spawn in experiment mode, so they don't get removed at the start of experiment mode function cycle() { if (simulation.cycle > 10) { - if (localSettings.loreCount === 6) { + if (localSettings.loreCount === 7) { powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2170, "field", false); } else { powerUps.spawnStartingPowerUps(2095 + 15 * (Math.random() - 0.5), -2070 - 125); diff --git a/js/lore.js b/js/lore.js index 1cde0f3..e57bcf2 100644 --- a/js/lore.js +++ b/js/lore.js @@ -3,11 +3,11 @@ const lore = { techGoal: 7, setTechGoal() { if (simulation.difficultyMode === 1) { - this.techGoal = 14 + this.techGoal = 8 } else if (simulation.difficultyMode === 2) { - this.techGoal = 7 + this.techGoal = 5 } else if (simulation.difficultyMode === 4) { - this.techGoal = 3 + this.techGoal = 2 } else if (simulation.difficultyMode === 6) { this.techGoal = 1 } @@ -641,6 +641,7 @@ const lore = { lore.anand.text(`So why don't you try to get the final level of the simulation without killing any mobs?`) localSettings.loreCount++ if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage + console.log(localSettings.loreCount) }, () => { lore.miriam.text(`Ok check back in and let us know how it goes.`) }, () => { lore.anand.text("bye") }, @@ -663,14 +664,14 @@ const lore = { () => { if (mobs.mobDeaths < level.levelsCleared) { lore.miriam.text(`So I think it worked.`) - } else { + } else if (!simulation.isCheating) { lore.miriam.text(`Looks like you got back here, but you you killed ${mobs.mobDeaths} mobs`) } }, () => { if (mobs.mobDeaths < level.levelsCleared) { lore.anand.text(`Yeah, at the end it wasn't attacking you.`) - } else { + } else if (!simulation.isCheating) { lore.miriam.text(`Try again to get ot the final boss without killing any mobs.`) } }, diff --git a/js/tech.js b/js/tech.js index bf196e3..6b6179a 100644 --- a/js/tech.js +++ b/js/tech.js @@ -8084,26 +8084,201 @@ const tech = { //************************************************** JUNK //************************************************** tech //************************************************** - // { - // name: "junk", - // description: "", - // maxCount: 9, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { - // return true - // }, - // requires: "", - // effect() { + { + name: "junk", + description: "", + maxCount: 9, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { + return true + }, + requires: "", + effect() { - // }, - // remove() {} - // }, + }, + remove() {} + }, + { + name: "swap meet", + description: "normal tech become JUNK
and JUNK become normal tech", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + isNonRefundable: true, + allowed() { + return true + }, + requires: "", + effect() { + for (let i = 0, len = tech.tech.length; i < len; i++) { + tech.tech[i].isJunk = !tech.tech[i].isJunk + if (tech.tech[i].isJunk) {} else {} + + if (tech.tech[i].frequency > 0) { + tech.tech[i].frequency = 0 + } else { + tech.tech[i].frequency = 2 + } + } + }, + remove() {} + }, + { + name: "boost", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + isNonRefundable: true, + allowed() { + return !build.isExperimentSelection + }, + requires: "NOT EXPERIMENT MODE", + effect() { + powerUps.spawnDelay("boost", this.spawnCount) + }, + remove() {}, + id: 0, + text: "", + delay: 100, + spawnCount: 0, + descriptionFunction() { + let count = 9999 * Math.random() + const loop = () => { + if ((simulation.isChoosing) && m.alive && !build.isExperimentSelection) { //&& (!simulation.isChoosing || this.count === 0) //simulation.paused || + count += 4.5 + const waves = 2 * Math.sin(count * 0.0133) + Math.sin(count * 0.013) + 0.5 * Math.sin(count * 0.031) + 0.33 * Math.sin(count * 0.03) + this.spawnCount = Math.floor(100 * Math.abs(waves)) + this.text = `spawn ${this.spawnCount.toLocaleString(undefined, {minimumIntegerDigits:3})} ${powerUps.orb.boost(1)}
that give +${(powerUps.boost.damage*100).toFixed(0)}% damage for ${(powerUps.boost.duration/60).toFixed(0)} seconds` + if (document.getElementById(`boost-JUNK-id${this.id}`)) document.getElementById(`boost-JUNK-id${this.id}`).innerHTML = this.text + setTimeout(() => { loop() }, this.delay); + } + } + setTimeout(() => { loop() }, this.delay); + this.id++ + return `${this.text}` + }, + }, + { + name: "return", + description: "return to the introduction level
reduce combat difficulty by 2 levels", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + isNonRefundable: true, + allowed: () => true, + requires: "", + effect() { + level.difficultyDecrease(simulation.difficultyMode * 2) + level.onLevel = 0 + simulation.clearNow = true //end current level + }, + remove() {} + }, + { + name: "panpsychism", + description: "awaken all blocks
blocks have a chance to spawn power ups", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + isNonRefundable: true, + allowed: () => true, + requires: "", + effect() { + setInterval(() => { + for (let i = body.length - 1; i > -1; i--) { + if (!body[i].isNotHoldable) { + Matter.Composite.remove(engine.world, body[i]); + spawn.blockMob(body[i].position.x, body[i].position.y, body[i], 0); + if (!body[i].isAboutToBeRemoved) mob[mob.length - 1].isDropPowerUp = true + body.splice(i, 1); + } + } + }, 6000); + }, + remove() {} + }, + { + name: "meteor shower", + description: "take a shower, but meteors instead of water", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + isNonRefundable: true, + allowed: () => true, + requires: "", + effect() { + setInterval(() => { + + fireBlock = function(xPos, yPos) { + const index = body.length + spawn.bodyRect(xPos, yPos, 20 + 50 * Math.random(), 20 + 50 * Math.random()); + const bodyBullet = body[index] + Matter.Body.setVelocity(bodyBullet, { x: 5 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }); + bodyBullet.isAboutToBeRemoved = true + bodyBullet.collisionFilter.category = cat.body; + bodyBullet.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + bodyBullet.classType = "body"; + Composite.add(engine.world, bodyBullet); //add to world + setTimeout(() => { //remove block + for (let i = 0; i < body.length; i++) { + if (body[i] === bodyBullet) { + Matter.Composite.remove(engine.world, body[i]); + body.splice(i, 1); + } + } + }, 4000 + Math.floor(9000 * Math.random())); + } + fireBlock(player.position.x + 600 * (Math.random() - 0.5), player.position.y - 500 - 500 * Math.random()); + // for (let i = 0, len = Math.random(); i < len; i++) { + // } + + }, 1000); + }, + remove() {} + }, + { + name: "closed timelike curve", + description: "spawn 5 field power ups, but every 12 seconds
teleport a second into your future or past", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + isNonRefundable: true, + allowed: () => true, + requires: "", + effect() { + for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "field"); + + function loop() { + if (!simulation.paused && m.alive) { + if (!(simulation.cycle % 720)) { + requestAnimationFrame(() => { + if ((simulation.cycle % 1440) > 720) { //kinda alternate between each option + m.rewind(60) + m.energy += 0.4 //to make up for lost energy + } else { + simulation.timePlayerSkip(60) + } + }); //wrapping in animation frame prevents errors, probably + } + } + requestAnimationFrame(loop); + } + requestAnimationFrame(loop); + }, + remove() {} + }, // { - // name: "swap meet", - // description: "normal tech become JUNK
and JUNK become normal tech", + // name: "translate", + // description: "translate n-gon into a random language", // maxCount: 1, // count: 0, // frequency: 0, @@ -8114,1972 +8289,1797 @@ const tech = { // }, // requires: "", // effect() { - // for (let i = 0, len = tech.tech.length; i < len; i++) { - // tech.tech[i].isJunk = !tech.tech[i].isJunk - // if (tech.tech[i].isJunk) {} else {} + // // generate a container + // const gtElem = document.createElement('div') + // gtElem.id = "gtElem" + // gtElem.style.visibility = 'hidden' // make it invisible + // document.body.append(gtElem) - // if (tech.tech[i].frequency > 0) { - // tech.tech[i].frequency = 0 - // } else { - // tech.tech[i].frequency = 2 - // } - // } - // }, - // remove() {} - // }, - // { - // name: "boost", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // isNonRefundable: true, - // allowed() { - // return !build.isExperimentSelection - // }, - // requires: "NOT EXPERIMENT MODE", - // effect() { - // powerUps.spawnDelay("boost", this.spawnCount) - // }, - // remove() {}, - // id: 0, - // text: "", - // delay: 100, - // spawnCount: 0, - // descriptionFunction() { - // let count = 9999 * Math.random() - // const loop = () => { - // if ((simulation.isChoosing) && m.alive && !build.isExperimentSelection) { //&& (!simulation.isChoosing || this.count === 0) //simulation.paused || - // count += 4.5 - // const waves = 2 * Math.sin(count * 0.0133) + Math.sin(count * 0.013) + 0.5 * Math.sin(count * 0.031) + 0.33 * Math.sin(count * 0.03) - // this.spawnCount = Math.floor(100 * Math.abs(waves)) - // this.text = `spawn ${this.spawnCount.toLocaleString(undefined, {minimumIntegerDigits:3})} ${powerUps.orb.boost(1)}
that give +${(powerUps.boost.damage*100).toFixed(0)}% damage for ${(powerUps.boost.duration/60).toFixed(0)} seconds` - // if (document.getElementById(`boost-JUNK-id${this.id}`)) document.getElementById(`boost-JUNK-id${this.id}`).innerHTML = this.text - // setTimeout(() => { loop() }, this.delay); - // } - // } - // setTimeout(() => { loop() }, this.delay); - // this.id++ - // return `${this.text}` - // }, - // }, - // { - // name: "return", - // description: "return to the introduction level
reduce combat difficulty by 2 levels", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // isNonRefundable: true, - // allowed: () => true, - // requires: "", - // effect() { - // level.difficultyDecrease(simulation.difficultyMode * 2) - // level.onLevel = 0 - // simulation.clearNow = true //end current level - // }, - // remove() {} - // }, - // { - // name: "panpsychism", - // description: "awaken all blocks
blocks have a chance to spawn power ups", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // isNonRefundable: true, - // allowed: () => true, - // requires: "", - // effect() { - // setInterval(() => { - // for (let i = body.length - 1; i > -1; i--) { - // if (!body[i].isNotHoldable) { - // Matter.Composite.remove(engine.world, body[i]); - // spawn.blockMob(body[i].position.x, body[i].position.y, body[i], 0); - // if (!body[i].isAboutToBeRemoved) mob[mob.length - 1].isDropPowerUp = true - // body.splice(i, 1); - // } - // } - // }, 6000); - // }, - // remove() {} - // }, - // { - // name: "meteor shower", - // description: "take a shower, but meteors instead of water", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // isNonRefundable: true, - // allowed: () => true, - // requires: "", - // effect() { - // setInterval(() => { - - // fireBlock = function(xPos, yPos) { - // const index = body.length - // spawn.bodyRect(xPos, yPos, 20 + 50 * Math.random(), 20 + 50 * Math.random()); - // const bodyBullet = body[index] - // Matter.Body.setVelocity(bodyBullet, { x: 5 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }); - // bodyBullet.isAboutToBeRemoved = true - // bodyBullet.collisionFilter.category = cat.body; - // bodyBullet.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet - // bodyBullet.classType = "body"; - // Composite.add(engine.world, bodyBullet); //add to world - // setTimeout(() => { //remove block - // for (let i = 0; i < body.length; i++) { - // if (body[i] === bodyBullet) { - // Matter.Composite.remove(engine.world, body[i]); - // body.splice(i, 1); - // } - // } - // }, 4000 + Math.floor(9000 * Math.random())); - // } - // fireBlock(player.position.x + 600 * (Math.random() - 0.5), player.position.y - 500 - 500 * Math.random()); - // // for (let i = 0, len = Math.random(); i < len; i++) { - // // } - - // }, 1000); - // }, - // remove() {} - // }, - // { - // name: "closed timelike curve", - // description: "spawn 5 field power ups, but every 12 seconds
teleport a second into your future or past", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // isNonRefundable: true, - // allowed: () => true, - // requires: "", - // effect() { - // for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "field"); - - // function loop() { - // if (!simulation.paused && m.alive) { - // if (!(simulation.cycle % 720)) { - // requestAnimationFrame(() => { - // if ((simulation.cycle % 1440) > 720) { //kinda alternate between each option - // m.rewind(60) - // m.energy += 0.4 //to make up for lost energy - // } else { - // simulation.timePlayerSkip(60) - // } - // }); //wrapping in animation frame prevents errors, probably - // } - // } - // requestAnimationFrame(loop); - // } - // requestAnimationFrame(loop); - // }, - // remove() {} - // }, - // // { - // // name: "translate", - // // description: "translate n-gon into a random language", - // // maxCount: 1, - // // count: 0, - // // frequency: 0, - // // isJunk: true, - // // isNonRefundable: true, - // // allowed() { - // // return true - // // }, - // // requires: "", - // // effect() { - // // // generate a container - // // const gtElem = document.createElement('div') - // // gtElem.id = "gtElem" - // // gtElem.style.visibility = 'hidden' // make it invisible - // // document.body.append(gtElem) - - // // // generate a script to run after creation - // // function initGT() { - // // // create a new translate element - // // new google.translate.TranslateElement({ pageLanguage: 'en', layout: google.translate.TranslateElement.InlineLayout.HORIZONTAL }, 'gtElem') - // // // ok now since it's loaded perform a funny hack to make it work - // // const langSelect = document.getElementsByClassName("goog-te-combo")[0] - // // // select a random language. It takes a second for all langauges to load, so wait a second. - // // setTimeout(() => { - // // langSelect.selectedIndex = Math.round(langSelect.options.length * Math.random()) - // // // simulate a click - // // langSelect.dispatchEvent(new Event('change')) - // // // now make it go away - // // const bar = document.getElementById(':1.container') - // // bar.style.display = 'none' - // // bar.style.visibility = 'hidden' - // // }, 1000) - - // // } - - // // // add the google translate script - // // const translateScript = document.createElement('script') - // // translateScript.src = '//translate.google.com/translate_a/element.js?cb=initGT' - // // document.body.append(translateScript) - // // }, - // // remove() {} - // // }, - // { - // name: "discount", - // description: "get 3 random JUNK tech for the price of 1!", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // isNonRefundable: true, - // allowed: () => true, - // requires: "", - // effect() { - // tech.giveRandomJUNK() - // tech.giveRandomJUNK() - // tech.giveRandomJUNK() - // }, - // remove() {} - // }, - // // { - // // name: "hi", - // // description: `spawn to seed 616 `, - // // maxCount: 1, - // // count: 0, - // // frequency: 0, - // // isNonRefundable: true, - // // isJunk: true, - // // allowed() { - // // return true - // // }, - // // requires: "", - // // effect() { - // // document.getElementById("seed").placeholder = Math.initialSeed = String(616) - // // Math.seed = Math.abs(Math.hash(Math.initialSeed)) //update randomizer seed in case the player changed it - // // }, - // // remove() {} - // // }, - // { - // name: "Higgs phase transition", - // description: "instantly spawn 5 tech, but add a chance to
remove everything with a 5 minute half-life", - // maxCount: 1, - // count: 0, - // frequency: 0, - // frequencyDefault: 0, - // isJunk: true, - // isNonRefundable: true, - // allowed: () => true, - // requires: "", - // effect() { - // powerUps.spawn(m.pos.x, m.pos.y, "tech"); - // powerUps.spawn(m.pos.x + 30, m.pos.y, "tech"); - // powerUps.spawn(m.pos.x + 60, m.pos.y, "tech"); - // powerUps.spawn(m.pos.x, m.pos.y - 30, "tech"); - // powerUps.spawn(m.pos.x + 30, m.pos.y - 60, "tech"); - - // function loop() { - // // (1-X)^cycles = chance to be removed //Math.random() < 0.000019 10 min - // if (!simulation.paused && m.alive) { - // if (Math.random() < 0.000038) { - // // m.death(); - // simulation.clearMap(); - // simulation.draw.setPaths(); - // return - // } - // } - // requestAnimationFrame(loop); - // } - // requestAnimationFrame(loop); - // }, - // remove() {} - // }, - // { - // name: "harvest", - // description: "convert all the mobs on this level into ammo", - // maxCount: 1, - // count: 0, - // frequency: 0, - // frequencyDefault: 0, - // isJunk: true, - // isNonRefundable: true, - // allowed: () => true, - // requires: "", - // effect() { - // for (let i = 0, len = mob.length; i < len; i++) { - // if (mob[i].isDropPowerUp) { - // powerUps.directSpawn(mob[i].position.x, mob[i].position.y, "ammo"); - // mob[i].death(); - // } - // } - // // for (let i = powerUp.length - 1; i > -1; i--) { - // // if (powerUp[i].name !== "ammo") { - // // Matter.Composite.remove(engine.world, powerUp[i]); - // // powerUp.splice(i, 1); - // // } - // // } - // }, - // remove() {} - // }, - // { - // name: " ", - // description: "", - // maxCount: 1, - // count: 0, - // frequency: 0, - // frequencyDefault: 0, - // isJunk: true, - // allowed: () => true, - // requires: "", - // effect() { - - // }, - // remove() { - - // } - // }, - // { - // name: "brainstorm", - // description: "the tech choice menu randomizes
every 0.5 seconds for 10 seconds", - // maxCount: 1, - // count: 0, - // frequency: 0, - // frequencyDefault: 0, - // isJunk: true, - // allowed: () => true, - // requires: "", - // effect() { - // tech.isBrainstorm = true - // tech.isBrainstormActive = false - // tech.brainStormDelay = 30 - // }, - // remove() { - // tech.isBrainstorm = false - // tech.isBrainstormActive = false - // } - // }, - // { - // name: "catabolysis", - // description: `set your maximum health to 1
double your current ammo 10 times`, - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return !tech.isFallingDamage && !tech.isOverHeal && !tech.isEnergyHealth }, - // requires: "not quenching, tungsten carbide, mass-energy", - // effect() { - // m.baseHealth = 0.01 - // m.setMaxHealth(); - // for (let i = 0; i < b.guns.length; i++) b.guns[i].ammo = b.guns[i].ammo * Math.pow(2, 10) - // simulation.updateGunHUD(); - // }, - // remove() {} - // }, - // { - // name: "palantír", - // description: `see far away lands`, - // maxCount: 1, - // count: 0, - // frequency: 0, - // // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // m.look = () => { - // //always on mouse look - // m.angle = Math.atan2( - // simulation.mouseInGame.y - m.pos.y, - // simulation.mouseInGame.x - m.pos.x - // ); - // //smoothed mouse look translations - // const scale = 2; - // m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale; - // m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale; - // m.transX += (m.transSmoothX - m.transX) * m.lookSmoothing; - // m.transY += (m.transSmoothY - m.transY) * m.lookSmoothing; - // } - // }, - // remove() { - // if (this.count) m.look = m.lookDefault - // } - // }, - // { - // name: "motion sickness", - // description: `disable camera smoothing`, - // maxCount: 1, - // count: 0, - // frequency: 0, - // // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // m.look = () => { - // //always on mouse look - // m.angle = Math.atan2( - // simulation.mouseInGame.y - m.pos.y, - // simulation.mouseInGame.x - m.pos.x - // ); - // //smoothed mouse look translations - // const scale = 1.2; - // m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale; - // m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale; - // m.transX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale; - // m.transY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale; - // // m.transX += (m.transSmoothX - m.transX) * m.lookSmoothing; - // // m.transY += (m.transSmoothY - m.transY) * m.lookSmoothing; - // } - // }, - // remove() { - // if (this.count) m.look = m.lookDefault - // } - // }, - // { - // name: "facsimile", - // description: `inserts a copy of your current level into the level list`, - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // level.levels.splice(level.onLevel, 0, level.levels[level.onLevel]); - // }, - // remove() {} - // }, - // { - // name: "negative friction", - // description: "when you touch walls you speed up instead of slowing down. It's kinda fun.", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // player.friction = -0.4 - // }, - // remove() { - // if (this.count) player.friction = 0.002 - // } - // }, - // { - // name: "bounce", - // description: "you bounce off things. It's annoying, but not that bad.", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // player.restitution = 0.9 - // }, - // remove() { - // if (this.count) player.restitution = 0 - // } - // }, - // { - // name: "mouth", - // description: "mobs have a non functional mouth", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // mobs.draw = () => { - // ctx.lineWidth = 2; - // let i = mob.length; - // while (i--) { - // ctx.beginPath(); - // const vertices = mob[i].vertices; - // ctx.moveTo(vertices[0].x, vertices[0].y); - // for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y); - // ctx.quadraticCurveTo(mob[i].position.x, mob[i].position.y, vertices[0].x, vertices[0].y); - // ctx.fillStyle = mob[i].fill; - // ctx.strokeStyle = mob[i].stroke; - // ctx.fill(); - // ctx.stroke(); - // } - // } - // }, - // remove() { - // mobs.draw = () => { - // ctx.lineWidth = 2; - // let i = mob.length; - // while (i--) { - // ctx.beginPath(); - // const vertices = mob[i].vertices; - // ctx.moveTo(vertices[0].x, vertices[0].y); - // for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y); - // ctx.lineTo(vertices[0].x, vertices[0].y); - // ctx.fillStyle = mob[i].fill; - // ctx.strokeStyle = mob[i].stroke; - // ctx.fill(); - // ctx.stroke(); - // } - // } - // } - // }, - // { - // name: "all-stars", - // description: "make all mobs look like stars", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // mobs.draw = () => { - // ctx.lineWidth = 2; - // let i = mob.length; - // while (i--) { - // ctx.beginPath(); - // const vertices = mob[i].vertices; - // ctx.moveTo(vertices[0].x, vertices[0].y); - // for (let j = 1, len = vertices.length; j < len; ++j) ctx.quadraticCurveTo(mob[i].position.x, mob[i].position.y, vertices[j].x, vertices[j].y); - // ctx.quadraticCurveTo(mob[i].position.x, mob[i].position.y, vertices[0].x, vertices[0].y); - // ctx.fillStyle = mob[i].fill; - // ctx.strokeStyle = mob[i].stroke; - // ctx.fill(); - // ctx.stroke(); - // } - // } - // }, - // remove() { - // mobs.draw = () => { - // ctx.lineWidth = 2; - // let i = mob.length; - // while (i--) { - // ctx.beginPath(); - // const vertices = mob[i].vertices; - // ctx.moveTo(vertices[0].x, vertices[0].y); - // for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y); - // ctx.lineTo(vertices[0].x, vertices[0].y); - // ctx.fillStyle = mob[i].fill; - // ctx.strokeStyle = mob[i].stroke; - // ctx.fill(); - // ctx.stroke(); - // } - // } - // } - // }, - // // draw() { - // // ctx.lineWidth = 2; - // // let i = mob.length; - // // while (i--) { - // // ctx.beginPath(); - // // const vertices = mob[i].vertices; - // // ctx.moveTo(vertices[0].x, vertices[0].y); - // // for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y); - // // ctx.lineTo(vertices[0].x, vertices[0].y); - // // ctx.fillStyle = mob[i].fill; - // // ctx.strokeStyle = mob[i].stroke; - // // ctx.fill(); - // // ctx.stroke(); - // // } - // // }, - // { - // name: "true colors", - // description: `set all power ups to their real world colors`, - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // isNonRefundable: true, - // allowed() { return true }, - // requires: "", - // effect() { - // // const colors = shuffle(["#f7b", "#0eb", "#467", "#0cf", "hsl(246,100%,77%)", "#26a"]) - // const colors = shuffle([powerUps.research.color, powerUps.heal.color, powerUps.ammo.color, powerUps.ammo.color, powerUps.field.color, powerUps.gun.color]) - // powerUps.research.color = colors[0] - // powerUps.heal.color = colors[1] - // powerUps.ammo.color = colors[2] - // powerUps.field.color = colors[3] - // powerUps.tech.color = colors[4] - // powerUps.gun.color = colors[5] - // for (let i = 0; i < powerUp.length; i++) { - // switch (powerUp[i].name) { - // case "research": - // powerUp[i].color = colors[0] - // break; - // case "heal": - // powerUp[i].color = colors[1] - // break; - // case "ammo": - // powerUp[i].color = colors[2] - // break; - // case "field": - // powerUp[i].color = colors[3] - // break; - // case "tech": - // powerUp[i].color = colors[4] - // break; - // case "gun": - // powerUp[i].color = colors[5] - // break; - // } - // } - // }, - // remove() { - // // const colors = ["#f7b", "#0eb", "#467", "#0cf", "hsl(246,100%,77%)", "#26a"] //no shuffle - // // powerUps.research.color = colors[0] - // // powerUps.heal.color = colors[1] - // // powerUps.ammo.color = colors[2] - // // powerUps.field.color = colors[3] - // // powerUps.tech.color = colors[4] - // // powerUps.gun.color = colors[5] - // // for (let i = 0; i < powerUp.length; i++) { - // // switch (powerUp[i].name) { - // // case "research": - // // powerUp[i].color = colors[0] - // // break; - // // case "heal": - // // powerUp[i].color = colors[1] - // // break; - // // case "ammo": - // // powerUp[i].color = colors[2] - // // break; - // // case "field": - // // powerUp[i].color = colors[3] - // // break; - // // case "tech": - // // powerUp[i].color = colors[4] - // // break; - // // case "gun": - // // powerUp[i].color = colors[5] - // // break; - // // } - // // } - // } - // }, - // { - // name: "emergency broadcasting", - // description: "emit 2 sine waveforms at 853 Hz and 960 Hz
lower your volume", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // isNonRefundable: true, - // allowed() { return true }, - // requires: "", - // effect: () => { - // //setup audio context - // function tone(frequency) { - // const audioCtx = new(window.AudioContext || window.webkitAudioContext)(); - // const oscillator1 = audioCtx.createOscillator(); - // const gainNode1 = audioCtx.createGain(); - // gainNode1.gain.value = 0.5; //controls volume - // oscillator1.connect(gainNode1); - // gainNode1.connect(audioCtx.destination); - // oscillator1.type = "sine"; // 'sine' 'square', 'sawtooth', 'triangle' and 'custom' - // oscillator1.frequency.value = frequency; // value in hertz - // oscillator1.start(); - // return audioCtx - // } - // // let sound = tone(1050) - - // function EBS() { - // const audioCtx = new(window.AudioContext || window.webkitAudioContext)(); - - // const oscillator1 = audioCtx.createOscillator(); - // const gainNode1 = audioCtx.createGain(); - // gainNode1.gain.value = 0.3; //controls volume - // oscillator1.connect(gainNode1); - // gainNode1.connect(audioCtx.destination); - // oscillator1.type = "sine"; // 'sine' 'square', 'sawtooth', 'triangle' and 'custom' - // oscillator1.frequency.value = 850; // value in hertz - // oscillator1.start(); - - // const oscillator2 = audioCtx.createOscillator(); - // const gainNode2 = audioCtx.createGain(); - // gainNode2.gain.value = 0.3; //controls volume - // oscillator2.connect(gainNode2); - // gainNode2.connect(audioCtx.destination); - // oscillator2.type = "sine"; // 'sine' 'square', 'sawtooth', 'triangle' and 'custom' - // oscillator2.frequency.value = 957; // value in hertz - // oscillator2.start(); - // return audioCtx - // } - // let sound = EBS() - - // delay = 1000 - // setTimeout(() => { - // sound.suspend() - // powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + // // generate a script to run after creation + // function initGT() { + // // create a new translate element + // new google.translate.TranslateElement({ pageLanguage: 'en', layout: google.translate.TranslateElement.InlineLayout.HORIZONTAL }, 'gtElem') + // // ok now since it's loaded perform a funny hack to make it work + // const langSelect = document.getElementsByClassName("goog-te-combo")[0] + // // select a random language. It takes a second for all langauges to load, so wait a second. // setTimeout(() => { - // sound.resume() - // setTimeout(() => { - // sound.suspend() - // powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); - // setTimeout(() => { - // sound.resume() - // setTimeout(() => { - // sound.suspend() - // powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); - // setTimeout(() => { - // sound.resume() - // setTimeout(() => { - // sound.suspend() - // powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); - // setTimeout(() => { - // sound.resume() - // setTimeout(() => { - // sound.suspend() - // powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); - // setTimeout(() => { - // sound.resume() - // setTimeout(() => { - // sound.suspend() - // sound.close() - // powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); - // }, delay); - // }, delay); - // }, delay); - // }, delay); - // }, delay); - // }, delay); - // }, delay); - // }, delay); - // }, delay); - // }, delay); - // }, delay); - // }, - // remove() {} - // }, - // { - // name: "automatic", - // description: "you can't fire when moving
always fire when at rest", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // allowed() { - // return !tech.isFireMoveLock - // }, - // requires: "not Higgs mechanism", - // effect() { - // tech.isAlwaysFire = true; - // b.setFireMethod(); - // }, - // remove() { - // if (tech.isAlwaysFire) { - // tech.isAlwaysFire = false - // b.setFireMethod(); - // } - // } - // }, - // { - // name: "hidden variable", - // description: `spawn ${powerUps.orb.heal(20)}
but hide your health bar`, - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { - // return !tech.isEnergyHealth - // }, - // requires: "not mass-energy", - // effect() { - // document.getElementById("health").style.display = "none" - // document.getElementById("health-bg").style.display = "none" - // for (let i = 0; i < 20; i++) powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); - // }, - // remove() {} - // }, - // { - // name: "not a bug", - // description: "initiate a totally safe game crash for 10 seconds", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // const savedfunction = simulation.drawCircle - // simulation.drawCircle = () => { - // const a = mob[Infinity].position //crashed the game in a visually interesting way, because of the ctx.translate command is never reverted in the main game loop - // } - // setTimeout(() => { - // simulation.drawCircle = savedfunction - // canvas.width = canvas.width //clears the canvas // works on chrome at least - // powerUps.spawn(m.pos.x, m.pos.y, "tech"); - // }, 10000); + // langSelect.selectedIndex = Math.round(langSelect.options.length * Math.random()) + // // simulate a click + // langSelect.dispatchEvent(new Event('change')) + // // now make it go away + // const bar = document.getElementById(':1.container') + // bar.style.display = 'none' + // bar.style.visibility = 'hidden' + // }, 1000) - // // for (;;) {} //freezes the tab - // }, - // remove() {} - // }, - // { - // name: "spinor", - // description: "the direction you aim is determined by your position", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { - // return !m.isShipMode - // }, - // requires: "", - // effect() { - // m.look = function() { - // //always on mouse look - // m.angle = (((m.pos.x + m.pos.y) / 100 + Math.PI) % Math.PI * 2) - Math.PI - // //smoothed mouse look translations - // const scale = 0.8; - // m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale; - // m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale; - - // m.transX += (m.transSmoothX - m.transX) * 0.07; - // m.transY += (m.transSmoothY - m.transY) * 0.07; // } + + // // add the google translate script + // const translateScript = document.createElement('script') + // translateScript.src = '//translate.google.com/translate_a/element.js?cb=initGT' + // document.body.append(translateScript) // }, - // remove() { - // if (this.count) m.look = m.lookDefault - // } + // remove() {} // }, + { + name: "discount", + description: "get 3 random JUNK tech for the price of 1!", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + isNonRefundable: true, + allowed: () => true, + requires: "", + effect() { + tech.giveRandomJUNK() + tech.giveRandomJUNK() + tech.giveRandomJUNK() + }, + remove() {} + }, // { - // name: "decomposers", - // description: "after they die mobs leave behind spawns", + // name: "hi", + // description: `spawn to seed 616 `, // maxCount: 1, // count: 0, // frequency: 0, // isNonRefundable: true, // isJunk: true, // allowed() { - // return tech.deathSpawns === 0 + // return true // }, // requires: "", // effect() { - // tech.deathSpawns = 0.2 - // }, - // remove() { - // tech.deathSpawns = 0 - // } - // }, - // { - // name: "panopticon", - // description: "mobs can always see you", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // setInterval(() => { - // for (let i = 0; i < mob.length; i++) { - // if (!mob[i].shield && mob[i].isDropPowerUp) { - // mob[i].locatePlayer() - // mob[i].seePlayer.yes = true; - // } - // } - // }, 1000); //every 1 seconds + // document.getElementById("seed").placeholder = Math.initialSeed = String(616) + // Math.seed = Math.abs(Math.hash(Math.initialSeed)) //update randomizer seed in case the player changed it // }, // remove() {} // }, - // // { - // // name: "inverted mouse", - // // description: "your mouse is scrambled
it's fine, just rotate it 90 degrees", - // // maxCount: 1, - // // count: 0, - // // frequency: 0, - // // isExperimentHide: true, - // // isNonRefundable: true, - // // isJunk: true, - // // allowed() { - // // return !m.isShipMode - // // }, - // // requires: "not ship", - // // effect() { - // // document.body.addEventListener("mousemove", (e) => { - // // const ratio = window.innerWidth / window.innerHeight - // // simulation.mouse.x = e.clientY * ratio - // // simulation.mouse.y = e.clientX / ratio; - // // }); - // // }, - // // remove() { - // // // m.look = m.lookDefault - // // } - // // }, + { + name: "Higgs phase transition", + description: "instantly spawn 5 tech, but add a chance to
remove everything with a 5 minute half-life", + maxCount: 1, + count: 0, + frequency: 0, + frequencyDefault: 0, + isJunk: true, + isNonRefundable: true, + allowed: () => true, + requires: "", + effect() { + powerUps.spawn(m.pos.x, m.pos.y, "tech"); + powerUps.spawn(m.pos.x + 30, m.pos.y, "tech"); + powerUps.spawn(m.pos.x + 60, m.pos.y, "tech"); + powerUps.spawn(m.pos.x, m.pos.y - 30, "tech"); + powerUps.spawn(m.pos.x + 30, m.pos.y - 60, "tech"); + + function loop() { + // (1-X)^cycles = chance to be removed //Math.random() < 0.000019 10 min + if (!simulation.paused && m.alive) { + if (Math.random() < 0.000038) { + // m.death(); + simulation.clearMap(); + simulation.draw.setPaths(); + return + } + } + requestAnimationFrame(loop); + } + requestAnimationFrame(loop); + }, + remove() {} + }, + { + name: "harvest", + description: "convert all the mobs on this level into ammo", + maxCount: 1, + count: 0, + frequency: 0, + frequencyDefault: 0, + isJunk: true, + isNonRefundable: true, + allowed: () => true, + requires: "", + effect() { + for (let i = 0, len = mob.length; i < len; i++) { + if (mob[i].isDropPowerUp) { + powerUps.directSpawn(mob[i].position.x, mob[i].position.y, "ammo"); + mob[i].death(); + } + } + // for (let i = powerUp.length - 1; i > -1; i--) { + // if (powerUp[i].name !== "ammo") { + // Matter.Composite.remove(engine.world, powerUp[i]); + // powerUp.splice(i, 1); + // } + // } + }, + remove() {} + }, + { + name: " ", + description: "", + maxCount: 1, + count: 0, + frequency: 0, + frequencyDefault: 0, + isJunk: true, + allowed: () => true, + requires: "", + effect() { + + }, + remove() { + + } + }, + { + name: "brainstorm", + description: "the tech choice menu randomizes
every 0.5 seconds for 10 seconds", + maxCount: 1, + count: 0, + frequency: 0, + frequencyDefault: 0, + isJunk: true, + allowed: () => true, + requires: "", + effect() { + tech.isBrainstorm = true + tech.isBrainstormActive = false + tech.brainStormDelay = 30 + }, + remove() { + tech.isBrainstorm = false + tech.isBrainstormActive = false + } + }, + { + name: "catabolysis", + description: `set your maximum health to 1
double your current ammo 10 times`, + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return !tech.isFallingDamage && !tech.isOverHeal && !tech.isEnergyHealth }, + requires: "not quenching, tungsten carbide, mass-energy", + effect() { + m.baseHealth = 0.01 + m.setMaxHealth(); + for (let i = 0; i < b.guns.length; i++) b.guns[i].ammo = b.guns[i].ammo * Math.pow(2, 10) + simulation.updateGunHUD(); + }, + remove() {} + }, + { + name: "palantír", + description: `see far away lands`, + maxCount: 1, + count: 0, + frequency: 0, + // isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + m.look = () => { + //always on mouse look + m.angle = Math.atan2( + simulation.mouseInGame.y - m.pos.y, + simulation.mouseInGame.x - m.pos.x + ); + //smoothed mouse look translations + const scale = 2; + m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale; + m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale; + m.transX += (m.transSmoothX - m.transX) * m.lookSmoothing; + m.transY += (m.transSmoothY - m.transY) * m.lookSmoothing; + } + }, + remove() { + if (this.count) m.look = m.lookDefault + } + }, + { + name: "motion sickness", + description: `disable camera smoothing`, + maxCount: 1, + count: 0, + frequency: 0, + // isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + m.look = () => { + //always on mouse look + m.angle = Math.atan2( + simulation.mouseInGame.y - m.pos.y, + simulation.mouseInGame.x - m.pos.x + ); + //smoothed mouse look translations + const scale = 1.2; + m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale; + m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale; + m.transX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale; + m.transY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale; + // m.transX += (m.transSmoothX - m.transX) * m.lookSmoothing; + // m.transY += (m.transSmoothY - m.transY) * m.lookSmoothing; + } + }, + remove() { + if (this.count) m.look = m.lookDefault + } + }, + { + name: "facsimile", + description: `inserts a copy of your current level into the level list`, + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + level.levels.splice(level.onLevel, 0, level.levels[level.onLevel]); + }, + remove() {} + }, + { + name: "negative friction", + description: "when you touch walls you speed up instead of slowing down. It's kinda fun.", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + player.friction = -0.4 + }, + remove() { + if (this.count) player.friction = 0.002 + } + }, + { + name: "bounce", + description: "you bounce off things. It's annoying, but not that bad.", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + player.restitution = 0.9 + }, + remove() { + if (this.count) player.restitution = 0 + } + }, + { + name: "mouth", + description: "mobs have a non functional mouth", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + mobs.draw = () => { + ctx.lineWidth = 2; + let i = mob.length; + while (i--) { + ctx.beginPath(); + const vertices = mob[i].vertices; + ctx.moveTo(vertices[0].x, vertices[0].y); + for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y); + ctx.quadraticCurveTo(mob[i].position.x, mob[i].position.y, vertices[0].x, vertices[0].y); + ctx.fillStyle = mob[i].fill; + ctx.strokeStyle = mob[i].stroke; + ctx.fill(); + ctx.stroke(); + } + } + }, + remove() { + mobs.draw = () => { + ctx.lineWidth = 2; + let i = mob.length; + while (i--) { + ctx.beginPath(); + const vertices = mob[i].vertices; + ctx.moveTo(vertices[0].x, vertices[0].y); + for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y); + ctx.lineTo(vertices[0].x, vertices[0].y); + ctx.fillStyle = mob[i].fill; + ctx.strokeStyle = mob[i].stroke; + ctx.fill(); + ctx.stroke(); + } + } + } + }, + { + name: "all-stars", + description: "make all mobs look like stars", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + mobs.draw = () => { + ctx.lineWidth = 2; + let i = mob.length; + while (i--) { + ctx.beginPath(); + const vertices = mob[i].vertices; + ctx.moveTo(vertices[0].x, vertices[0].y); + for (let j = 1, len = vertices.length; j < len; ++j) ctx.quadraticCurveTo(mob[i].position.x, mob[i].position.y, vertices[j].x, vertices[j].y); + ctx.quadraticCurveTo(mob[i].position.x, mob[i].position.y, vertices[0].x, vertices[0].y); + ctx.fillStyle = mob[i].fill; + ctx.strokeStyle = mob[i].stroke; + ctx.fill(); + ctx.stroke(); + } + } + }, + remove() { + mobs.draw = () => { + ctx.lineWidth = 2; + let i = mob.length; + while (i--) { + ctx.beginPath(); + const vertices = mob[i].vertices; + ctx.moveTo(vertices[0].x, vertices[0].y); + for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y); + ctx.lineTo(vertices[0].x, vertices[0].y); + ctx.fillStyle = mob[i].fill; + ctx.strokeStyle = mob[i].stroke; + ctx.fill(); + ctx.stroke(); + } + } + } + }, + // draw() { + // ctx.lineWidth = 2; + // let i = mob.length; + // while (i--) { + // ctx.beginPath(); + // const vertices = mob[i].vertices; + // ctx.moveTo(vertices[0].x, vertices[0].y); + // for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y); + // ctx.lineTo(vertices[0].x, vertices[0].y); + // ctx.fillStyle = mob[i].fill; + // ctx.strokeStyle = mob[i].stroke; + // ctx.fill(); + // ctx.stroke(); + // } + // }, + { + name: "true colors", + description: `set all power ups to their real world colors`, + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + isNonRefundable: true, + allowed() { return true }, + requires: "", + effect() { + // const colors = shuffle(["#f7b", "#0eb", "#467", "#0cf", "hsl(246,100%,77%)", "#26a"]) + const colors = shuffle([powerUps.research.color, powerUps.heal.color, powerUps.ammo.color, powerUps.ammo.color, powerUps.field.color, powerUps.gun.color]) + powerUps.research.color = colors[0] + powerUps.heal.color = colors[1] + powerUps.ammo.color = colors[2] + powerUps.field.color = colors[3] + powerUps.tech.color = colors[4] + powerUps.gun.color = colors[5] + for (let i = 0; i < powerUp.length; i++) { + switch (powerUp[i].name) { + case "research": + powerUp[i].color = colors[0] + break; + case "heal": + powerUp[i].color = colors[1] + break; + case "ammo": + powerUp[i].color = colors[2] + break; + case "field": + powerUp[i].color = colors[3] + break; + case "tech": + powerUp[i].color = colors[4] + break; + case "gun": + powerUp[i].color = colors[5] + break; + } + } + }, + remove() { + // const colors = ["#f7b", "#0eb", "#467", "#0cf", "hsl(246,100%,77%)", "#26a"] //no shuffle + // powerUps.research.color = colors[0] + // powerUps.heal.color = colors[1] + // powerUps.ammo.color = colors[2] + // powerUps.field.color = colors[3] + // powerUps.tech.color = colors[4] + // powerUps.gun.color = colors[5] + // for (let i = 0; i < powerUp.length; i++) { + // switch (powerUp[i].name) { + // case "research": + // powerUp[i].color = colors[0] + // break; + // case "heal": + // powerUp[i].color = colors[1] + // break; + // case "ammo": + // powerUp[i].color = colors[2] + // break; + // case "field": + // powerUp[i].color = colors[3] + // break; + // case "tech": + // powerUp[i].color = colors[4] + // break; + // case "gun": + // powerUp[i].color = colors[5] + // break; + // } + // } + } + }, + { + name: "emergency broadcasting", + description: "emit 2 sine waveforms at 853 Hz and 960 Hz
lower your volume", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + isNonRefundable: true, + allowed() { return true }, + requires: "", + effect: () => { + //setup audio context + function tone(frequency) { + const audioCtx = new(window.AudioContext || window.webkitAudioContext)(); + const oscillator1 = audioCtx.createOscillator(); + const gainNode1 = audioCtx.createGain(); + gainNode1.gain.value = 0.5; //controls volume + oscillator1.connect(gainNode1); + gainNode1.connect(audioCtx.destination); + oscillator1.type = "sine"; // 'sine' 'square', 'sawtooth', 'triangle' and 'custom' + oscillator1.frequency.value = frequency; // value in hertz + oscillator1.start(); + return audioCtx + } + // let sound = tone(1050) + + function EBS() { + const audioCtx = new(window.AudioContext || window.webkitAudioContext)(); + + const oscillator1 = audioCtx.createOscillator(); + const gainNode1 = audioCtx.createGain(); + gainNode1.gain.value = 0.3; //controls volume + oscillator1.connect(gainNode1); + gainNode1.connect(audioCtx.destination); + oscillator1.type = "sine"; // 'sine' 'square', 'sawtooth', 'triangle' and 'custom' + oscillator1.frequency.value = 850; // value in hertz + oscillator1.start(); + + const oscillator2 = audioCtx.createOscillator(); + const gainNode2 = audioCtx.createGain(); + gainNode2.gain.value = 0.3; //controls volume + oscillator2.connect(gainNode2); + gainNode2.connect(audioCtx.destination); + oscillator2.type = "sine"; // 'sine' 'square', 'sawtooth', 'triangle' and 'custom' + oscillator2.frequency.value = 957; // value in hertz + oscillator2.start(); + return audioCtx + } + let sound = EBS() + + delay = 1000 + setTimeout(() => { + sound.suspend() + powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + setTimeout(() => { + sound.resume() + setTimeout(() => { + sound.suspend() + powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + setTimeout(() => { + sound.resume() + setTimeout(() => { + sound.suspend() + powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + setTimeout(() => { + sound.resume() + setTimeout(() => { + sound.suspend() + powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + setTimeout(() => { + sound.resume() + setTimeout(() => { + sound.suspend() + powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + setTimeout(() => { + sound.resume() + setTimeout(() => { + sound.suspend() + sound.close() + powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, + remove() {} + }, + { + name: "automatic", + description: "you can't fire when moving
always fire when at rest", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + allowed() { + return !tech.isFireMoveLock + }, + requires: "not Higgs mechanism", + effect() { + tech.isAlwaysFire = true; + b.setFireMethod(); + }, + remove() { + if (tech.isAlwaysFire) { + tech.isAlwaysFire = false + b.setFireMethod(); + } + } + }, + { + name: "hidden variable", + description: `spawn ${powerUps.orb.heal(20)}
but hide your health bar`, + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { + return !tech.isEnergyHealth + }, + requires: "not mass-energy", + effect() { + document.getElementById("health").style.display = "none" + document.getElementById("health-bg").style.display = "none" + for (let i = 0; i < 20; i++) powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + }, + remove() {} + }, + { + name: "not a bug", + description: "initiate a totally safe game crash for 10 seconds", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + const savedfunction = simulation.drawCircle + simulation.drawCircle = () => { + const a = mob[Infinity].position //crashed the game in a visually interesting way, because of the ctx.translate command is never reverted in the main game loop + } + setTimeout(() => { + simulation.drawCircle = savedfunction + canvas.width = canvas.width //clears the canvas // works on chrome at least + powerUps.spawn(m.pos.x, m.pos.y, "tech"); + }, 10000); + + // for (;;) {} //freezes the tab + }, + remove() {} + }, + { + name: "spinor", + description: "the direction you aim is determined by your position", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { + return !m.isShipMode + }, + requires: "", + effect() { + m.look = function() { + //always on mouse look + m.angle = (((m.pos.x + m.pos.y) / 100 + Math.PI) % Math.PI * 2) - Math.PI + //smoothed mouse look translations + const scale = 0.8; + m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale; + m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale; + + m.transX += (m.transSmoothX - m.transX) * 0.07; + m.transY += (m.transSmoothY - m.transY) * 0.07; + } + }, + remove() { + if (this.count) m.look = m.lookDefault + } + }, + { + name: "decomposers", + description: "after they die mobs leave behind spawns", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { + return tech.deathSpawns === 0 + }, + requires: "", + effect() { + tech.deathSpawns = 0.2 + }, + remove() { + tech.deathSpawns = 0 + } + }, + { + name: "panopticon", + description: "mobs can always see you", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + setInterval(() => { + for (let i = 0; i < mob.length; i++) { + if (!mob[i].shield && mob[i].isDropPowerUp) { + mob[i].locatePlayer() + mob[i].seePlayer.yes = true; + } + } + }, 1000); //every 1 seconds + }, + remove() {} + }, // { - // name: "Fourier analysis", - // description: "your aiming is now controlled by this equation:
2sin(0.0133t) + sin(0.013t) + 0.5sin(0.031t)+ 0.33sin(0.03t)", + // name: "inverted mouse", + // description: "your mouse is scrambled
it's fine, just rotate it 90 degrees", // maxCount: 1, // count: 0, // frequency: 0, + // isExperimentHide: true, + // isNonRefundable: true, // isJunk: true, // allowed() { // return !m.isShipMode // }, // requires: "not ship", // effect() { - // m.look = () => { - // m.angle = 2 * Math.sin(m.cycle * 0.0133) + Math.sin(m.cycle * 0.013) + 0.5 * Math.sin(m.cycle * 0.031) + 0.33 * Math.sin(m.cycle * 0.03) - // const scale = 0.8; - // simulation.mouse.y - // m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale; - // m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale; - // m.transX += (m.transSmoothX - m.transX) * 0.07; - // m.transY += (m.transSmoothY - m.transY) * 0.07; - // } + // document.body.addEventListener("mousemove", (e) => { + // const ratio = window.innerWidth / window.innerHeight + // simulation.mouse.x = e.clientY * ratio + // simulation.mouse.y = e.clientX / ratio; + // }); // }, // remove() { - // if (this.count) m.look = m.lookDefault + // // m.look = m.lookDefault // } // }, - // { - // name: "disintegrated armament", - // description: "spawn a gun
remove your active gun", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { - // return b.inventory.length > 0 - // }, - // requires: "at least 1 gun", - // effect() { - // if (b.inventory.length > 0) b.removeGun(b.guns[b.activeGun].name) - // simulation.makeGunHUD() - // powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "gun"); - // }, - // remove() {} - // }, - // { - // name: "probability", - // description: "increase the frequency
of one random tech by 100", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // let options = []; //find what tech I could get - // for (let i = 0, len = tech.tech.length; i < len; i++) { - // if ( - // tech.tech[i].count < tech.tech[i].maxCount && - // tech.tech[i].allowed() && - // !tech.tech[i].isJunk && - // !tech.tech.isLore - // ) { - // options.push(i); - // } - // } - // if (options.length) { - // const index = options[Math.floor(Math.random() * options.length)] - // tech.tech[index].frequency = 100 - // } - // }, - // remove() {} - // }, - // { - // name: "encryption", - // description: "secure tech information", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // String.prototype.shuffle = function() { - // var a = this.split(""), - // n = a.length; + { + name: "Fourier analysis", + description: "your aiming is now controlled by this equation:
2sin(0.0133t) + sin(0.013t) + 0.5sin(0.031t)+ 0.33sin(0.03t)", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + allowed() { + return !m.isShipMode + }, + requires: "not ship", + effect() { + m.look = () => { + m.angle = 2 * Math.sin(m.cycle * 0.0133) + Math.sin(m.cycle * 0.013) + 0.5 * Math.sin(m.cycle * 0.031) + 0.33 * Math.sin(m.cycle * 0.03) + const scale = 0.8; + simulation.mouse.y + m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale; + m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale; + m.transX += (m.transSmoothX - m.transX) * 0.07; + m.transY += (m.transSmoothY - m.transY) * 0.07; + } + }, + remove() { + if (this.count) m.look = m.lookDefault + } + }, + { + name: "disintegrated armament", + description: "spawn a gun
remove your active gun", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { + return b.inventory.length > 0 + }, + requires: "at least 1 gun", + effect() { + if (b.inventory.length > 0) b.removeGun(b.guns[b.activeGun].name) + simulation.makeGunHUD() + powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "gun"); + }, + remove() {} + }, + { + name: "probability", + description: "increase the frequency
of one random tech by 100", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + let options = []; //find what tech I could get + for (let i = 0, len = tech.tech.length; i < len; i++) { + if ( + tech.tech[i].count < tech.tech[i].maxCount && + tech.tech[i].allowed() && + !tech.tech[i].isJunk && + !tech.tech.isLore + ) { + options.push(i); + } + } + if (options.length) { + const index = options[Math.floor(Math.random() * options.length)] + tech.tech[index].frequency = 100 + } + }, + remove() {} + }, + { + name: "encryption", + description: "secure tech information", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + String.prototype.shuffle = function() { + var a = this.split(""), + n = a.length; - // for (var i = n - 1; i > 0; i--) { - // var j = Math.floor(Math.random() * (i + 1)); - // var tmp = a[i]; - // a[i] = a[j]; - // a[j] = tmp; - // } - // return a.join(""); - // } + for (var i = n - 1; i > 0; i--) { + var j = Math.floor(Math.random() * (i + 1)); + var tmp = a[i]; + a[i] = a[j]; + a[j] = tmp; + } + return a.join(""); + } - // for (let i = 0, len = tech.tech.length; i < len; i++) tech.tech[i].name = tech.tech[i].name.shuffle() - // }, - // remove() {} - // }, + for (let i = 0, len = tech.tech.length; i < len; i++) tech.tech[i].name = tech.tech[i].name.shuffle() + }, + remove() {} + }, + { + name: "quantum leap", + description: "become an alternate version of yourself
every 20 seconds", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + setInterval(() => { + m.switchWorlds() + simulation.trails() + }, 20000); //every 30 seconds + }, + remove() {} + }, + { + name: "score", + description: "Add a score to n-gon!", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + setInterval(() => { + let score = Math.ceil(1000 * Math.random() * Math.random() * Math.random() * Math.random() * Math.random()) + simulation.makeTextLog(`simulation.score = ${score.toFixed(0)}`); + }, 10000); //every 10 seconds + }, + remove() {} + }, + { + name: "pop-ups", + description: "sign up to learn endless easy ways to win n-gon
that Landgreen doesn't want you to know!!!1!!", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + setInterval(() => { + alert(`The best combo is ${tech.tech[Math.floor(Math.random() * tech.tech.length)].name} with ${tech.tech[Math.floor(Math.random() * tech.tech.length)].name}!`); + }, 30000); //every 30 seconds + }, + remove() {} + }, + { + name: "music", + description: "add music to n-gon", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + window.open('https://www.youtube.com/watch?v=lEbHeSdmS-k&list=PL9Z5wjoBiPKEDhwCW2RN-VZoCpmhIojdn', '_blank') + }, + remove() {} + }, + { + name: "performance", + description: "display performance stats to n-gon", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + (function() { + var script = document.createElement('script'); + script.onload = function() { + var stats = new Stats(); + document.body.appendChild(stats.dom); + requestAnimationFrame(function loop() { + stats.update(); + requestAnimationFrame(loop) + }); + }; + script.src = 'https://unpkg.com/stats.js@0.17.0/build/stats.min.js'; + document.head.appendChild(script); + })() + //move health to the right + document.getElementById("health").style.left = "86px" + document.getElementById("health-bg").style.left = "86px" + }, + remove() {} + }, + { + name: "repartitioning", + description: "set the frequency of finding normal tech to 0
spawn 5 tech", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + for (let i = 0, len = tech.tech.length; i < len; i++) { + if (tech.tech[i].isJunk) { + tech.tech[i].frequency = 2 + } else { + tech.tech[i].frequency = 0 + } + } + for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x, m.pos.y, "tech"); + }, + remove() {} + }, + { + name: "defragment", + description: "set the frequency of finding JUNK tech to zero", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + for (let i = tech.tech.length - 1; i > 0; i--) { + if (tech.tech[i].isJunk) tech.tech[i].frequency = 0 + } + }, + remove() {} + }, // { - // name: "quantum leap", - // description: "become an alternate version of yourself
every 20 seconds", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // setInterval(() => { - // m.switchWorlds() - // simulation.trails() - // }, 20000); //every 30 seconds - // }, - // remove() {} - // }, - // { - // name: "score", - // description: "Add a score to n-gon!", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // setInterval(() => { - // let score = Math.ceil(1000 * Math.random() * Math.random() * Math.random() * Math.random() * Math.random()) - // simulation.makeTextLog(`simulation.score = ${score.toFixed(0)}`); - // }, 10000); //every 10 seconds - // }, - // remove() {} - // }, - // { - // name: "pop-ups", - // description: "sign up to learn endless easy ways to win n-gon
that Landgreen doesn't want you to know!!!1!!", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // setInterval(() => { - // alert(`The best combo is ${tech.tech[Math.floor(Math.random() * tech.tech.length)].name} with ${tech.tech[Math.floor(Math.random() * tech.tech.length)].name}!`); - // }, 30000); //every 30 seconds - // }, - // remove() {} - // }, - // { - // name: "music", - // description: "add music to n-gon", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // window.open('https://www.youtube.com/watch?v=lEbHeSdmS-k&list=PL9Z5wjoBiPKEDhwCW2RN-VZoCpmhIojdn', '_blank') - // }, - // remove() {} - // }, - // { - // name: "performance", - // description: "display performance stats to n-gon", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // (function() { - // var script = document.createElement('script'); - // script.onload = function() { - // var stats = new Stats(); - // document.body.appendChild(stats.dom); - // requestAnimationFrame(function loop() { - // stats.update(); - // requestAnimationFrame(loop) - // }); - // }; - // script.src = 'https://unpkg.com/stats.js@0.17.0/build/stats.min.js'; - // document.head.appendChild(script); - // })() - // //move health to the right - // document.getElementById("health").style.left = "86px" - // document.getElementById("health-bg").style.left = "86px" - // }, - // remove() {} - // }, - // { - // name: "repartitioning", - // description: "set the frequency of finding normal tech to 0
spawn 5 tech", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // for (let i = 0, len = tech.tech.length; i < len; i++) { - // if (tech.tech[i].isJunk) { - // tech.tech[i].frequency = 2 - // } else { - // tech.tech[i].frequency = 0 - // } - // } - // for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x, m.pos.y, "tech"); - // }, - // remove() {} - // }, - // { - // name: "defragment", - // description: "set the frequency of finding JUNK tech to zero", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // for (let i = tech.tech.length - 1; i > 0; i--) { - // if (tech.tech[i].isJunk) tech.tech[i].frequency = 0 - // } - // }, - // remove() {} - // }, - // // { - // // name: "lubrication", - // // description: "reduce block density and friction for this level", - // // maxCount: 9, - // // count: 0, - // // frequency: 0, - // // isNonRefundable: true, - // // isExperimentHide: true, - // // isJunk: true, - // // allowed() { - // // return true - // // }, - // // requires: "", - // // effect() { - // // for (let i = 0; i < body.length; i++) { - // // Matter.Body.setDensity(body[i], 0.0001) // 0.001 is normal - // // body[i].friction = 0.01 - // // } - // // }, - // // remove() {} - // // }, - // { - // name: "pitch", - // description: "oscillate the pitch of your world", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // setInterval(() => { if (!simulation.paused) ctx.rotate(0.001 * Math.sin(simulation.cycle * 0.01)) }, 16); - // }, - // remove() {} - // }, - // { - // name: "umbra", - // description: "produce a blue glow around everything
and probably some simulation lag", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // ctx.shadowColor = '#06f'; - // ctx.shadowBlur = 25; - // }, - // remove() {} - // }, - // { - // name: "lighter", - // description: `ctx.globalCompositeOperation = "lighter"`, - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { - // return m.fieldUpgrades[m.fieldMode].name !== "negative mass" - // }, - // requires: "", - // effect() { - // ctx.globalCompositeOperation = "lighter"; - // }, - // remove() {} - // }, - // { - // name: "rewind", - // description: "every 10 seconds rewind 2 seconds", + // name: "lubrication", + // description: "reduce block density and friction for this level", // maxCount: 9, // count: 0, // frequency: 0, // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // setInterval(() => { - // m.rewind(120) - // m.energy += 0.4 - // }, 10000); - // // for (let i = 0; i < 24; i++) { - // // setTimeout(() => { m.rewind(120) }, i * 5000); - // // } - // }, - // remove() {} - // }, - // { - // name: "undo", - // description: "every 4 seconds rewind 1/2 a second", - // maxCount: 9, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // setInterval(() => { - // m.rewind(30) - // m.energy += 0.2 - // }, 4000); - // }, - // remove() {} - // }, - // { - // name: "energy to mass conversion", - // description: "convert your energy into blocks", - // maxCount: 9, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // for (let i = 0, len = 40; i < len; i++) { - // setTimeout(() => { - // m.energy -= 1 / len - // const index = body.length - // where = Vector.add(m.pos, { x: 400 * (Math.random() - 0.5), y: 400 * (Math.random() - 0.5) }) - // spawn.bodyRect(where.x, where.y, Math.floor(15 + 100 * Math.random()), Math.floor(15 + 100 * Math.random())); - // body[index].collisionFilter.category = cat.body; - // body[index].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet - // body[index].classType = "body"; - // Composite.add(engine.world, body[index]); //add to world - // }, i * 100); - // } - - // }, - // remove() {} - // }, - // { - // name: "level.nextLevel()", - // description: "advance to the next level", - // maxCount: 9, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // level.nextLevel(); - // }, - // remove() {} - // }, - // { - // name: "reincarnation", - // description: "kill all mobs and spawn new ones
(also spawn a few extra mobs for fun)", - // maxCount: 3, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // spawn.setSpawnList(); - // spawn.setSpawnList(); - // for (let i = 0, len = mob.length; i < len; i++) { - // if (mob[i].alive && !mob[i].shield && !mob[i].isBadTarget) { - // const pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; - // spawn[pick](mob[i].position.x, mob[i].position.y); - // if (Math.random() < 0.5) spawn[pick](mob[i].position.x, mob[i].position.y); - // mob[i].death(); - // } - // } - // }, - // remove() {} - // }, - // { - // name: "expert system", - // description: "spawn a tech power up
+64% JUNK to tech pool", - // maxCount: 9, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // powerUps.spawn(m.pos.x, m.pos.y, "tech"); - // tech.addJunkTechToPool(0.64) - // }, - // remove() {} - // }, - // { - // name: "energy investment", - // description: "every 10 seconds drain your energy
return it doubled 5 seconds later", - // maxCount: 9, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // setInterval(() => { - // if (!simulation.paused) { - // const energy = m.energy - // m.energy = 0 - // setTimeout(() => { //return energy - // m.energy += 2 * energy - // }, 5000); - // } - // }, 10000); - // }, - // remove() {} - // }, - // { - // name: "missile launching system", - // description: "fire missiles for the next 120 seconds", - // maxCount: 9, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // for (let i = 0; i < 120; i++) { - // setTimeout(() => { - // const where = { - // x: m.pos.x, - // y: m.pos.y - 40 - // } - // b.missile(where, -Math.PI / 2 + 0.2 * (Math.random() - 0.5) * Math.sqrt(tech.missileCount), -2) - // }, i * 1000); - // } - // }, - // remove() {} - // }, - // { - // name: "grenade production", - // description: "drop a grenade every 2 seconds", - // maxCount: 9, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // setInterval(() => { - // if (!simulation.paused && document.visibilityState !== "hidden") { - // b.grenade(Vector.add(m.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -Math.PI / 2) //fire different angles for each grenade - // const who = bullet[bullet.length - 1] - // Matter.Body.setVelocity(who, { - // x: who.velocity.x * 0.1, - // y: who.velocity.y * 0.1 - // }); - // } - // }, 2000); - // }, - // remove() {} - // }, - // // { - // // name: "inverted input", - // // description: "left input becomes right and up input becomes down", - // // maxCount: 9, - // // count: 0, - // // frequency: 0, - // // isNonRefundable: true, - // // isExperimentHide: true, - // // isJunk: true, - // // allowed() { - // // return true - // // }, - // // requires: "", - // // effect() { - // // const left = input.key.left - // // input.key.left = input.key.right - // // input.key.right = left - - // // const up = input.key.up - // // input.key.up = input.key.down - // // input.key.down = up - // // }, - // // remove() {} - // // }, - // { - // name: "Sleipnir", - // description: "grow more legs", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isSkin: true, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return !m.isShipMode }, - // requires: "", - // effect() { - // m.draw = function() { - // ctx.fillStyle = m.fillColor; - // m.walk_cycle += m.flipLegs * m.Vx; - - // //draw body - // ctx.save(); - // ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 - // ctx.translate(m.pos.x, m.pos.y); - // for (let i = 0; i < 16; i++) { - // m.calcLeg(Math.PI * i / 8, -3 * i / 16) - // m.drawLeg("#444") - // } - // ctx.rotate(m.angle); - - // ctx.beginPath(); - // ctx.arc(0, 0, 30, 0, 2 * Math.PI); - // ctx.fillStyle = m.bodyGradient - // ctx.fill(); - // ctx.arc(15, 0, 4, 0, 2 * Math.PI); - // ctx.strokeStyle = "#333"; - // ctx.lineWidth = 2; - // ctx.stroke(); - // // ctx.beginPath(); - // // ctx.arc(15, 0, 3, 0, 2 * Math.PI); - // // ctx.fillStyle = '#0cf'; - // // ctx.fill() - // ctx.restore(); - // m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal - // } - // }, - // remove() {} - // }, - // { - // name: "diegesis", - // description: "indicate fire cooldown
through a rotation of your head", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isSkin: true, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return !m.isShipMode }, - // requires: "", - // effect() { - // m.draw = function() { - // ctx.fillStyle = m.fillColor; - // m.walk_cycle += m.flipLegs * m.Vx; - - // ctx.save(); - // ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 - // ctx.translate(m.pos.x, m.pos.y); - // m.calcLeg(Math.PI, -3); - // m.drawLeg("#4a4a4a"); - // m.calcLeg(0, 0); - // m.drawLeg("#333"); - // ctx.rotate(m.angle - (m.fireCDcycle != Infinity ? m.flipLegs * 0.25 * Math.pow(Math.max(m.fireCDcycle - m.cycle, 0), 0.5) : 0)); - - // ctx.beginPath(); - // ctx.arc(0, 0, 30, 0, 2 * Math.PI); - // ctx.fillStyle = m.bodyGradient - // ctx.fill(); - // ctx.arc(15, 0, 4, 0, 2 * Math.PI); - // ctx.strokeStyle = "#333"; - // ctx.lineWidth = 2; - // ctx.stroke(); - // ctx.restore(); - // m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal - // } - // }, - // remove() {} - // }, - // { - // name: "🐱", - // description: "🐈", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isSkin: true, - // isNonRefundable: true, + // isExperimentHide: true, // isJunk: true, // allowed() { - // return !m.isShipMode + // return true // }, // requires: "", // effect() { - // m.draw = function() { - // ctx.fillStyle = m.fillColor; - // m.walk_cycle += m.flipLegs * m.Vx; - // ctx.save(); - // ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 - // ctx.translate(m.pos.x, m.pos.y); - // m.calcLeg(Math.PI, -3); - // m.drawLeg("#4a4a4a"); - - - // if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) { - // ctx.scale(1, -1); - // ctx.rotate(Math.PI); - // } - // ctx.beginPath(); - // ctx.moveTo(-30, 0); - // ctx.bezierCurveTo(-65, -75, - // -5, 150 + (5 * Math.sin(simulation.cycle / 10)), - // -70 + (10 * Math.sin(simulation.cycle / 10)), 0 + (10 * Math.sin(simulation.cycle / 10))); - // ctx.strokeStyle = "#333"; - // ctx.lineWidth = 4; - // ctx.stroke(); - - // if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) { - // ctx.scale(1, -1); - // ctx.rotate(0 - Math.PI); - // } - // m.calcLeg(0, 0); - // m.drawLeg("#333"); - - // ctx.rotate(m.angle); - // if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) ctx.scale(1, -1); - // ctx.beginPath(); - // ctx.moveTo(5, -30); - // ctx.lineTo(20, -40); - // ctx.lineTo(20, -20); - // ctx.lineWidth = 2; - // ctx.fillStyle = "#f3f"; - // ctx.fill(); - // ctx.stroke(); - - // ctx.beginPath(); - // ctx.arc(0, 0, 30, 0, 2 * Math.PI); - // ctx.fillStyle = m.bodyGradient - // ctx.fill(); - // ctx.stroke(); - // ctx.moveTo(19, 0); - // ctx.arc(15, 0, 4, Math.PI, 2 * Math.PI); - // ctx.stroke(); - // ctx.beginPath(); - // ctx.arc(24.3, 6, 5, Math.PI * 2, Math.PI); - // ctx.stroke(); - - // ctx.beginPath(); - // ctx.moveTo(30, 6); - // ctx.lineTo(32, 0); - // ctx.lineTo(26, 0); - // ctx.lineTo(30, 6); - // ctx.fillStyle = "#f3f"; - // ctx.fill(); - // ctx.stroke(); - - // ctx.restore(); - // m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal + // for (let i = 0; i < body.length; i++) { + // Matter.Body.setDensity(body[i], 0.0001) // 0.001 is normal + // body[i].friction = 0.01 // } // }, // remove() {} // }, - // { - // name: "transparency", - // description: "become invisible to yourself
mobs can still see you", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isSkin: true, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // m.draw = () => {} - // }, - // remove() {} - // }, - // { - // name: "posture", - // description: "stand a bit taller", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isSkin: true, - // isJunk: true, - // allowed() { - // return !m.isShipMode - // }, - // requires: "", - // effect() { - // m.yOffWhen.stand = 70 - // }, - // remove() { - // m.yOffWhen.stand = 49 - // } - // }, - // { - // name: "rhythm", - // description: "you oscillate up and down", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isSkin: true, - // isJunk: true, - // isNonRefundable: true, - // allowed() { - // return !m.isShipMode - // }, - // requires: "", - // effect() { - // setInterval(() => { - // m.yOffWhen.stand = 53 + 28 * Math.sin(simulation.cycle * 0.2) - // if (m.onGround && !m.crouch) m.yOffGoal = m.yOffWhen.stand - // }, 100); - // }, - // remove() {} - // }, - // { - // name: "pareidolia", - // description: "don't", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isSkin: true, - // isNonRefundable: true, - // isJunk: true, - // allowed() { - // return !m.isShipMode - // }, - // requires: "", - // effect() { - // m.draw = function() { - // ctx.fillStyle = m.fillColor; - // m.walk_cycle += m.flipLegs * m.Vx; - // ctx.save(); - // ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.7 - // ctx.translate(m.pos.x, m.pos.y); - // m.calcLeg(Math.PI, -3); - // m.drawLeg("#4a4a4a"); - // m.calcLeg(0, 0); - // m.drawLeg("#333"); - // ctx.rotate(m.angle); - // ctx.beginPath(); - // ctx.arc(0, 0, 30, 0, 2 * Math.PI); - // ctx.fillStyle = m.bodyGradient - // ctx.fill(); - // ctx.strokeStyle = "#333"; - // ctx.lineWidth = 2; - // if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) ctx.scale(1, -1); //here is the flip - // ctx.stroke(); - // ctx.beginPath(); - // ctx.arc(2, -6, 7, 0, 2 * Math.PI); - // ctx.stroke(); - // ctx.beginPath(); - // ctx.arc(25, -6, 7, 0.25 * Math.PI, 1.6 * Math.PI); - // ctx.stroke(); - // ctx.beginPath(); - // ctx.arc(2, -10, 9, 1.25 * Math.PI, 1.75 * Math.PI); - // ctx.stroke(); - // ctx.beginPath(); - // ctx.arc(25, -10, 9, 1.25 * Math.PI, 1.4 * Math.PI); - // ctx.stroke(); - // ctx.beginPath(); - // ctx.arc(18, 13, 10, 0, 2 * Math.PI); - // ctx.fillStyle = m.bodyGradient; - // ctx.fill(); - // ctx.stroke(); - // ctx.beginPath(); - // ctx.arc(18, 13, 6, 0, 2 * Math.PI); - // ctx.fillStyle = "#555"; - // ctx.fill(); - // ctx.stroke(); - // ctx.beginPath(); - // ctx.arc(3, -6, 3, 0, 2 * Math.PI); - // ctx.fill(); - // ctx.stroke(); - // ctx.beginPath(); - // ctx.arc(26, -6, 3, 0, 2 * Math.PI); - // ctx.fill(); - // ctx.stroke(); - // ctx.restore(); - // m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; - // } - // }, - // remove() {} - // }, - // { - // name: "prism", - // description: "you cycle through different colors", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isSkin: true, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // m.color = { - // hue: 0, - // sat: 100, - // light: 50 - // } - // setInterval(function() { - // m.color.hue++ - // m.setFillColors() - // }, 10); - // }, - // remove() {} - // }, - // { - // name: "microtransactions", - // description: `when you choose a tech you can
use ${powerUps.orb.research(1)} to buy a free in game skin`, - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // tech.isMicroTransactions = true - // }, - // remove() { - // tech.isMicroTransactions = false - // } - // }, - // { - // name: "ship", - // description: "fly around with no legs
reduce combat difficulty by 1 level", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { - // return !m.isShipMode && m.fieldUpgrades[m.fieldMode].name !== "negative mass" - // }, - // requires: "", - // effect() { - // m.shipMode() - // level.difficultyDecrease(simulation.difficultyMode) - // }, - // remove() {} - // }, - // { - // name: "assimilation", - // description: "all your bots are converted to the same random model", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isBotTech: true, - // isNonRefundable: true, - // isJunk: true, - // allowed() { - // return b.totalBots() > 2 - // }, - // requires: "at least 3 bots", - // effect() { - // const total = b.totalBots(); - // tech.dynamoBotCount = 0; - // tech.nailBotCount = 0; - // tech.laserBotCount = 0; - // tech.orbitBotCount = 0; - // tech.foamBotCount = 0; - // tech.boomBotCount = 0; - // tech.plasmaBotCount = 0; - // tech.missileBotCount = 0; - // for (let i = 0; i < bullet.length; i++) { - // if (bullet[i].botType) bullet[i].endCycle = 0 - // } + { + name: "pitch", + description: "oscillate the pitch of your world", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + setInterval(() => { if (!simulation.paused) ctx.rotate(0.001 * Math.sin(simulation.cycle * 0.01)) }, 16); + }, + remove() {} + }, + { + name: "umbra", + description: "produce a blue glow around everything
and probably some simulation lag", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + ctx.shadowColor = '#06f'; + ctx.shadowBlur = 25; + }, + remove() {} + }, + { + name: "lighter", + description: `ctx.globalCompositeOperation = "lighter"`, + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { + return m.fieldUpgrades[m.fieldMode].name !== "negative mass" + }, + requires: "", + effect() { + ctx.globalCompositeOperation = "lighter"; + }, + remove() {} + }, + { + name: "rewind", + description: "every 10 seconds rewind 2 seconds", + maxCount: 9, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + setInterval(() => { + m.rewind(120) + m.energy += 0.4 + }, 10000); + // for (let i = 0; i < 24; i++) { + // setTimeout(() => { m.rewind(120) }, i * 5000); + // } + }, + remove() {} + }, + { + name: "undo", + description: "every 4 seconds rewind 1/2 a second", + maxCount: 9, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + setInterval(() => { + m.rewind(30) + m.energy += 0.2 + }, 4000); + }, + remove() {} + }, + { + name: "energy to mass conversion", + description: "convert your energy into blocks", + maxCount: 9, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + for (let i = 0, len = 40; i < len; i++) { + setTimeout(() => { + m.energy -= 1 / len + const index = body.length + where = Vector.add(m.pos, { x: 400 * (Math.random() - 0.5), y: 400 * (Math.random() - 0.5) }) + spawn.bodyRect(where.x, where.y, Math.floor(15 + 100 * Math.random()), Math.floor(15 + 100 * Math.random())); + body[index].collisionFilter.category = cat.body; + body[index].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + body[index].classType = "body"; + Composite.add(engine.world, body[index]); //add to world + }, i * 100); + } - // const bots = [ - // () => { - // b.nailBot(); - // tech.nailBotCount++; - // }, - // () => { - // b.foamBot(); - // tech.foamBotCount++; - // }, - // () => { - // b.boomBot(); - // tech.boomBotCount++; - // }, - // () => { - // b.laserBot(); - // tech.laserBotCount++; - // }, - // () => { - // b.orbitBot(); - // tech.orbitBotCount++ - // }, - // () => { - // b.dynamoBot(); - // tech.dynamoBotCount++ - // } - // ] - // const index = Math.floor(Math.random() * bots.length) - // for (let i = 0; i < total; i++) bots[index]() - // }, - // remove() {} - // }, + }, + remove() {} + }, + { + name: "level.nextLevel()", + description: "advance to the next level", + maxCount: 9, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + level.nextLevel(); + }, + remove() {} + }, + { + name: "reincarnation", + description: "kill all mobs and spawn new ones
(also spawn a few extra mobs for fun)", + maxCount: 3, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + spawn.setSpawnList(); + spawn.setSpawnList(); + for (let i = 0, len = mob.length; i < len; i++) { + if (mob[i].alive && !mob[i].shield && !mob[i].isBadTarget) { + const pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; + spawn[pick](mob[i].position.x, mob[i].position.y); + if (Math.random() < 0.5) spawn[pick](mob[i].position.x, mob[i].position.y); + mob[i].death(); + } + } + }, + remove() {} + }, + { + name: "expert system", + description: "spawn a tech power up
+64% JUNK to tech pool", + maxCount: 9, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + powerUps.spawn(m.pos.x, m.pos.y, "tech"); + tech.addJunkTechToPool(0.64) + }, + remove() {} + }, + { + name: "energy investment", + description: "every 10 seconds drain your energy
return it doubled 5 seconds later", + maxCount: 9, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + setInterval(() => { + if (!simulation.paused) { + const energy = m.energy + m.energy = 0 + setTimeout(() => { //return energy + m.energy += 2 * energy + }, 5000); + } + }, 10000); + }, + remove() {} + }, + { + name: "missile launching system", + description: "fire missiles for the next 120 seconds", + maxCount: 9, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + for (let i = 0; i < 120; i++) { + setTimeout(() => { + const where = { + x: m.pos.x, + y: m.pos.y - 40 + } + b.missile(where, -Math.PI / 2 + 0.2 * (Math.random() - 0.5) * Math.sqrt(tech.missileCount), -2) + }, i * 1000); + } + }, + remove() {} + }, + { + name: "grenade production", + description: "drop a grenade every 2 seconds", + maxCount: 9, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + setInterval(() => { + if (!simulation.paused && document.visibilityState !== "hidden") { + b.grenade(Vector.add(m.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -Math.PI / 2) //fire different angles for each grenade + const who = bullet[bullet.length - 1] + Matter.Body.setVelocity(who, { + x: who.velocity.x * 0.1, + y: who.velocity.y * 0.1 + }); + } + }, 2000); + }, + remove() {} + }, // { - // name: "growth hacking", - // description: "increase combat difficulty by 1 level", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // level.difficultyIncrease(simulation.difficultyMode) - // }, - // remove() {} - // }, - // { - // name: "stun", - // description: "stun all mobs for up to 8 seconds", - // maxCount: 9, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // for (let i = 0; i < mob.length; i++) mobs.statusStun(mob[i], 480) - // }, - // remove() {} - // }, - // { - // name: "translucent", - // description: "remove your guns and spawn new ones
your bullets and bots are transparent", - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { - // for (let i = 0; i < b.inventory.length; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "gun"); - - // //removes guns and ammo - // b.inventory = []; - // b.activeGun = null; - // b.inventoryGun = 0; - // for (let i = 0, len = b.guns.length; i < len; ++i) { - // b.guns[i].have = false; - // if (b.guns[i].ammo !== Infinity) b.guns[i].ammo = 0; - // } - // simulation.makeGunHUD(); //update gun HUD - // b.bulletDraw = () => {}; - // }, - // remove() {} - // }, - // { - // name: "re-research", - // description: `eject all your ${powerUps.orb.research(1)}`, + // name: "inverted input", + // description: "left input becomes right and up input becomes down", // maxCount: 9, // count: 0, // frequency: 0, // isNonRefundable: true, + // isExperimentHide: true, // isJunk: true, // allowed() { - // return powerUps.research.count > 3 + // return true // }, - // requires: "at least 4 research", - // effect() { - // const dist = 10 * powerUps.research.count + 100 - // for (let i = 0; i < powerUps.research.count; i++) { - // powerUps.directSpawn(m.pos.x + dist * (Math.random() - 0.5), m.pos.y + dist * (Math.random() - 0.5), "research"); - // } - // powerUps.research.count = 0 - // }, - // remove() {} - // }, - // { - // name: "black hole", - // description: `use your energy and ${powerUps.orb.research(4)} to spawn
inside the event horizon of a huge black hole`, - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { - // return powerUps.research.count > 3 - // }, - // requires: "at least 4 research", - // effect() { - // m.energy = 0 - // spawn.suckerBoss(m.pos.x, m.pos.y - 700) - // powerUps.research.changeRerolls(-4) - // simulation.makeTextLog(`m.research --
${powerUps.research.count}`) - // }, - // remove() {} - // }, - // { - // name: "black hole cluster", - // description: `spawn 30 nearby black holes`, - // maxCount: 1, - // count: 0, - // frequency: 0, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, // requires: "", // effect() { - // const unit = { x: 1, y: 0 } - // for (let i = 0; i < 30; i++) { - // const where = Vector.add(m.pos, Vector.mult(Vector.rotate(unit, Math.random() * 2 * Math.PI), 2000 + 1200 * Math.random())) - // spawn.sucker(where.x, where.y, 140) - // const who = mob[mob.length - 1] - // who.locatePlayer() - // // who.damageReduction = 0.2 - // } + // const left = input.key.left + // input.key.left = input.key.right + // input.key.right = left + + // const up = input.key.up + // input.key.up = input.key.down + // input.key.down = up // }, // remove() {} // }, - // { - // name: "JUNKie", //just crashes the game - // description: "all junk", - // maxCount: 1, - // count: 0, - // frequency: 1, - // frequencyDefault: 1, - // isNonRefundable: true, - // isJunk: true, - // allowed() { return true }, - // requires: "", - // effect() { + { + name: "Sleipnir", + description: "grow more legs", + maxCount: 1, + count: 0, + frequency: 0, + isSkin: true, + isNonRefundable: true, + isJunk: true, + allowed() { return !m.isShipMode }, + requires: "", + effect() { + m.draw = function() { + ctx.fillStyle = m.fillColor; + m.walk_cycle += m.flipLegs * m.Vx; - // for (let i = 0, len = tech.tech.length; i < len; i++) { - // if (tech.tech[i].isJunk && tech.tech[i].count < tech.tech[i].maxCount) tech.tech[i].effect() - // } + //draw body + ctx.save(); + ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 + ctx.translate(m.pos.x, m.pos.y); + for (let i = 0; i < 16; i++) { + m.calcLeg(Math.PI * i / 8, -3 * i / 16) + m.drawLeg("#444") + } + ctx.rotate(m.angle); - // }, - // remove() { - // tech.tooManyTechChoices = 0 - // } - // }, + ctx.beginPath(); + ctx.arc(0, 0, 30, 0, 2 * Math.PI); + ctx.fillStyle = m.bodyGradient + ctx.fill(); + ctx.arc(15, 0, 4, 0, 2 * Math.PI); + ctx.strokeStyle = "#333"; + ctx.lineWidth = 2; + ctx.stroke(); + // ctx.beginPath(); + // ctx.arc(15, 0, 3, 0, 2 * Math.PI); + // ctx.fillStyle = '#0cf'; + // ctx.fill() + ctx.restore(); + m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal + } + }, + remove() {} + }, + { + name: "diegesis", + description: "indicate fire cooldown
through a rotation of your head", + maxCount: 1, + count: 0, + frequency: 0, + isSkin: true, + isNonRefundable: true, + isJunk: true, + allowed() { return !m.isShipMode }, + requires: "", + effect() { + m.draw = function() { + ctx.fillStyle = m.fillColor; + m.walk_cycle += m.flipLegs * m.Vx; + + ctx.save(); + ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 + ctx.translate(m.pos.x, m.pos.y); + m.calcLeg(Math.PI, -3); + m.drawLeg("#4a4a4a"); + m.calcLeg(0, 0); + m.drawLeg("#333"); + ctx.rotate(m.angle - (m.fireCDcycle != Infinity ? m.flipLegs * 0.25 * Math.pow(Math.max(m.fireCDcycle - m.cycle, 0), 0.5) : 0)); + + ctx.beginPath(); + ctx.arc(0, 0, 30, 0, 2 * Math.PI); + ctx.fillStyle = m.bodyGradient + ctx.fill(); + ctx.arc(15, 0, 4, 0, 2 * Math.PI); + ctx.strokeStyle = "#333"; + ctx.lineWidth = 2; + ctx.stroke(); + ctx.restore(); + m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal + } + }, + remove() {} + }, + { + name: "🐱", + description: "🐈", + maxCount: 1, + count: 0, + frequency: 0, + isSkin: true, + isNonRefundable: true, + isJunk: true, + allowed() { + return !m.isShipMode + }, + requires: "", + effect() { + m.draw = function() { + ctx.fillStyle = m.fillColor; + m.walk_cycle += m.flipLegs * m.Vx; + ctx.save(); + ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 + ctx.translate(m.pos.x, m.pos.y); + m.calcLeg(Math.PI, -3); + m.drawLeg("#4a4a4a"); + + + if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) { + ctx.scale(1, -1); + ctx.rotate(Math.PI); + } + ctx.beginPath(); + ctx.moveTo(-30, 0); + ctx.bezierCurveTo(-65, -75, + -5, 150 + (5 * Math.sin(simulation.cycle / 10)), + -70 + (10 * Math.sin(simulation.cycle / 10)), 0 + (10 * Math.sin(simulation.cycle / 10))); + ctx.strokeStyle = "#333"; + ctx.lineWidth = 4; + ctx.stroke(); + + if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) { + ctx.scale(1, -1); + ctx.rotate(0 - Math.PI); + } + m.calcLeg(0, 0); + m.drawLeg("#333"); + + ctx.rotate(m.angle); + if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) ctx.scale(1, -1); + ctx.beginPath(); + ctx.moveTo(5, -30); + ctx.lineTo(20, -40); + ctx.lineTo(20, -20); + ctx.lineWidth = 2; + ctx.fillStyle = "#f3f"; + ctx.fill(); + ctx.stroke(); + + ctx.beginPath(); + ctx.arc(0, 0, 30, 0, 2 * Math.PI); + ctx.fillStyle = m.bodyGradient + ctx.fill(); + ctx.stroke(); + ctx.moveTo(19, 0); + ctx.arc(15, 0, 4, Math.PI, 2 * Math.PI); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(24.3, 6, 5, Math.PI * 2, Math.PI); + ctx.stroke(); + + ctx.beginPath(); + ctx.moveTo(30, 6); + ctx.lineTo(32, 0); + ctx.lineTo(26, 0); + ctx.lineTo(30, 6); + ctx.fillStyle = "#f3f"; + ctx.fill(); + ctx.stroke(); + + ctx.restore(); + m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal + } + }, + remove() {} + }, + { + name: "transparency", + description: "become invisible to yourself
mobs can still see you", + maxCount: 1, + count: 0, + frequency: 0, + isSkin: true, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + m.draw = () => {} + }, + remove() {} + }, + { + name: "posture", + description: "stand a bit taller", + maxCount: 1, + count: 0, + frequency: 0, + isSkin: true, + isJunk: true, + allowed() { + return !m.isShipMode + }, + requires: "", + effect() { + m.yOffWhen.stand = 70 + }, + remove() { + m.yOffWhen.stand = 49 + } + }, + { + name: "rhythm", + description: "you oscillate up and down", + maxCount: 1, + count: 0, + frequency: 0, + isSkin: true, + isJunk: true, + isNonRefundable: true, + allowed() { + return !m.isShipMode + }, + requires: "", + effect() { + setInterval(() => { + m.yOffWhen.stand = 53 + 28 * Math.sin(simulation.cycle * 0.2) + if (m.onGround && !m.crouch) m.yOffGoal = m.yOffWhen.stand + }, 100); + }, + remove() {} + }, + { + name: "pareidolia", + description: "don't", + maxCount: 1, + count: 0, + frequency: 0, + isSkin: true, + isNonRefundable: true, + isJunk: true, + allowed() { + return !m.isShipMode + }, + requires: "", + effect() { + m.draw = function() { + ctx.fillStyle = m.fillColor; + m.walk_cycle += m.flipLegs * m.Vx; + ctx.save(); + ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.7 + ctx.translate(m.pos.x, m.pos.y); + m.calcLeg(Math.PI, -3); + m.drawLeg("#4a4a4a"); + m.calcLeg(0, 0); + m.drawLeg("#333"); + ctx.rotate(m.angle); + ctx.beginPath(); + ctx.arc(0, 0, 30, 0, 2 * Math.PI); + ctx.fillStyle = m.bodyGradient + ctx.fill(); + ctx.strokeStyle = "#333"; + ctx.lineWidth = 2; + if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) ctx.scale(1, -1); //here is the flip + ctx.stroke(); + ctx.beginPath(); + ctx.arc(2, -6, 7, 0, 2 * Math.PI); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(25, -6, 7, 0.25 * Math.PI, 1.6 * Math.PI); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(2, -10, 9, 1.25 * Math.PI, 1.75 * Math.PI); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(25, -10, 9, 1.25 * Math.PI, 1.4 * Math.PI); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(18, 13, 10, 0, 2 * Math.PI); + ctx.fillStyle = m.bodyGradient; + ctx.fill(); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(18, 13, 6, 0, 2 * Math.PI); + ctx.fillStyle = "#555"; + ctx.fill(); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(3, -6, 3, 0, 2 * Math.PI); + ctx.fill(); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(26, -6, 3, 0, 2 * Math.PI); + ctx.fill(); + ctx.stroke(); + ctx.restore(); + m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; + } + }, + remove() {} + }, + { + name: "prism", + description: "you cycle through different colors", + maxCount: 1, + count: 0, + frequency: 0, + isSkin: true, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + m.color = { + hue: 0, + sat: 100, + light: 50 + } + setInterval(function() { + m.color.hue++ + m.setFillColors() + }, 10); + }, + remove() {} + }, + { + name: "microtransactions", + description: `when you choose a tech you can
use ${powerUps.orb.research(1)} to buy a free in game skin`, + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + tech.isMicroTransactions = true + }, + remove() { + tech.isMicroTransactions = false + } + }, + { + name: "ship", + description: "fly around with no legs
reduce combat difficulty by 1 level", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { + return !m.isShipMode && m.fieldUpgrades[m.fieldMode].name !== "negative mass" + }, + requires: "", + effect() { + m.shipMode() + level.difficultyDecrease(simulation.difficultyMode) + }, + remove() {} + }, + { + name: "assimilation", + description: "all your bots are converted to the same random model", + maxCount: 1, + count: 0, + frequency: 0, + isBotTech: true, + isNonRefundable: true, + isJunk: true, + allowed() { + return b.totalBots() > 2 + }, + requires: "at least 3 bots", + effect() { + const total = b.totalBots(); + tech.dynamoBotCount = 0; + tech.nailBotCount = 0; + tech.laserBotCount = 0; + tech.orbitBotCount = 0; + tech.foamBotCount = 0; + tech.boomBotCount = 0; + tech.plasmaBotCount = 0; + tech.missileBotCount = 0; + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType) bullet[i].endCycle = 0 + } + + const bots = [ + () => { + b.nailBot(); + tech.nailBotCount++; + }, + () => { + b.foamBot(); + tech.foamBotCount++; + }, + () => { + b.boomBot(); + tech.boomBotCount++; + }, + () => { + b.laserBot(); + tech.laserBotCount++; + }, + () => { + b.orbitBot(); + tech.orbitBotCount++ + }, + () => { + b.dynamoBot(); + tech.dynamoBotCount++ + } + ] + const index = Math.floor(Math.random() * bots.length) + for (let i = 0; i < total; i++) bots[index]() + }, + remove() {} + }, + { + name: "growth hacking", + description: "increase combat difficulty by 1 level", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + level.difficultyIncrease(simulation.difficultyMode) + }, + remove() {} + }, + { + name: "stun", + description: "stun all mobs for up to 8 seconds", + maxCount: 9, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + for (let i = 0; i < mob.length; i++) mobs.statusStun(mob[i], 480) + }, + remove() {} + }, + { + name: "translucent", + description: "remove your guns and spawn new ones
your bullets and bots are transparent", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + for (let i = 0; i < b.inventory.length; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "gun"); + + //removes guns and ammo + b.inventory = []; + b.activeGun = null; + b.inventoryGun = 0; + for (let i = 0, len = b.guns.length; i < len; ++i) { + b.guns[i].have = false; + if (b.guns[i].ammo !== Infinity) b.guns[i].ammo = 0; + } + simulation.makeGunHUD(); //update gun HUD + b.bulletDraw = () => {}; + }, + remove() {} + }, + { + name: "re-research", + description: `eject all your ${powerUps.orb.research(1)}`, + maxCount: 9, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { + return powerUps.research.count > 3 + }, + requires: "at least 4 research", + effect() { + const dist = 10 * powerUps.research.count + 100 + for (let i = 0; i < powerUps.research.count; i++) { + powerUps.directSpawn(m.pos.x + dist * (Math.random() - 0.5), m.pos.y + dist * (Math.random() - 0.5), "research"); + } + powerUps.research.count = 0 + }, + remove() {} + }, + { + name: "black hole", + description: `use your energy and ${powerUps.orb.research(4)} to spawn
inside the event horizon of a huge black hole`, + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { + return powerUps.research.count > 3 + }, + requires: "at least 4 research", + effect() { + m.energy = 0 + spawn.suckerBoss(m.pos.x, m.pos.y - 700) + powerUps.research.changeRerolls(-4) + simulation.makeTextLog(`m.research --
${powerUps.research.count}`) + }, + remove() {} + }, + { + name: "black hole cluster", + description: `spawn 30 nearby black holes`, + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + const unit = { x: 1, y: 0 } + for (let i = 0; i < 30; i++) { + const where = Vector.add(m.pos, Vector.mult(Vector.rotate(unit, Math.random() * 2 * Math.PI), 2000 + 1200 * Math.random())) + spawn.sucker(where.x, where.y, 140) + const who = mob[mob.length - 1] + who.locatePlayer() + // who.damageReduction = 0.2 + } + }, + remove() {} + }, + { + name: "JUNKie", //just crashes the game + description: "all junk", + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + + for (let i = 0, len = tech.tech.length; i < len; i++) { + if (tech.tech[i].isJunk && tech.tech[i].count < tech.tech[i].maxCount) tech.tech[i].effect() + } + + }, + remove() { + tech.tooManyTechChoices = 0 + } + }, { name: "rule 30", maxCount: 1, diff --git a/todo.txt b/todo.txt index e58f20a..3181c93 100644 --- a/todo.txt +++ b/todo.txt @@ -1,14 +1,6 @@ ******************************************************** NEXT PATCH ************************************************** -ghoster mobs are faster -teatherBoss spawns some seekerBullets on death -added 2 more lore chapters - 7 total - -bug fixes - updated requirements text - *********************************************************** TODO *****************************************************