From cc1bbeb53b586dbac0d1fad9520a080b290561ea Mon Sep 17 00:00:00 2001 From: landgreen Date: Sun, 28 Aug 2022 19:47:32 -0700 Subject: [PATCH] shotgun rivets some shotgun ammo tech upgrades will continue to fire some original recipe shotgun bullets rivets, fleas, worms, iceIX tech: band gap - boosts give more damage but it lasts for 1 less second WIMPs are 10% faster controlled explosion renamed shaped charge bug fixes construction mode works better with my buttons to unlock run this and press T to enter testing mode simulation.enableConstructMode() //used to build maps in testing mode removed -experiment- tech because it's function was reproduced by "tech - tinker" --- js/bullet.js | 90 ++++----- js/engine.js | 1 - js/index.js | 20 +- js/level.js | 29 ++- js/mob.js | 14 +- js/player.js | 16 +- js/powerup.js | 12 +- js/simulation.js | 22 ++- js/spawn.js | 191 +++++++++++++++++-- js/tech.js | 463 ++++++++++++++++++++++------------------------- todo.txt | 45 +++-- 11 files changed, 525 insertions(+), 378 deletions(-) diff --git a/js/bullet.js b/js/bullet.js index 8d04cbc..8d5bd5d 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -1926,7 +1926,7 @@ const b = { if (tech.isMissileBig) { size *= 1.55 if (tech.isMissileBiggest) { - size *= 2 + size *= 1.55 } } @@ -2015,7 +2015,7 @@ const b = { ctx.fill(); }, }); - const thrust = 0.0066 * bullet[me].mass * (tech.isMissileBig ? (tech.isMissileBiggest ? 0.15 : 0.7) : 1); + const thrust = 0.0066 * bullet[me].mass * (tech.isMissileBig ? (tech.isMissileBiggest ? 0.3 : 0.7) : 1); Matter.Body.setVelocity(bullet[me], { x: m.Vx / 2 + speed * Math.cos(angle), y: m.Vy / 2 + speed * Math.sin(angle) @@ -5463,16 +5463,40 @@ const b = { player.force.y -= knock * Math.sin(m.angle) * 0.5 //reduce knock back in vertical direction to stop super jumps } + const spray = (num) => { + const side = 22 + for (let i = 0; i < num; i++) { + const me = bullet.length; + const dir = m.angle + (Math.random() - 0.5) * spread + bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle) + 15 * (Math.random() - 0.5), m.pos.y + 35 * Math.sin(m.angle) + 15 * (Math.random() - 0.5), side, side, b.fireAttributes(dir)); + Composite.add(engine.world, bullet[me]); //add bullet to world + const SPEED = 52 + Math.random() * 8 + Matter.Body.setVelocity(bullet[me], { + x: SPEED * Math.cos(dir), + y: SPEED * Math.sin(dir) + }); + bullet[me].endCycle = simulation.cycle + 40 * tech.isBulletsLastLonger + bullet[me].minDmgSpeed = 15 + if (tech.isShotgunReversed) Matter.Body.setDensity(bullet[me], 0.0015) + // bullet[me].restitution = 0.4 + bullet[me].frictionAir = 0.034; + bullet[me].do = function() { + const scale = 1 - 0.034 / tech.isBulletsLastLonger + Matter.Body.scale(this, scale, scale); + }; + } + } + b.muzzleFlash(35); if (tech.isRivets) { const me = bullet.length; // const dir = m.angle + 0.02 * (Math.random() - 0.5) - bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle), m.pos.y + 35 * Math.sin(m.angle), 60 * tech.bulletSize, 27 * tech.bulletSize, b.fireAttributes(m.angle)); + bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle), m.pos.y + 35 * Math.sin(m.angle), 56 * tech.bulletSize, 25 * tech.bulletSize, b.fireAttributes(m.angle)); - Matter.Body.setDensity(bullet[me], 0.007 * (tech.isShotgunReversed ? 1.6 : 1)); + Matter.Body.setDensity(bullet[me], 0.005 * (tech.isShotgunReversed ? 1.5 : 1)); Composite.add(engine.world, bullet[me]); //add bullet to world - const SPEED = (input.down ? 50 : 37) + const SPEED = (input.down ? 50 : 43) Matter.Body.setVelocity(bullet[me], { x: SPEED * Math.cos(m.angle), y: SPEED * Math.sin(m.angle) @@ -5480,7 +5504,7 @@ const b = { if (tech.isIncendiary) { bullet[me].endCycle = simulation.cycle + 60 bullet[me].onEnd = function() { - b.explosion(this.position, 300 + (Math.random() - 0.5) * 60); //makes bullet do explosive damage at end + b.explosion(this.position, 360 + (Math.random() - 0.5) * 60); //makes bullet do explosive damage at end } bullet[me].beforeDmg = function() { this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion @@ -5490,10 +5514,10 @@ const b = { } bullet[me].minDmgSpeed = 7 // bullet[me].restitution = 0.4 - bullet[me].frictionAir = 0.006; + bullet[me].frictionAir = 0.004; bullet[me].turnMag = 0.04 * Math.pow(tech.bulletSize, 3.75) bullet[me].do = function() { - this.force.y += this.mass * 0.0022 + this.force.y += this.mass * 0.002 if (this.speed > 6) { //rotates bullet to face current velocity? const facing = { x: Math.cos(this.angle), y: Math.sin(this.angle) } if (Vector.cross(Vector.normalise(this.velocity), facing) < 0) { @@ -5512,9 +5536,11 @@ const b = { b.targetedNail(this.position, 6 * tech.fragments * tech.bulletSize) this.endCycle = 0 //triggers despawn } + if (tech.isIncendiary) this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion if (tech.isCritKill) b.crit(who, this) } } + spray(12); //fires normal shotgun bullets } else if (tech.isIncendiary) { spread *= 0.15 const END = Math.floor(input.down ? 10 : 7); @@ -5534,7 +5560,7 @@ const b = { y: speed * Math.sin(dirOff) }); bullet[me].onEnd = function() { - b.explosion(this.position, 150 * (tech.isShotgunReversed ? 1.5 : 1) + (Math.random() - 0.5) * 40); //makes bullet do explosive damage at end + b.explosion(this.position, 150 * (tech.isShotgunReversed ? 1.4 : 1) + (Math.random() - 0.5) * 40); //makes bullet do explosive damage at end } bullet[me].beforeDmg = function() { this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion @@ -5546,7 +5572,7 @@ const b = { } } else if (tech.isNailShot) { spread *= 0.65 - const dmg = 2 * (tech.isShotgunReversed ? 1.6 : 1) + const dmg = 2 * (tech.isShotgunReversed ? 1.5 : 1) if (input.down) { for (let i = 0; i < 17; i++) { speed = 38 + 15 * Math.random() @@ -5576,47 +5602,49 @@ const b = { } } else if (tech.isSporeFlea) { const where = { x: m.pos.x + 35 * Math.cos(m.angle), y: m.pos.y + 35 * Math.sin(m.angle) } - const number = 4 * (tech.isShotgunReversed ? 1.6 : 1) + const number = 2 * (tech.isShotgunReversed ? 1.5 : 1) for (let i = 0; i < number; i++) { const angle = m.angle + 0.2 * (Math.random() - 0.5) - const speed = (input.down ? 33 : 20) * (1 + 0.1 * Math.random()) + const speed = (input.down ? 35 * (1 + 0.05 * Math.random()) : 30 * (1 + 0.15 * Math.random())) b.flea(where, { x: speed * Math.cos(angle), y: speed * Math.sin(angle) }) bullet[bullet.length - 1].setDamage() } + spray(10); //fires normal shotgun bullets } else if (tech.isSporeWorm) { const where = { x: m.pos.x + 35 * Math.cos(m.angle), y: m.pos.y + 35 * Math.sin(m.angle) } const spread = (input.down ? 0.02 : 0.07) - const number = 4 * (tech.isShotgunReversed ? 1.6 : 1) + const number = 3 * (tech.isShotgunReversed ? 1.5 : 1) let angle = m.angle - (number - 1) * spread * 0.5 for (let i = 0; i < number; i++) { b.worm(where) - const SPEED = (8 + 10 * input.down) * (1 + 0.15 * Math.random()) + const SPEED = (30 + 10 * input.down) * (1 + 0.2 * Math.random()) Matter.Body.setVelocity(bullet[bullet.length - 1], { x: player.velocity.x * 0.5 + SPEED * Math.cos(angle), y: player.velocity.y * 0.5 + SPEED * Math.sin(angle) }); angle += spread } + spray(7); //fires normal shotgun bullets } else if (tech.isIceShot) { const spread = (input.down ? 0.7 : 1.2) - for (let i = 0, len = 16 * (tech.isShotgunReversed ? 1.6 : 1); i < len; i++) { - // iceIX(speed = 0, dir = m.angle + Math.PI * 2 * Math.random(), where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }) { - b.iceIX(25 + 20 * Math.random(), m.angle + spread * (Math.random() - 0.5)) + for (let i = 0, len = 10 * (tech.isShotgunReversed ? 1.5 : 1); i < len; i++) { + b.iceIX(23 + 10 * Math.random(), m.angle + spread * (Math.random() - 0.5)) } + spray(10); //fires normal shotgun bullets } else if (tech.isFoamShot) { const spread = (input.down ? 0.15 : 0.4) const where = { x: m.pos.x + 25 * Math.cos(m.angle), y: m.pos.y + 25 * Math.sin(m.angle) } - const number = 16 * (tech.isShotgunReversed ? 1.6 : 1) + const number = 16 * (tech.isShotgunReversed ? 1.5 : 1) for (let i = 0; i < number; i++) { - const SPEED = 11 + 4 * Math.random(); + const SPEED = 13 + 4 * Math.random(); const angle = m.angle + spread * (Math.random() - 0.5) b.foam(where, { x: SPEED * Math.cos(angle), y: SPEED * Math.sin(angle) }, 8 + 7 * Math.random()) } } else if (tech.isNeedles) { - const number = 9 * (tech.isShotgunReversed ? 1.6 : 1) + const number = 9 * (tech.isShotgunReversed ? 1.5 : 1) const spread = (input.down ? 0.03 : 0.05) let angle = m.angle - (number - 1) * spread * 0.5 for (let i = 0; i < number; i++) { @@ -5624,27 +5652,7 @@ const b = { angle += spread } } else { - const side = 22 - for (let i = 0; i < 17; i++) { - const me = bullet.length; - const dir = m.angle + (Math.random() - 0.5) * spread - bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle) + 15 * (Math.random() - 0.5), m.pos.y + 35 * Math.sin(m.angle) + 15 * (Math.random() - 0.5), side, side, b.fireAttributes(dir)); - Composite.add(engine.world, bullet[me]); //add bullet to world - const SPEED = 52 + Math.random() * 8 - Matter.Body.setVelocity(bullet[me], { - x: SPEED * Math.cos(dir), - y: SPEED * Math.sin(dir) - }); - bullet[me].endCycle = simulation.cycle + 40 * tech.isBulletsLastLonger - bullet[me].minDmgSpeed = 15 - if (tech.isShotgunReversed) Matter.Body.setDensity(bullet[me], 0.0016) - // bullet[me].restitution = 0.4 - bullet[me].frictionAir = 0.034; - bullet[me].do = function() { - const scale = 1 - 0.034 / tech.isBulletsLastLonger - Matter.Body.scale(this, scale, scale); - }; - } + spray(16); //fires normal shotgun bullets } } }, { diff --git a/js/engine.js b/js/engine.js index 399ce79..3a0e8c4 100644 --- a/js/engine.js +++ b/js/engine.js @@ -208,7 +208,6 @@ function collisionChecks(event) { const v = Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)); if (v > 9) { if (tech.blockDmg) { //electricity - // console.log("hi") Matter.Body.setVelocity(mob[k], { x: 0.5 * mob[k].velocity.x, y: 0.5 * mob[k].velocity.y }); if (tech.isBlockRadiation && !mob[k].isShielded && !mob[k].isMobBullet) { mobs.statusDoT(mob[k], tech.blockDmg * m.dmgScale * 4 / 12, 360) //200% increase -> x (1+2) //over 7s -> 360/30 = 12 half seconds -> 3/12 diff --git a/js/index.js b/js/index.js index 52c9f9e..e00e897 100644 --- a/js/index.js +++ b/js/index.js @@ -431,7 +431,7 @@ ${simulation.isCheating ? "

lore disabled": ""} //update tech text //disable not allowed tech for (let i = 0, len = tech.tech.length; i < len; i++) { const techID = document.getElementById("tech-" + i) - if (!tech.tech[i].isExperimentHide && !tech.tech[i].isNonRefundable && (!tech.tech[i].isJunk || tech.tech[i].isExperimentalMode || localSettings.isJunkExperiment)) { + if (!tech.tech[i].isExperimentHide && !tech.tech[i].isNonRefundable && (!tech.tech[i].isJunk || localSettings.isJunkExperiment)) { if (tech.tech[i].allowed() || isAllowed || tech.tech[i].count > 0) { const techCountText = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""; //
@@ -460,8 +460,6 @@ ${simulation.isCheating ? "

lore disabled": ""} ` } else if (tech.tech[i].isJunk) { techID.innerHTML = `
  ${tech.tech[i].link} ${techCountText}
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}` - } else if (tech.tech[i].isExperimentalMode) { - techID.innerHTML = `
${tech.tech[i].name}
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}` } else { techID.innerHTML = `
  ${tech.tech[i].link} ${techCountText}
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}` } @@ -531,11 +529,9 @@ ${simulation.isCheating ? "

lore disabled": ""} text += `
  ${build.nameLink(b.guns[i].name)}
${b.guns[i].description}
` } for (let i = 0, len = tech.tech.length; i < len; i++) { - if (!tech.tech[i].isExperimentHide && (!tech.tech[i].isJunk || localSettings.isJunkExperiment)) { //&& (!tech.tech[i].isNonRefundable || tech.tech[i].isExperimentalMode)) { - if (tech.tech[i].allowed() && (!tech.tech[i].isNonRefundable || tech.tech[i].isExperimentalMode || localSettings.isJunkExperiment)) { // || tech.tech[i].name === "+1 cardinality") { //|| tech.tech[i].name === "leveraged investment" - if (tech.tech[i].isExperimentalMode) { - text += `
${tech.tech[i].name}
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}
` - } else if (tech.tech[i].isJunk) { + if (!tech.tech[i].isExperimentHide && (!tech.tech[i].isJunk || localSettings.isJunkExperiment)) { //&& (!tech.tech[i].isNonRefundable)) { + if (tech.tech[i].allowed() && (!tech.tech[i].isNonRefundable || localSettings.isJunkExperiment)) { // || tech.tech[i].name === "+1 cardinality") { //|| tech.tech[i].name === "leveraged investment" + if (tech.tech[i].isJunk) { text += `
  ${tech.tech[i].link}
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}
` } else { text += `
  ${tech.tech[i].link}
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}
` @@ -668,13 +664,7 @@ ${simulation.isCheating ? "

lore disabled": ""} build.hasExperimentalMode = false if (!simulation.isCheating) { for (let i = 0, len = tech.tech.length; i < len; i++) { - if (tech.tech[i].count > 0) { - if (tech.tech[i].isExperimentalMode) { - build.hasExperimentalMode = true - } else if (!tech.tech[i].isLore) { - simulation.isCheating = true; - } - } + if (tech.tech[i].count > 0 && !tech.tech[i].isLore) simulation.isCheating = true; } if (b.inventory.length !== 0 || m.fieldMode !== 0) simulation.isCheating = true; } diff --git a/js/level.js b/js/level.js index 6672ef0..61b4b3f 100644 --- a/js/level.js +++ b/js/level.js @@ -16,7 +16,7 @@ const level = { start() { if (level.levelsCleared === 0) { //this code only runs on the first level // simulation.enableConstructMode() //used to build maps in testing mode - // level.difficultyIncrease(3 * 4) //30 is near max on hard //60 is near max on why + // level.difficultyIncrease(10 * 4) //30 is near max on hard //60 is near max on why // simulation.isHorizontalFlipped = true // m.maxHealth = m.health = 100 // tech.isRerollDamage = true @@ -24,9 +24,11 @@ const level = { // m.immuneCycle = Infinity //you can't take damage // tech.tech[297].frequency = 100 // m.setField("metamaterial cloaking") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass - // b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 matter wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser + // b.giveGuns("shotgun") //0 nail gun 1 shotgun 2 super balls 3 matter wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.guns[0].ammo = 1000000 - // tech.giveTech("1st ionization energy") + // tech.giveTech("rivet gun") + // tech.isFoamShot = true + // tech.isIncendiary = true // for (let i = 0; i < 1; ++i) tech.giveTech("field coupling") // for (let i = 0; i < 1; ++i) tech.giveTech("free-electron laser") // m.damage(0.1); @@ -36,10 +38,10 @@ const level = { // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); // spawn.starter(1900, -500, 200) - // spawn.beetleBoss(1900, -400) - // spawn.shooter(1900, -500) - // for (let i = 0; i < 15; ++i) spawn.starter(1900 + 300 * Math.random(), -500 + 300 * Math.random()) + // spawn.ghoster(2538, -1950) + // for (let i = 0; i < 15; ++i) spawn.shooter(1900 + 300 * Math.random(), -500 + 300 * Math.random()) // level.testing(); + // spawn.blowSuckBoss(1900, -500) // for (let i = 0; i < 7; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research"); // for (let i = 0; i < 4; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech"); @@ -114,7 +116,6 @@ const level = { spawn.WIMP() for (let j = 0, len = 5; j < len; j++) powerUps.spawn(level.exit.x + 100 * (Math.random() - 0.5), level.exit.y - 100 + 100 * (Math.random() - 0.5), "research", false) } - for (let i = 0; i < tech.wimpExperiment; i++) spawn.WIMP() // if (tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) { if ((tech.isRelay || tech.isFlipFlop) && !tech.isFlipFlopOn) { tech.isFlipFlopOn = true @@ -2809,6 +2810,17 @@ const level = { spawn.mapRect(5300, -275, 50, 175); spawn.mapRect(5050, -100, 50, 150); spawn.mapRect(4850, -275, 50, 175); + spawn.mapRect(-950, -3250, 850, 1750); + //roof + spawn.mapRect(-175, -2975, 300, 1425); + spawn.mapRect(75, -2650, 325, 1150); + spawn.mapRect(375, -2225, 250, 650); + spawn.mapRect(4075, -2125, 700, 800); + spawn.mapRect(4450, -2950, 675, 1550); + spawn.mapRect(4875, -3625, 725, 2225); + spawn.mapRect(5525, -4350, 1725, 2925); + spawn.mapRect(7200, -5125, 300, 3900); + //??? // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why @@ -10926,9 +10938,6 @@ const level = { simulation.fallHeight = -1000; simulation.setZoom(1800); templePlayer.startAnim = -1; - for (let i = 0; i < tech.wimpCount + tech.wimpExperiment; i++) { - addWIMP(); - } templePlayer.drawExit = false; } }, diff --git a/js/mob.js b/js/mob.js index d5148e3..ab66ec0 100644 --- a/js/mob.js +++ b/js/mob.js @@ -899,7 +899,7 @@ const mobs = { //accelerate towards the searchTarget if (!this.seePlayer.recall) { const newTarget = function(that) { - if (Math.random() < 0.0005) { + if (Math.random() < 0.0007) { that.searchTarget = player.position; //chance to target player } else { //target random body @@ -1246,18 +1246,6 @@ const mobs = { } } } - if (tech.removeMaxHealthOnKill) { - const amount = 0.002 - if (tech.isEnergyHealth) { - if (m.maxEnergy > amount) { - tech.healMaxEnergyBonus -= amount - m.setMaxEnergy(); - } - } else if (m.maxHealth > amount) { - tech.extraMaxHealth -= amount //decrease max health - m.setMaxHealth(); - } - } if (tech.cloakDuplication && !this.isBoss) { tech.cloakDuplication -= 0.02 powerUps.setDupChance(); //needed after adjusting duplication chance diff --git a/js/player.js b/js/player.js index 7db4cb1..d81de84 100644 --- a/js/player.js +++ b/js/player.js @@ -1571,24 +1571,24 @@ const m = { case 0: //field emitter return `gain the effects of all fields` case 1: //standing wave - return `deflecting condenses +${Math.ceil(couple)} ice IX` + return `deflecting condenses +${couple.toFixed(1)} ice IX` case 2: //perfect diamagnetism - return `deflecting condenses +${Math.ceil(couple)} ice IX` + return `deflecting condenses +${couple.toFixed(1)} ice IX` // return `invulnerable +${2*couple} seconds post collision` case 3: //negative mass return `+${((1-0.73 ** couple)*100).toFixed(1)}% defense` case 4: //assembler - return `generate ${6*couple} energy per second` + return `generate ${(6*couple).toFixed(0)} energy per second` case 5: //plasma - return `+${15*couple} damage` + return `+${(15*couple).toFixed(0)}% damage` case 6: //time dilation - return `+${25*couple}% longer stopped time` //movement, jumping, and + return `+${(25*couple).toFixed(0)}% longer stopped time` //movement, jumping, and case 7: //cloaking - return `+${33*couple}% ambush damage` + return `+${(33*couple).toFixed(0)}% ambush damage` case 8: //pilot wave - return `+${40*couple}% block collision damage` + return `+${(40*couple).toFixed(0)}% block collision damage` case 9: //wormhole - return `after eating blocks +${20*couple} energy` + return `after eating blocks +${(20*couple).toFixed(0)} energy` } }, couplingChange() { diff --git a/js/powerup.js b/js/powerup.js index 57e32d9..5552c04 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -333,7 +333,7 @@ const powerUps = { }, endDraft(type, isCanceled = false) { //type should be a gun, tech, or field if (isCanceled) { - if (tech.isCancelTech && Math.random() < 0.9) { + if (tech.isCancelTech && Math.random() < 0.88) { // powerUps.research.use('tech') powerUps[type].effect(); return @@ -414,8 +414,8 @@ const powerUps = { return 11; }, endCycle: 0, - duration: 600, - damage: 1.5, + duration: null, //set by "tech: band gap" + damage: null, //set by "tech: band gap" effect() { powerUps.boost.endCycle = m.cycle + Math.floor(Math.max(0, powerUps.boost.endCycle - m.cycle) * 0.6) + powerUps.boost.duration //duration+seconds plus 2/3 of current time left }, @@ -912,7 +912,7 @@ const powerUps = { } function removeOption(index) { - for (let i = options.length; i > -1; i--) { + for (let i = options.length - 1; i > -1; i--) { if (index === options[i]) { options.splice(i, 1) //remove all copies of that option form the options array (some tech are in the options array multiple times because of frequency) optionLengthNoDuplicates-- @@ -1272,9 +1272,11 @@ const powerUps = { } if (tech.isCouplingPowerUps && Math.random() < 0.17) { powerUps.spawn(x, y, "coupling"); + return; } - if (tech.isBoostPowerUps && Math.random() < 0.17) { + if (tech.isBoostPowerUps && Math.random() < 0.18) { powerUps.spawn(x, y, "boost"); + return; } // if (Math.random() < 0.01) { // powerUps.spawn(x, y, "research"); diff --git a/js/simulation.js b/js/simulation.js index d2427b2..77554cf 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -1458,21 +1458,22 @@ const simulation = { const y = round(simulation.constructMouseDownPosition.y) const dx = Math.max(25, round(simulation.mouseInGame.x) - x) const dy = Math.max(25, round(simulation.mouseInGame.y) - y) - - if (e.button === 2) { + console.log(e.button) + if (e.button === 1) { if (level.isProcedural) { - simulation.outputMapString(`spawn.randomMob(x+${x}, y+${y}, 0);`); + simulation.outputMapString(`spawn.randomMob(x+${x}, y+${y}, 0);\n`); } else { - simulation.outputMapString(`spawn.randomMob(${x}, ${y}, 0);`); + simulation.outputMapString(`spawn.randomMob(${x}, ${y}, 0);\n`); } } else if (e.button === 4) { simulation.outputMapString(`${Math.floor(simulation.constructMouseDownPosition.x)}, ${Math.floor(simulation.constructMouseDownPosition.y)}`); } else if (simulation.mouseInGame.x > simulation.constructMouseDownPosition.x && simulation.mouseInGame.y > simulation.constructMouseDownPosition.y) { //make sure that the width and height are positive - if (e.button === 1) { //add map + + if (e.button === 0) { //add map if (level.isProcedural) { - simulation.outputMapString(`spawn.mapRect(x+${x}, y+${y}, ${dx}, ${dy});`); + simulation.outputMapString(`spawn.mapRect(x+${x}, y+${y}, ${dx}, ${dy});\n`); } else { - simulation.outputMapString(`spawn.mapRect(${x}, ${y}, ${dx}, ${dy});`); + simulation.outputMapString(`spawn.mapRect(${x}, ${y}, ${dx}, ${dy});\n`); } //see map in world @@ -1484,11 +1485,11 @@ const simulation = { Composite.add(engine.world, map[len]); //add to world simulation.draw.setPaths() //update map graphics - } else if (e.button === 3) { //add body + } else if (e.button === 2) { //add body if (level.isProcedural) { - simulation.outputMapString(`spawn.bodyRect(x+${x}, y+${y}, ${dx}, ${dy});`); + simulation.outputMapString(`spawn.bodyRect(x+${x}, y+${y}, ${dx}, ${dy});\n`); } else { - simulation.outputMapString(`spawn.bodyRect(${x}, ${y}, ${dx}, ${dy});`); + simulation.outputMapString(`spawn.bodyRect(${x}, ${y}, ${dx}, ${dy});\n`); } //see map in world @@ -1513,6 +1514,7 @@ const simulation = { } }); + //undo last element added after you press z document.body.addEventListener("keydown", (e) => { // e.keyCode z=90 m=77 b=66 shift = 16 c = 67 if (simulation.testing && e.keyCode === 90 && simulation.constructMapString.length) { if (simulation.constructMapString[simulation.constructMapString.length - 1][6] === 'm') { //remove map from current level diff --git a/js/spawn.js b/js/spawn.js index 081a24d..4814e70 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -5,8 +5,8 @@ const spawn = { randomBossList: [ "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "powerUpBossBaby", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", - "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss", "shieldingBoss", "timeSkipBoss", - "dragonFlyBoss", "beetleBoss" + "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss", "shieldingBoss", + "timeSkipBoss", "dragonFlyBoss", "beetleBoss" ], bossTypeSpawnOrder: [], //preset list of boss names calculated at the start of a run by the randomSeed bossTypeSpawnIndex: 0, //increases as the boss type cycles @@ -142,7 +142,7 @@ const spawn = { const pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; spawn[pick](x, y); } - if (tech.isMoreMobs || (tech.isDuplicateBoss && Math.random() < tech.duplicationChance())) { + if (tech.isDuplicateBoss && Math.random() < tech.duplicationChance()) { const pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; spawn[pick](x, y); } @@ -158,7 +158,7 @@ const spawn = { spawn[pick](x + Math.round((Math.random() - 0.5) * 20) + i * size * 2.5, y + Math.round((Math.random() - 0.5) * 20), size); } } - if (tech.isMoreMobs || (tech.isDuplicateBoss && Math.random() < tech.duplicationChance())) { + if (tech.isDuplicateBoss && Math.random() < tech.duplicationChance()) { for (let i = 0; i < num; ++i) { const pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; spawn[pick](x + Math.round((Math.random() - 0.5) * 20) + i * size * 2.5, y + Math.round((Math.random() - 0.5) * 20), size); @@ -296,7 +296,7 @@ const spawn = { me.showHealthBar = false; me.collisionFilter.category = 0; me.collisionFilter.mask = 0; //cat.player //| cat.body - me.chaseSpeed = 1 + 2 * Math.random() + me.chaseSpeed = 1.2 + 2 * Math.random() me.awake = function() { //chase player @@ -4104,8 +4104,8 @@ const spawn = { if (this.phaseCycle > -1) { Matter.Body.rotate(this, 0.02) for (let i = 0, len = this.vertices.length; i < len; i++) { //fire a bullet from each vertex - spawn.sniperBullet(this.vertices[i].x, this.vertices[i].y, 6, 4); - const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[i])), -17) + spawn.sniperBullet(this.vertices[i].x, this.vertices[i].y, 5, 4); + const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[i])), -15) Matter.Body.setVelocity(mob[mob.length - 1], { x: velocity.x, y: velocity.y @@ -5013,13 +5013,13 @@ const spawn = { }, 2000); //add in a delay in case the level gets flipped left right me.isBoss = true; - Matter.Body.setDensity(me, 0.01 + 0.0003 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger + Matter.Body.setDensity(me, 0.01 + 0.0004 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front me.isVerticesChange = true me.memory = 240; - me.fireFreq = 0.025; + me.fireFreq = 0.009 + 0.0004 * Math.min(40, simulation.difficulty); //bigger number means more shots per second me.noseLength = 0; me.fireAngle = 0; me.accelMag = 0.005 * simulation.accelScale; @@ -5066,16 +5066,14 @@ const spawn = { //fire for (let i = 0, len = 2 + 0.07 * simulation.difficulty; i < len; i++) { spawn.bullet(this.vertices[1].x, this.vertices[1].y, 7 + Math.ceil(this.radius / 25)); - const v = 15; - Matter.Body.setVelocity(mob[mob.length - 1], { - x: this.velocity.x + this.fireDir.x * v + 7 * Math.random(), - y: this.velocity.y + this.fireDir.y * v + 7 * Math.random() - }); + const spread = Vector.rotate({ + x: Math.sqrt(len) + 4, + y: 0 + }, 2 * Math.PI * Math.random()) + const dir = Vector.add(Vector.mult(this.fireDir, 15), spread) + Matter.Body.setVelocity(mob[mob.length - 1], dir); } this.noseLength = 0; - // recoil - this.force.x -= 0.005 * this.fireDir.x * this.mass; - this.force.y -= 0.005 * this.fireDir.y * this.mass; } if (this.noseLength < 1.5) this.noseLength += this.fireFreq; setNoseShape(); @@ -5421,6 +5419,163 @@ const spawn = { } }; }, + // blowSuckBoss(x, y, radius = 80) { + // mobs.spawn(x, y, 10, radius, "transparent"); + // let me = mob[mob.length - 1]; + // me.isBoss = true; + // Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger + // me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) + + // me.fireFreq = Math.floor(60 * simulation.CDScale) + // me.seePlayerFreq = 15 + // me.seeAtDistance2 = 300000; + // me.accelMag = 0.0003 * simulation.accelScale; + // if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search + // // Matter.Body.setDensity(me, 0.001); //normal is 0.001 //makes effective life much lower + // me.stroke = "transparent"; //used for drawGhost + // me.alpha = 1; //used in drawGhost + // me.canTouchPlayer = false; //used in drawGhost + // me.isBadTarget = true; + // // me.leaveBody = false; + // me.collisionFilter.mask = cat.bullet //| cat.body + // me.showHealthBar = false; + // me.memory = 480; + // me.onDeath = function() { + // powerUps.spawnBossPowerUp(this.position.x, this.position.y) + // }; + // me.onDamage = function() {}; + // me.suck = function() { + // for (let i = 0; i < mob.length; i++) { + // if (mob[i].isBlowSuckBullet) { + // const unit = Vector.normalise(Vector.sub(this.position, mob[i].position)) + // const mag = Vector.mult(unit, 0.0008 * mob[i].mass) + // mob[i].force.x += mag.x + // mob[i].force.y += mag.y + // } + // } + // } + // me.do = function() { + // //cap max speed + // if (this.speed > 8) { + // Matter.Body.setVelocity(this, { + // x: this.velocity.x * 0.8, + // y: this.velocity.y * 0.8 + // }); + // } + // this.seePlayerCheckByDistance(); + // this.checkStatus(); + // this.attraction(); + // this.search(); + // //draw + // if (this.distanceToPlayer2() < this.seeAtDistance2) { + // if (this.alpha < 1) this.alpha += 0.005 * simulation.CDScale; //near player go solid + // } else { + // if (this.alpha > 0) this.alpha -= 0.05; ///away from player, hide + // } + // if (this.alpha > 0) { + // if (this.alpha > 0.8 && this.seePlayer.recall) { + // this.healthBar(); + // if (!this.canTouchPlayer) { + // this.canTouchPlayer = true; + // this.isBadTarget = false; + // this.collisionFilter.mask = cat.player | cat.bullet + // } + // } + // //draw body + // ctx.beginPath(); + // const vertices = this.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.lineWidth = 1; + // ctx.fillStyle = `rgba(255,255,255,${this.alpha * this.alpha})`; + // ctx.fill(); + + + // this.suck(); + // if (this.seePlayer.recall && !(simulation.cycle % this.fireFreq)) { + // this.suckCount = 0; + // Matter.Body.setAngularVelocity(this, 0.11) + // //fire a bullet from each vertex + // for (let i = 0, len = this.vertices.length; i < len; i++) { + // spawn.bounceBullet(this.vertices[i].x, this.vertices[i].y, 8) + // //give the bullet a rotational velocity as if they were attached to a vertex + // const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[i]))), -16) + // const who = mob[mob.length - 1] + // who.isBlowSuckBullet = true + // Matter.Body.setVelocity(who, { + // x: this.velocity.x + velocity.x, + // y: this.velocity.y + velocity.y + // }); + // } + // } + + + // } else if (this.canTouchPlayer) { + // this.canTouchPlayer = false; + // this.isBadTarget = true; + // this.collisionFilter.mask = cat.bullet; //can't touch player or walls + // } + // }; + // }, + // blowSuckBoss(x, y, radius = 80, isSpawnBossPowerUp = true) { + // mobs.spawn(x, y, 10, radius, "transparent"); //rgb(60,60,85) + // let me = mob[mob.length - 1]; + // me.isBoss = true; + // Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger + // me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) + + // me.accelMag = 0.0001 * simulation.accelScale; + // me.fireFreq = Math.floor(180 * simulation.CDScale) + // me.frictionStatic = 0; + // me.friction = 0; + // me.frictionAir = 0.005; + // me.memory = 420; + // me.repulsionRange = 1000000; //squared + // // spawn.shield(me, x, y, 1); + // // spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random()) + + // me.onDeath = function() { + // if (isSpawnBossPowerUp) powerUps.spawnBossPowerUp(this.position.x, this.position.y) + // }; + // me.onDamage = function() {}; + // me.suck = function() { + // for (let i = 0; i < mob.length; i++) { + // if (mob[i].isBlowSuckBullet) { + // const unit = Vector.normalise(Vector.sub(this.position, mob[i].position)) + // const mag = Vector.mult(unit, 0.0008 * mob[i].mass) + // mob[i].force.x += mag.x + // mob[i].force.y += mag.y + // } + // } + // } + // me.do = function() { + // this.seePlayerCheck(); + // this.checkStatus(); + // this.attraction(); + // // this.repulsion(); + // this.suck(); + + // if (this.seePlayer.recall && !(simulation.cycle % this.fireFreq)) { + // this.suckCount = 0; + // Matter.Body.setAngularVelocity(this, 0.11) + // //fire a bullet from each vertex + // for (let i = 0, len = this.vertices.length; i < len; i++) { + // spawn.bounceBullet(this.vertices[i].x, this.vertices[i].y, 8) + // //give the bullet a rotational velocity as if they were attached to a vertex + // const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[i]))), -16) + // const who = mob[mob.length - 1] + // who.isBlowSuckBullet = true + // Matter.Body.setVelocity(who, { + // x: this.velocity.x + velocity.x, + // y: this.velocity.y + velocity.y + // }); + // } + // } + // }; + // }, grenadierBoss(x, y, radius = 95) { mobs.spawn(x, y, 6, radius, "rgb(0,235,255)"); let me = mob[mob.length - 1]; @@ -6192,7 +6347,7 @@ const spawn = { mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)"); let me = mob[mob.length - 1]; me.collisionFilter.mask = cat.bullet | cat.player //| cat.mob //| cat.body - me.damageReduction = 0.021 + me.damageReduction = 0.024 Matter.Body.setDensity(me, 0.0001); //normal is 0.001 // me.accelMag = 0.0007 * simulation.accelScale; diff --git a/js/tech.js b/js/tech.js index b88ea79..29260a1 100644 --- a/js/tech.js +++ b/js/tech.js @@ -2227,7 +2227,7 @@ const tech = { name: "1st ionization energy", link: `1st ionization energy`, description: `after you collect ${powerUps.orb.heal()}
+10 maximum energy`, - description: `convert ${powerUps.orb.heal()} into

give +10 maximum energy`, + description: `convert current and future ${powerUps.orb.heal()} into

give +10 maximum energy`, maxCount: 1, count: 0, frequency: 2, @@ -3240,7 +3240,8 @@ const tech = { }, { name: "abiogenesis", - description: `at the start of a level spawn a 2nd boss
use ${powerUps.orb.research(4)}or add 49% JUNK to the tech pool`, + description: `use ${powerUps.orb.research(4)} (or 49% JUNK to the tech pool if you can't) to add a 2nd boss to each level`, + description: `as a level begins spawn a 2nd boss using ${powerUps.orb.research(4)}
(+49% JUNK to the tech pool if you can't pay)
`, maxCount: 1, count: 0, frequency: 2, @@ -3297,7 +3298,7 @@ const tech = { { name: "exciton", descriptionFunction() { - return `after mobs die they have a 17% chance to
spawn ${powerUps.orb.boost(1)} that give +${powerUps.boost.damage*100}% damage for ${(powerUps.boost.duration/60).toFixed(0)} seconds
` + return `after mobs die they have a 18% chance to
spawn ${powerUps.orb.boost(1)} that give +${(powerUps.boost.damage*100).toFixed(0)}% damage for ${(powerUps.boost.duration/60).toFixed(0)} seconds
` }, maxCount: 1, count: 0, @@ -3314,6 +3315,29 @@ const tech = { tech.isBoostPowerUps = false } }, + { + name: "band gap", + descriptionFunction() { + return `${powerUps.orb.boost(1)} give +77% damage
but their duration is reduced by 1 second` + }, + maxCount: 9, + count: 1, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.isBoostPowerUps || tech.isBoostReplaceAmmo + }, + requires: "exciton, quasiparticles", + effect() { + powerUps.boost.duration -= 60 + powerUps.boost.damage += 0.77 + }, + remove() { + powerUps.boost.duration = 600 + powerUps.boost.damage = 1.25 + } + }, + { name: "eternalism", description: "+34% damage
time can't be paused (time can be dilated)", @@ -3463,7 +3487,7 @@ const tech = { maxCount: 1, count: 0, frequency: 1, - frequencyDefault: 1, + frequencyDefault: 100, allowed() { return true }, @@ -3474,11 +3498,14 @@ const tech = { simulation.makeTextLog(`m.coupling += ${(this.value).toFixed(1)}`); m.coupling += this.value m.couplingChange() + this.maxCount = 0 }, remove() { if (this.count) { m.coupling -= this.value m.couplingChange() + } else { + this.maxCount = 1 } tech.isCouplingNoHit = false } @@ -3506,7 +3533,7 @@ const tech = { { name: "options exchange", link: `options exchange`, - description: `clicking × for a field, tech, or gun has a 90%
chance to randomize choices and not cancel`, + description: `clicking × for a field, tech, or gun has a 88%
chance to randomize choices and not cancel`, maxCount: 1, count: 0, frequency: 1, @@ -3542,7 +3569,7 @@ const tech = { }, { name: "futures exchange", - description: "clicking × to cancel a field, tech, or gun
+4.5% power up duplication chance", + description: "clicking × to cancel a field, tech, or gun
gives +4.5% power up duplication chance", maxCount: 1, count: 0, frequency: 1, @@ -4034,7 +4061,7 @@ const tech = { frequencyDefault: 2, allowed() { // return (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("mines")) - return tech.isMineDrop || tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !(tech.isLaserMine || tech.isFoamMine)) || (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot)) + return tech.isMineDrop || tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !(tech.isLaserMine || tech.isFoamMine)) || (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot) && !tech.isRivets && !tech.isNeedles) }, // requires: "nail gun, not rotary cannon, rivets, or needles", @@ -4298,7 +4325,7 @@ const tech = { { name: "Noether violation", link: `Noether violation`, - description: "+60% shotgun damage
shotgun recoil is reversed", + description: "+50% shotgun damage
shotgun recoil is reversed", isGunTech: true, maxCount: 1, count: 0, @@ -4318,7 +4345,7 @@ const tech = { { name: "nail-shot", link: `nail-shot`, - description: "shotgun fires 17 nails", + description: "shotgun drives a long clip of nails", isGunTech: true, maxCount: 1, count: 0, @@ -4338,7 +4365,7 @@ const tech = { { name: "foam-shot", link: `foam-shot`, - description: "shotgun sprays 15 sticky foam bubbles", + description: "shotgun sprays sticky foam bubbles", isGunTech: true, maxCount: 1, count: 0, @@ -4358,7 +4385,7 @@ const tech = { { name: "ice-shot", link: `ice-shot`, - description: "shotgun grows 15 freezing ice IX crystals", + description: "shotgun grows freezing ice IX crystals", isGunTech: true, maxCount: 1, count: 0, @@ -4756,7 +4783,7 @@ const tech = { }, { name: "cruise missile", - description: "+100% missile explosive damage, radius
–50% missiles speed", + description: "+100% missile explosive damage, radius
–50% missile speed", isGunTech: true, maxCount: 1, count: 0, @@ -4765,7 +4792,7 @@ const tech = { allowed() { return (tech.haveGunCheck("missiles") && tech.missileFireCD === 45) || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && simulation.molecularMode === 1) || tech.missileBotCount }, - requires: "missiles", + requires: "missiles, not launch system", effect() { tech.isMissileBig = true }, @@ -4775,7 +4802,7 @@ const tech = { }, { name: "ICBM", - description: "+100% missile explosive damage, radius
–66% missiles speed", + description: "+75% missile explosive damage, radius
–50% missile speed", isGunTech: true, maxCount: 1, count: 0, @@ -4803,7 +4830,7 @@ const tech = { allowed() { return tech.haveGunCheck("missiles") && !tech.isMissileBig }, - requires: "missiles", + requires: "missiles, not cruise missile", ammoBonus: 1.2, effect() { tech.missileFireCD = 10 @@ -4976,7 +5003,7 @@ const tech = { } }, { - name: "controlled explosion", + name: "shaped charge", description: `use ${powerUps.orb.research(4)} to dynamically reduce
all explosions to prevent health loss`, isGunTech: true, maxCount: 1, @@ -5959,9 +5986,9 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.isHarpoonPowerUp && !tech.isGrapple + return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.isHarpoonPowerUp && !tech.isGrapple && !tech.isBoostReplaceAmmo }, - requires: "harpoon, not UHMWPE, induction furnace, grappling hook", + requires: "harpoon, not UHMWPE, induction furnace, grappling hook, quasiparticles", ammoBonus: 9, effect() { tech.isRailGun = true; @@ -6179,6 +6206,35 @@ const tech = { tech.harpoonDensity = 0.004 } }, + { + name: "quasiparticles", + descriptionFunction() { + return `convert current and future ${powerUps.orb.ammo(1)} into ${powerUps.orb.boost(1)} which
give +${(powerUps.boost.damage*100).toFixed(0)}% damage for ${(powerUps.boost.duration/60).toFixed(0)} seconds` + }, + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("laser") || (tech.haveGunCheck("harpoon") && !tech.isRailGun) + }, + requires: "harpoon, laser, not railgun", + effect() { + tech.isBoostReplaceAmmo = true + for (let i = powerUp.length - 1; i > -1; i--) { + if (powerUp[i].name === "ammo") { + powerUps.spawn(powerUp[i].position.x + 50 * (Math.random() - 0.5), powerUp[i].position.y + 50 * (Math.random() - 0.5), "boost"); + Matter.Composite.remove(engine.world, powerUp[i]); + powerUp.splice(i, 1); + } + } + + }, + remove() { + tech.isBoostReplaceAmmo = false + } + }, { name: "optical amplifier", description: "gain 3 random laser guntech
laser only turns off if you have no energy", @@ -6195,7 +6251,7 @@ const tech = { effect() { let techGiven = 0 for (let j = 0; j < 3; j++) { - const names = ["lens", "compound lens", "arc length", "infrared diode", "free-electron laser", "dye laser", "relativistic momentum", "specular reflection", "diffraction grating", "diffuse beam", "output coupler", "slow light", "laser-bot", "laser-bot upgrade"] + const names = ["quasiparticles", "lens", "compound lens", "arc length", "infrared diode", "free-electron laser", "dye laser", "relativistic momentum", "specular reflection", "diffraction grating", "diffuse beam", "output coupler", "slow light", "laser-bot", "laser-bot upgrade"] //convert names into indexes const options = [] for (let i = 0; i < names.length; i++) { @@ -6241,27 +6297,6 @@ const tech = { tech.isStuckOn = false } }, - { - name: "quasiparticles", - descriptionFunction() { - return `replace all ${powerUps.orb.ammo(1)} spawns with ${powerUps.orb.boost(1)} which give
+${powerUps.boost.damage*100}% damage for ${(powerUps.boost.duration/60).toFixed(0)} seconds` - }, - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.haveGunCheck("laser") - }, - requires: "laser, not pulse", - effect() { - tech.isBoostReplaceAmmo = true - }, - remove() { - tech.isBoostReplaceAmmo = false - } - }, { name: "relativistic momentum", description: "lasers push mobs and blocks", @@ -7812,207 +7847,153 @@ const tech = { //************************************************** experimental //************************************************** modes //************************************************** - { - name: "-ship-", - description: "experiment: fly around with no legs
aim with the keyboard", - maxCount: 1, - count: 0, - frequency: 0, - isNonRefundable: true, - isBadRandomOption: true, - isExperimentalMode: true, - allowed() { - return build.isExperimentSelection && !m.isShipMode && m.fieldUpgrades[m.fieldMode].name !== "negative mass" - }, - requires: "", - effect() { - m.shipMode() - }, - remove() {} - }, - { - name: "-quantum leap-", - description: "experiment: every 20 seconds
become an alternate version of yourself", - maxCount: 1, - count: 0, - frequency: 0, - isBadRandomOption: true, - isExperimentalMode: true, - allowed() { - return build.isExperimentSelection - }, - requires: "", - interval: undefined, - effect() { - this.interval = setInterval(() => { - if (!build.isExperimentSelection) { - m.switchWorlds() - simulation.trails() - } - }, 20000); //every 20 seconds + // { + // name: "-ship-", + // description: "experiment: fly around with no legs
aim with the keyboard", + // maxCount: 1, + // count: 0, + // frequency: 0, + // isNonRefundable: true, + // isBadRandomOption: true, + // isExperimentalMode: true, + // allowed() { + // return build.isExperimentSelection && !m.isShipMode && m.fieldUpgrades[m.fieldMode].name !== "negative mass" + // }, + // requires: "", + // effect() { + // m.shipMode() + // }, + // remove() {} + // }, + // { + // name: "-quantum leap-", + // description: "experiment: every 20 seconds
become an alternate version of yourself", + // maxCount: 1, + // count: 0, + // frequency: 0, + // isBadRandomOption: true, + // isExperimentalMode: true, + // allowed() { + // return build.isExperimentSelection + // }, + // requires: "", + // interval: undefined, + // effect() { + // this.interval = setInterval(() => { + // if (!build.isExperimentSelection) { + // m.switchWorlds() + // simulation.trails() + // } + // }, 20000); //every 20 seconds + + // }, + // remove() { + // if (this.count > 0) clearTimeout(this.interval); + // } + // }, + // { + // name: "-shields-", + // description: "experiment: every 5 seconds
all mobs gain a shield", + // maxCount: 1, + // count: 0, + // frequency: 0, + // isBadRandomOption: true, + // isExperimentalMode: true, + // allowed() { + // return build.isExperimentSelection + // }, + // requires: "", + // effect() { + // this.interval = setInterval(() => { + // if (!build.isExperimentSelection) { + // for (let i = 0; i < mob.length; i++) { + // if (!mob[i].isShielded && !mob[i].shield && mob[i].isDropPowerUp) spawn.shield(mob[i], mob[i].position.x, mob[i].position.y, 1, true); + // } + // } + // }, 5000); //every 5 seconds + // }, + // interval: undefined, + // remove() { + // if (this.count > 0) clearTimeout(this.interval); + // } + // }, + // { + // name: "-Fourier analysis-", + // description: "experiment: your aiming is random", + // maxCount: 1, + // count: 0, + // frequency: 0, + // isBadRandomOption: true, + // isExperimentalMode: true, + // allowed() { + // return build.isExperimentSelection && !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; + // 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 > 0) m.look = m.lookDefault() + // } + // }, + // { + // name: "-panopticon-", + // description: "experiment: mobs can always see you", + // maxCount: 1, + // count: 0, + // frequency: 0, + // isBadRandomOption: true, + // isExperimentalMode: true, + // allowed() { + // return build.isExperimentSelection + // }, + // requires: "", + // effect() { + // this.interval = setInterval(() => { + // if (!build.isExperimentSelection) { + // 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 + // }, + // interval: undefined, + // remove() { + // if (this.count > 0) clearTimeout(this.interval); + // } + // }, + // { + // name: "-decomposers-", + // description: "experiment: after they die
mobs leave behind spawns", + // maxCount: 1, + // count: 0, + // frequency: 0, + // isBadRandomOption: true, + // isExperimentalMode: true, + // allowed() { + // return build.isExperimentSelection + // }, + // requires: "", + // effect() { + // tech.deathSpawns = 0.2 + // }, + // remove() { + // tech.deathSpawns = 0 + // } + // }, + + - }, - remove() { - if (this.count > 0) clearTimeout(this.interval); - } - }, - { - name: "-shields-", - description: "experiment: every 5 seconds
all mobs gain a shield", - maxCount: 1, - count: 0, - frequency: 0, - isBadRandomOption: true, - isExperimentalMode: true, - allowed() { - return build.isExperimentSelection - }, - requires: "", - effect() { - this.interval = setInterval(() => { - if (!build.isExperimentSelection) { - for (let i = 0; i < mob.length; i++) { - if (!mob[i].isShielded && !mob[i].shield && mob[i].isDropPowerUp) spawn.shield(mob[i], mob[i].position.x, mob[i].position.y, 1, true); - } - } - }, 5000); //every 5 seconds - }, - interval: undefined, - remove() { - if (this.count > 0) clearTimeout(this.interval); - } - }, - { - name: "-Fourier analysis-", - description: "experiment: your aiming is random", - maxCount: 1, - count: 0, - frequency: 0, - isBadRandomOption: true, - isExperimentalMode: true, - allowed() { - return build.isExperimentSelection && !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; - 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 > 0) m.look = m.lookDefault() - } - }, - { - name: "-panopticon-", - description: "experiment: mobs can always see you", - maxCount: 1, - count: 0, - frequency: 0, - isBadRandomOption: true, - isExperimentalMode: true, - allowed() { - return build.isExperimentSelection - }, - requires: "", - effect() { - this.interval = setInterval(() => { - if (!build.isExperimentSelection) { - 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 - }, - interval: undefined, - remove() { - if (this.count > 0) clearTimeout(this.interval); - } - }, - { - name: "-decomposers-", - description: "experiment: after they die
mobs leave behind spawns", - maxCount: 1, - count: 0, - frequency: 0, - isBadRandomOption: true, - isExperimentalMode: true, - allowed() { - return build.isExperimentSelection - }, - requires: "", - effect() { - tech.deathSpawns = 0.2 - }, - remove() { - tech.deathSpawns = 0 - } - }, - { - name: "-WIMP-", - description: "experiment: harmful particles slowly chase you", - maxCount: 1, - count: 0, - frequency: 0, - isBadRandomOption: true, - isExperimentalMode: true, - allowed() { - return build.isExperimentSelection - }, - requires: "", - effect() { - tech.wimpExperiment = 5 - }, - remove() { - tech.wimpExperiment = 0 - } - }, - { - name: "-symbiosis-", - description: "experiment: if you kill a mob
lose 0.2 max health", - maxCount: 1, - count: 0, - frequency: 0, - isBadRandomOption: true, - isExperimentalMode: true, - allowed() { - return build.isExperimentSelection - }, - requires: "", - effect() { - tech.removeMaxHealthOnKill = 0.002 - }, - remove() { - tech.removeMaxHealthOnKill = 0 - } - }, - { - name: "-parthenocarpy-", - description: "experiment: spawn about 50% more mobs", - maxCount: 1, - count: 1, - frequency: 0, - isBadRandomOption: true, - isExperimentalMode: true, - allowed() { - return build.isExperimentSelection - }, - requires: "", - effect() { - tech.isMoreMobs = true - }, - remove() { - tech.isMoreMobs = false - } - }, //************************************************** //************************************************** JUNK //************************************************** tech @@ -10629,12 +10610,10 @@ const tech = { isHarpoonPowerUp: null, harpoonDensity: null, isAddRemoveMaxHealth: null, - removeMaxHealthOnKill: null, isSpawnExitTech: null, cloakDuplication: null, extruderRange: null, isForeverDrones: null, - isMoreMobs: null, nailRecoil: null, baseJumpForce: null, baseFx: null, diff --git a/todo.txt b/todo.txt index bd5c991..88050d7 100644 --- a/todo.txt +++ b/todo.txt @@ -1,21 +1,41 @@ ******************************************************** NEXT PATCH ************************************************** -tech: virtual particles - mobs have a chance to spawn coupling power ups - old tech virtual particles renamed vacuum fluctuation +some shotgun ammo tech upgrades will continue to fire some original recipe shotgun bullets + rivets, fleas, worms, iceIX +tech: band gap - boosts give more damage but it lasts for 1 less second -tech: exciton - mobs have a chance to spawn a boost - boosts are a power up that increases your damage for 10 seconds - old tech exciton renamed non-renewables -laser tech: quasiparticles - replace all ammo with boosts +WIMPs are 10% faster +controlled explosion renamed shaped charge -added +20px to grid elements to prevent text spillover bug fixes + construction mode works better with my buttons + to unlock run this and press T to enter testing mode + simulation.enableConstructMode() //used to build maps in testing mode +removed -experiment- tech because it's function was reproduced by "tech - tinker" *********************************************************** TODO ***************************************************** +complete blowSuckBoss... or don't + +tech: laser reflections increase damage + +JUNK tech different effects based on night or day + use system time + +buffing your deflecting for 1 second after pressing the field button + 2 second cooldown on the effect to prevent spamming it + buff: giving energy or doing damage makes sense + maybe this could be a rework for bremstralung + +replace field descriptions with a function call so they can have dynamic text + add in dynamic coupling text as a 4th line + +Boss that shoots out a ring of bullets, then after a few seconds it gravitates the bullets back + +JUNK: Placebo: double the power up spawn rate but make half of them do nothing + coupling - pause menu +defense on coupling description goes above 100% put coupling description as 4th line on field description raw text no function call no need for coupling description in power ups, pause @@ -27,15 +47,8 @@ coupling tech tech: coupling starts at 200%, but decays when the field is in use, coupling recharges when the field is not in use some fields aren't used much (that's ok?) -tech: increase the effect of boosts, but shorten the duration? - tech give laser mines more lasers (3->4? 5?) -buffing your deflecting for 1 second after pressing the field button sounds cool - 2 second cooldown on the effect to prevent spamming it - buff: giving energy or doing damage makes sense - maybe this could be a rework for bremstralung - rewindBoss: after hitting 1/5 damage thresholds the boss rewinds back in time to where it was a few seconds ago track it's data like player history @@ -913,6 +926,8 @@ possible names for tech lenticular lens: is an array of lenses, designed so that when viewed from slightly different angles, different parts of the image underneath are shown. p-zombie p-hacking JUNK tech + https://en.wikipedia.org/wiki/High-entropy_alloys + https://en.wikipedia.org/wiki/Refractory_metals plot script: