From 10b56164601d030f5f8425139d6559c3ef3c3fe8 Mon Sep 17 00:00:00 2001 From: landgreen Date: Sat, 20 Feb 2021 16:37:32 -0800 Subject: [PATCH] upgrades many worlds renamed to ansatz new tech many-worlds: at the start of each new level switch realities removed tech: electroactive polymers - convert bots to the same type on weapon swap all bot upgrades convert current bots to the upgraded type only one bot upgrade allowed --- .DS_Store | Bin 6148 -> 6148 bytes js/bullet.js | 167 ++++++++++++++++++++++++------------- js/level.js | 10 ++- js/player.js | 177 ++++++++++++++++++++------------------- js/powerup.js | 4 +- js/simulation.js | 20 ----- js/spawn.js | 29 ++++--- js/tech.js | 211 ++++++++++++++++++++++++++++------------------- todo.txt | 15 ++-- 9 files changed, 365 insertions(+), 268 deletions(-) diff --git a/.DS_Store b/.DS_Store index d4ddd7cca0c183e6cc10a7d8eaee4da5ceddf6d4..906e7a9d6a05ed53d17fdecca074685d8b988f9a 100644 GIT binary patch delta 21 ccmZoMXffEJ#mwZQJXwd?k8#1~YUWN607QERE&u=k delta 21 ccmZoMXffEJ#mr<9K3Rv^k8#50YUWN607bh7LI3~& diff --git a/js/bullet.js b/js/bullet.js index 2edbfa6..98fd86f 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -1089,18 +1089,18 @@ const b = { m.energy = 0; } b.isExtruderOn = true - const SPEED = 10 + const SPEED = 8 const me = bullet.length; const where = Vector.add(m.pos, player.velocity) bullet[me] = Bodies.polygon(where.x + 20 * Math.cos(m.angle), where.y + 20 * Math.sin(m.angle), 4, 0.01, { cycle: -0.5, isWave: true, - endCycle: simulation.cycle + 10 + 40 * tech.isPlasmaRange, + endCycle: simulation.cycle + 35 + 45 * tech.isPlasmaRange, inertia: Infinity, frictionAir: 0, isInHole: true, //this keeps the bullet from entering wormholes minDmgSpeed: 0, - dmg: b.dmgScale * 1.35, //damage also changes when you divide by mob.mass on in .do() + dmg: b.dmgScale * 1.2, //damage also changes when you divide by mob.mass on in .do() classType: "bullet", isBranch: false, restitution: 0, @@ -1121,8 +1121,8 @@ const b = { const q = Matter.Query.point(mob, this.position) for (let i = 0; i < q.length; i++) { Matter.Body.setVelocity(q[i], { - x: q[i].velocity.x * 0.6, - y: q[i].velocity.y * 0.6 + x: q[i].velocity.x * 0.2, + y: q[i].velocity.y * 0.2 }); Matter.Body.setPosition(this, Vector.add(this.position, q[i].velocity)) //move with the medium let dmg = this.dmg / Math.min(10, q[i].mass) @@ -2226,6 +2226,55 @@ const b = { // ******************************** Bots ********************************************* // ************************************************************************************************** // ************************************************************************************************** + totalBots() { + return tech.dynamoBotCount + tech.foamBotCount + tech.nailBotCount + tech.laserBotCount + tech.boomBotCount + tech.orbitBotCount + tech.plasmaBotCount + tech.missileBotCount + }, + hasBotUpgrade() { + return tech.isNailBotUpgrade + tech.isFoamBotUpgrade + tech.isBoomBotUpgrade + tech.isLaserBotUpgrade + tech.isOrbitBotUpgrade + tech.isDynamoBotUpgrade + }, + convertBotsTo(type) { //type can be a string like "dynamoBotCount" + //count all bots + const totalBots = b.totalBots() + //remove all bots techs and convert them to the new type so that tech refunds work correctly + let totalTechToConvert = 0 //count how many tech need to be converted + for (let i = 0; i < tech.tech.length; i++) { + if (tech.tech[i].count && tech.tech[i].isBotTech) { + totalTechToConvert += tech.tech[i].count + tech.removeTech(i) + } + } + console.log(totalTechToConvert) + + let name = "" + if (type === "nailBotCount") name = "nail-bot" + if (type === "orbitBotCount") name = "orbital-bot" + if (type === "boomBotCount") name = "boom-bot" + if (type === "laserBotCount") name = "laser-bot" + if (type === "foamBotCount") name = "foam-bot" + if (type === "dynamoBotCount") name = "dynamo-bot" + if (type === "plasmaBotCount") name = "plasma-bot" + if (type === "missileBotCount") name = "missile-bot" + //spawn tech for the correct bot type + for (let i = 0; i < totalTechToConvert; i++) tech.giveTech(name) + + //remove all bots + b.zeroBotCount() + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType && bullet[i].endCycle === Infinity) bullet[i].endCycle = 0 //don't remove temp bots + } + //set all bots to type + tech[type] = totalBots + //respawn all bots + b.respawnBots(); + }, + zeroBotCount() { //remove all bots + tech.dynamoBotCount = 0 + tech.laserBotCount = 0 + tech.nailBotCount = 0 + tech.foamBotCount = 0 + tech.boomBotCount = 0 + tech.orbitBotCount = 0 + }, respawnBots() { for (let i = 0; i < tech.dynamoBotCount; i++) b.dynamoBot({ x: player.position.x + 50 * (Math.random() - 0.5), y: player.position.y + 50 * (Math.random() - 0.5) }, false) for (let i = 0; i < tech.laserBotCount; i++) b.laserBot({ x: player.position.x + 50 * (Math.random() - 0.5), y: player.position.y + 50 * (Math.random() - 0.5) }, false) @@ -2311,61 +2360,65 @@ const b = { // ctx.arc(this.position.x, this.position.y, 150, 0, 2 * Math.PI); // ctx.fill(); // } - if (!((m.cycle + this.phase) % 30)) { //twice a second - if (Vector.magnitude(Vector.sub(this.position, player.position)) < 250) { //give energy - Matter.Body.setAngularVelocity(this, this.spin) - if (this.isUpgraded) { - m.energy += 0.12 - simulation.drawList.push({ //add dmg to draw queue - x: this.position.x, - y: this.position.y, - radius: 8, - color: m.fieldMeterColor, - time: simulation.drawTime - }); - } else { - m.energy += 0.03 - simulation.drawList.push({ //add dmg to draw queue - x: this.position.x, - y: this.position.y, - radius: 5, - color: m.fieldMeterColor, - time: simulation.drawTime - }); - } - } - } + //check for damage - if (!m.isCloak && !m.isBodiesAsleep) { //if time dilation isn't active - const size = 33 - q = Matter.Query.region(mob, { - min: { - x: this.position.x - size, - y: this.position.y - size - }, - max: { - x: this.position.x + size, - y: this.position.y + size + if (!m.isBodiesAsleep) { + if (!((m.cycle + this.phase) % 30)) { //twice a second + if (Vector.magnitude(Vector.sub(this.position, player.position)) < 250) { //give energy + Matter.Body.setAngularVelocity(this, this.spin) + if (this.isUpgraded) { + m.energy += 0.12 + simulation.drawList.push({ //add dmg to draw queue + x: this.position.x, + y: this.position.y, + radius: 8, + color: m.fieldMeterColor, + time: simulation.drawTime + }); + } else { + m.energy += 0.03 + simulation.drawList.push({ //add dmg to draw queue + x: this.position.x, + y: this.position.y, + radius: 5, + color: m.fieldMeterColor, + time: simulation.drawTime + }); + } } - }) - for (let i = 0; i < q.length; i++) { - Matter.Body.setAngularVelocity(this, this.spin) - // mobs.statusStun(q[i], 180) - // const dmg = 0.5 * b.dmgScale * (this.isUpgraded ? 2.5 : 1) - const dmg = 0.5 * b.dmgScale - q[i].damage(dmg); - q[i].foundPlayer(); - simulation.drawList.push({ //add dmg to draw queue - x: this.position.x, - y: this.position.y, - radius: Math.log(2 * dmg + 1.1) * 40, - color: 'rgba(0,0,0,0.4)', - time: simulation.drawTime - }); } + + if (!m.isCloak) { //if time dilation isn't active + const size = 33 + q = Matter.Query.region(mob, { + min: { + x: this.position.x - size, + y: this.position.y - size + }, + max: { + x: this.position.x + size, + y: this.position.y + size + } + }) + for (let i = 0; i < q.length; i++) { + Matter.Body.setAngularVelocity(this, this.spin) + // mobs.statusStun(q[i], 180) + // const dmg = 0.5 * b.dmgScale * (this.isUpgraded ? 2.5 : 1) + const dmg = 0.5 * b.dmgScale + q[i].damage(dmg); + q[i].foundPlayer(); + simulation.drawList.push({ //add dmg to draw queue + x: this.position.x, + y: this.position.y, + radius: Math.log(2 * dmg + 1.1) * 40, + color: 'rgba(0,0,0,0.4)', + time: simulation.drawTime + }); + } + } + let history = m.history[(m.cycle - this.followDelay) % 600] + Matter.Body.setPosition(this, { x: history.position.x, y: history.position.y - history.yOff + 24.2859 }) //bullets move with player } - let history = m.history[(m.cycle - this.followDelay) % 600] - Matter.Body.setPosition(this, { x: history.position.x, y: history.position.y - history.yOff + 24.2859 }) //bullets move with player } }) World.add(engine.world, bullet[me]); //add bullet to world @@ -2605,7 +2658,7 @@ const b = { } //hit target with laser if (this.lockedOn && this.lockedOn.alive && m.energy > this.drainThreshold) { - m.energy -= tech.laserFieldDrain * tech.isLaserDiode + m.energy -= tech.laserFieldDrain * tech.isLaserDiode * 0.7 b.laser(this.vertices[0], this.lockedOn.position, b.dmgScale * (0.38 * tech.laserDamage + this.isUpgraded * 0.25), tech.laserReflections, false, 0.4) //tech.laserDamage = 0.16 // laser(where = { // x: m.pos.x + 20 * Math.cos(m.angle), diff --git a/js/level.js b/js/level.js index 51e1d06..665b89f 100644 --- a/js/level.js +++ b/js/level.js @@ -20,7 +20,7 @@ const level = { // tech.isExplodeRadio = true // for (let i = 0; i < 1; i++) tech.giveTech("dynamo-bot") // tech.giveTech("supercritical fission") - // tech.giveTech("CPT reversal") + // tech.giveTech("micro-extruder") // tech.giveTech("causality bombs") // tech.giveTech("cardinality") // tech.giveTech("Bayesian statistics") @@ -110,6 +110,11 @@ const level = { if (b.inventoryGun > b.inventory.length - 1) b.inventoryGun = 0; simulation.switchGun(); } + if (tech.isSwitchReality) { + simulation.makeTextLog(`simulation.amplitude = ${Math.random()}`); + m.switchWorlds() + for (let i = 0; i < 2; i++) powerUps.spawn(m.pos.x + Math.random() * 10, m.pos.y + Math.random() * 10, "tech", false); + } }, custom() {}, customTopLayer() {}, @@ -2503,13 +2508,14 @@ const level = { spawn.randomMob(1725, 125, 0.5); if (simulation.difficulty > 3) { if (Math.random() < 0.1) { // tether ball + const index = mob.length spawn.tetherBoss(4250, 0) cons[cons.length] = Constraint.create({ pointA: { x: 4250, y: -675 }, - bodyB: mob[mob.length - 1], + bodyB: mob[index], stiffness: 0.00007 }); World.add(engine.world, cons[cons.length - 1]); diff --git a/js/player.js b/js/player.js index 21eea8f..06bde88 100644 --- a/js/player.js +++ b/js/player.js @@ -303,106 +303,117 @@ const m = { } }, alive: false, + switchWorlds() { + //count tech + const totalGuns = b.inventory.length - tech.isRewindGun //count guns, but not CPT gun + simulation.isTextLogOpen = false; //prevent console spam + //remove all tech and count current tech total + let totalTech = 0; + for (let i = 0, len = tech.tech.length; i < len; i++) { + if (!tech.tech[i].isNonRefundable && tech.tech[i].name !== "quantum immortality" && tech.tech[i].name !== "many-worlds") { + totalTech += tech.tech[i].count + tech.tech[i].remove(); + tech.tech[i].isLost = false + tech.tech[i].count = 0 + } + } + lore.techCount = 0; + tech.removeJunkTechFromPool(); + tech.removeLoreTechFromPool(); + tech.addLoreTechToPool(); + tech.armorFromPowerUps = 0; + tech.totalCount = 0; + + //randomize health + m.health = 0.7 + Math.random() + if (m.health > 1) m.health = 1; + m.displayHealth(); + + //randomize field + m.setField(Math.ceil(Math.random() * (m.fieldUpgrades.length - 1))) + + + //track how ammo/ ammoPack count + let ammoCount = 0 + for (let i = 0, len = b.inventory.length; i < len; i++) { + if (b.guns[b.inventory[i]].ammo !== Infinity) ammoCount += b.guns[b.inventory[i]].ammo / b.guns[b.inventory[i]].ammoPack + } + + //remove all bullets + for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]); + bullet = []; + //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; + } + //give random guns + for (let i = 0; i < totalGuns; i++) b.giveGuns() + + //randomize ammo based on ammo/ammopack count + for (let i = 0, len = b.inventory.length; i < len; i++) { + if (b.guns[b.inventory[i]].ammo !== Infinity) b.guns[b.inventory[i]].ammo = Math.max(0, Math.floor(ammoCount / b.inventory.length * b.guns[b.inventory[i]].ammoPack * (1.05 + 0.5 * (Math.random() - 0.5)))) + } + + //randomize tech + for (let i = 0; i < totalTech; i++) { + //find what tech I could get + let options = []; + for (let i = 0, len = tech.tech.length; i < len; i++) { + if (tech.tech[i].count < tech.tech[i].maxCount && + !tech.tech[i].isNonRefundable && + tech.tech[i].name !== "quantum immortality" && + tech.tech[i].name !== "many-worlds" && + tech.tech[i].name !== "Born rule" && + tech.tech[i].name !== "determinism" && + tech.tech[i].allowed() + ) options.push(i); + } + //add a new tech from options pool + if (options.length > 0) tech.giveTech(options[Math.floor(Math.random() * options.length)]) + } + + simulation.makeGunHUD(); //update gun HUD + simulation.updateTechHUD(); + simulation.isTextLogOpen = true; + }, death() { if (tech.isImmortal) { //if player has the immortality buff, spawn on the same level with randomized damage - simulation.isTextLogOpen = false; - //count tech - let totalTech = 0; + + //remove immortality tech for (let i = 0; i < tech.tech.length; i++) { - if (!tech.tech[i].isNonRefundable) totalTech += tech.tech[i].count - } - if (tech.isDeterminism) totalTech -= 3 //remove the bonus tech - if (tech.isSuperDeterminism) totalTech -= 2 //remove the bonus tech - totalTech = totalTech * 1.15 + 1 // a few extra to make it stronger - const totalGuns = b.inventory.length //count guns - - function randomizeTech() { - for (let i = 0; i < totalTech; i++) { - //find what tech I don't have - let options = []; - for (let i = 0, len = tech.tech.length; i < len; i++) { - if (tech.tech[i].count < tech.tech[i].maxCount && - !tech.tech[i].isNonRefundable && - tech.tech[i].name !== "quantum immortality" && - tech.tech[i].name !== "Born rule" && - tech.tech[i].allowed() - ) options.push(i); - } - //add a new tech - if (options.length > 0) { - const choose = Math.floor(Math.random() * options.length) - let newTech = options[choose] - tech.giveTech(newTech) - options.splice(choose, 1); - } - } - simulation.updateTechHUD(); - } - - function randomizeField() { - m.setField(Math.ceil(Math.random() * (m.fieldUpgrades.length - 1))) - } - - function randomizeHealth() { - m.health = 0.7 + Math.random() - if (m.health > 1) m.health = 1; - m.displayHealth(); - } - - function randomizeGuns() { - //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; - } - //give random guns - for (let i = 0; i < totalGuns; i++) b.giveGuns() - //randomize ammo - for (let i = 0, len = b.inventory.length; i < len; i++) { - if (b.guns[b.inventory[i]].ammo !== Infinity) { - b.guns[b.inventory[i]].ammo = Math.max(0, Math.floor(6 * b.guns[b.inventory[i]].ammo * Math.sqrt(Math.random()))) - } - } - simulation.makeGunHUD(); //update gun HUD + if (tech.tech[i].name === "quantum immortality") tech.removeTech(i) } simulation.wipe = function() { //set wipe to have trails ctx.fillStyle = "rgba(255,255,255,0)"; ctx.fillRect(0, 0, canvas.width, canvas.height); } - - function randomizeEverything() { - spawn.setSpawnList(); //new mob types - simulation.clearNow = true; //triggers a map reset - - tech.setupAllTech(); //remove all tech - for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]); - bullet = []; //remove all bullets - randomizeHealth() - randomizeField() - randomizeGuns() - randomizeTech() - } - - randomizeEverything() + spawn.setSpawnList(); //new mob types + simulation.clearNow = true; //triggers a map reset + m.switchWorlds() const swapPeriod = 1000 for (let i = 0, len = 5; i < len; i++) { setTimeout(function() { - randomizeEverything() + simulation.wipe = function() { //set wipe to have trails + ctx.fillStyle = "rgba(255,255,255,0)"; + ctx.fillRect(0, 0, canvas.width, canvas.height); + } + spawn.setSpawnList(); //new mob types + simulation.clearNow = true; //triggers a map reset + m.switchWorlds() simulation.isTextLogOpen = true; simulation.makeTextLog(`simulation.amplitude = 0.${len-i-1}`, swapPeriod); simulation.isTextLogOpen = false; simulation.wipe = function() { //set wipe to have trails ctx.fillStyle = `rgba(255,255,255,${(i+1)*(i+1)*0.006})`; ctx.fillRect(0, 0, canvas.width, canvas.height); - // pixelWindows() } }, (i + 1) * swapPeriod); } - setTimeout(function() { simulation.wipe = function() { //set wipe to normal ctx.clearRect(0, 0, canvas.width, canvas.height); @@ -410,7 +421,6 @@ const m = { simulation.isTextLogOpen = true; simulation.makeTextLog("simulation.amplitude = null"); }, 6 * swapPeriod); - } else if (m.alive) { //normal death code here m.alive = false; simulation.paused = true; @@ -482,7 +492,7 @@ const m = { if (tech.isSlowFPS) dmg *= 0.8 if (tech.isPiezo) dmg *= 0.85 if (tech.isHarmReduce && m.fieldUpgrades[m.fieldMode].name === "negative mass field" && m.isFieldActive) dmg *= 0.5 - if (tech.isBotArmor) dmg *= 0.94 ** tech.totalBots() + if (tech.isBotArmor) dmg *= 0.94 ** b.totalBots() if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.33; if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.34 if (tech.energyRegen === 0) dmg *= 0.34 @@ -1163,7 +1173,7 @@ const m = { //draw electricity const step = 40 ctx.beginPath(); - for (let i = 0, len = 2.5 * tech.blockDmg; i < len; i++) { + for (let i = 0, len = 1.5 * tech.blockDmg; i < len; i++) { let x = m.pos.x - 20 * unit.x; let y = m.pos.y - 20 * unit.y; ctx.moveTo(x, y); @@ -1180,7 +1190,7 @@ const m = { m.drawHold(who); } // if (tech.isFreezeMobs) mobs.statusSlow(who, 60) //this works but doesn't have a fun effect - + if (tech.isStunField) mobs.statusStun(who, tech.isStunField) // m.holdingTarget = null //knock backs if (m.fieldShieldingScale > 0) { @@ -1202,7 +1212,6 @@ const m = { }); } } else { - if (tech.isStunField && m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism") mobs.statusStun(who, tech.isStunField) // mobs.statusSlow(who, tech.isStunField) const massRoot = Math.sqrt(Math.max(0.15, who.mass)); // masses above 12 can start to overcome the push back Matter.Body.setVelocity(who, { diff --git a/js/powerup.js b/js/powerup.js index 0115435..cdb0839 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -94,7 +94,7 @@ const powerUps = { } } if (tech.isRerollBots) { - const limit = 5 + const limit = 4 for (; powerUps.research.count > limit - 1; powerUps.research.count -= limit) { b.randomBot() if (tech.renormalization) { @@ -462,7 +462,7 @@ const powerUps = { } // console.log(powerUps.gun.choiceLog) // console.log(choice1, choice2, choice3) - if (tech.isOneGun) text += `
replaces your current gun
` + if (tech.isOneGun && b.inventory.length > 0) text += `
replaces your current gun
` document.getElementById("choose-grid").innerHTML = text powerUps.showDraft(); } else { diff --git a/js/simulation.js b/js/simulation.js index 2f11300..f13a1cc 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -362,26 +362,6 @@ const simulation = { b.activeGun = b.inventory[b.inventoryGun]; simulation.updateGunHUD(); simulation.boldActiveGunHUD(); - if (tech.isBotSwap) { - //get total count - const countPermanent = tech.dynamoBotCount + tech.laserBotCount + tech.nailBotCount + tech.foamBotCount + tech.boomBotCount + tech.orbitBotCount - //remove all bots - tech.dynamoBotCount = 0 - tech.laserBotCount = 0 - tech.nailBotCount = 0 - tech.foamBotCount = 0 - tech.boomBotCount = 0 - tech.orbitBotCount = 0 - for (let i = 0; i < bullet.length; i++) { - if (bullet[i].botType && bullet[i].endCycle === Infinity) bullet[i].endCycle = 0 //don't remove temp bots - } - //set to a new type - options = [() => { tech.laserBotCount = countPermanent }, () => { tech.nailBotCount = countPermanent }, () => { tech.foamBotCount = countPermanent }, () => { tech.boomBotCount = countPermanent }, () => { tech.orbitBotCount = countPermanent }, () => { tech.dynamoBotCount = countPermanent }, ] - options[tech.botSwapCycleIndex]() - tech.botSwapCycleIndex++ - if (tech.botSwapCycleIndex > options.length - 1) tech.botSwapCycleIndex = 0 - b.respawnBots() - } }, zoom: null, zoomScale: 1000, diff --git a/js/spawn.js b/js/spawn.js index f42f68c..3a6c6ea 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -82,6 +82,7 @@ const spawn = { } } }, + randomLevelBoss(x, y, options = ["orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss"]) { // other bosses: suckerBoss, laserBoss, tetherBoss, //these need a particular level to work so they are not included in the random pool spawn[options[Math.floor(Math.random() * options.length)]](x, y) @@ -1355,7 +1356,7 @@ const spawn = { me.isBoss = true; me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front Matter.Body.rotate(me, Math.random() * Math.PI * 2); - me.accelMag = 0.00022 * Math.sqrt(simulation.accelScale); + me.accelMag = 0.00018 * Math.sqrt(simulation.accelScale); me.seePlayerFreq = Math.floor(30 * simulation.lookFreqScale); me.memory = 420; me.restitution = 1; @@ -1467,7 +1468,7 @@ const spawn = { // hitting player if (best.who === player) { if (m.immuneCycle < m.cycle) { - const dmg = 0.001 * simulation.dmgScale; + const dmg = 0.002 * simulation.dmgScale; m.damage(dmg); //draw damage ctx.fillStyle = color; @@ -1477,9 +1478,7 @@ const spawn = { } } //draw beam - if (best.dist2 === Infinity) { - best = look; - } + if (best.dist2 === Infinity) best = look; ctx.beginPath(); ctx.moveTo(this.vertices[1].x, this.vertices[1].y); ctx.lineTo(best.x, best.y); @@ -1948,11 +1947,20 @@ const spawn = { me.frictionStatic = 0; me.friction = 0; me.frictionAir = 0.01; + me.memory = Infinity; // me.memory = 300; // Matter.Body.setDensity(me, 0.0015); //extra dense //normal is 0.001 me.collisionFilter.mask = cat.player | cat.bullet spawn.shield(me, x, y, 1); - spawn.spawnOrbitals(me, radius + 150 + 250 * Math.random(), 1) + + + const len = Math.floor(Math.min(15, 3 + Math.sqrt(simulation.difficulty))) // simulation.difficulty = 40 on hard mode level 10 + const speed = (0.007 + 0.003 * Math.random() + 0.004 * Math.sqrt(simulation.difficulty)) + let radiusOrbitals = radius + 125 + 350 * Math.random() + for (let i = 0; i < len; i++) spawn.orbital(me, radiusOrbitals, i / len * 2 * Math.PI, speed) + radiusOrbitals = radius + 125 + 350 * Math.random() + for (let i = 0; i < len; i++) spawn.orbital(me, radiusOrbitals, i / len * 2 * Math.PI, -speed) + me.onDeath = function() { powerUps.spawnBossPowerUp(this.position.x, this.position.y) }; @@ -2570,8 +2578,8 @@ const spawn = { me.memory = 20; Matter.Body.setDensity(me, 0.001 + 0.0005 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger spawn.shield(me, x, y, 1); - spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random()) + setTimeout(() => { spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random()) }, 100); //have to wait a sec so the tether constraint doesn't attach to an orbital me.onDeath = function() { powerUps.spawnBossPowerUp(this.position.x, this.position.y) this.removeCons(); //remove constraint @@ -2677,7 +2685,7 @@ const spawn = { }, orbital(who, radius, phase, speed) { // for (let i = 0, len = 7; i < len; i++) spawn.orbital(me, radius + 250, 2 * Math.PI / len * i) - mobs.spawn(0, 0, 8, 12, "rgb(255,0,150)"); + mobs.spawn(who.position.x, who.position.y, 8, 12, "rgb(255,0,150)"); let me = mob[mob.length - 1]; me.stroke = "transparent"; // Matter.Body.setDensity(me, 0.00004); //normal is 0.001 @@ -2701,11 +2709,10 @@ const spawn = { } Matter.Body.setPosition(this, Vector.add(who.position, Vector.mult(orbit, radius))) //bullets move with player //damage player - if (Matter.Query.collides(this, [player]).length > 0) { - m.damage(0.1 * simulation.dmgScale); + if (Matter.Query.collides(this, [player]).length > 0 && !m.isCloak) { + m.damage(0.035 * simulation.dmgScale); this.death(); } - }; }, orbitalBoss(x, y, radius = 88) { diff --git a/js/tech.js b/js/tech.js index fbdc75d..4c7c1f5 100644 --- a/js/tech.js +++ b/js/tech.js @@ -46,7 +46,7 @@ tech.junk[index].numberInPool++ tech.tech.push(Object.assign({}, tech.junk[index])) // push a "clone" of the tech.junk into the pool - if (tech.junk[index].numberInPool > 1) tech.tech[tech.tech.length - 1].name += `(${tech.junk[index].numberInPool})` //give it a unique name so it can be found + if (tech.junk[index].numberInPool > 1) tech.tech[tech.tech.length - 1].name += ` - ${(tech.junk[index].numberInPool + 9).toString(36)}` //give it a unique name so it can be found } }, removeJunkTechFromPool() { @@ -127,7 +127,7 @@ if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.25 if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2 if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.4, player.speed * 0.013) - if (tech.isBotDamage) dmg *= 1 + 0.06 * tech.totalBots() + if (tech.isBotDamage) dmg *= 1 + 0.06 * b.totalBots() return dmg * tech.slowFire * tech.aimDamage }, duplicationChance() { @@ -144,9 +144,6 @@ spawn.randomLevelBoss(m.pos.x, m.pos.y - range, bossOptions); } }, - totalBots() { - return tech.dynamoBotCount + tech.foamBotCount + tech.nailBotCount + tech.laserBotCount + tech.boomBotCount + tech.orbitBotCount + tech.plasmaBotCount + tech.missileBotCount - }, tech: [{ name: "integrated armament", description: `increase damage by 25%
your inventory can only hold 1 gun`, @@ -158,7 +155,6 @@ requires: "no more than 1 gun", effect() { tech.isOneGun = true; - // for (let i = 0; i < tech.tech.length; i++) { if (tech.tech[i].name === "CPT gun") tech.tech[i].description = `adds the CPT gun to your inventory
it rewinds your health, velocity, and position
replaces your current gun
` } @@ -710,7 +706,7 @@ maxCount: 1, count: 0, allowed() { - return (tech.totalBots() > 1 || tech.haveGunCheck("drones") || tech.haveGunCheck("mine") || tech.haveGunCheck("spores") || m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing") && !tech.isEnergyHealth + return (b.totalBots() > 1 || tech.haveGunCheck("drones") || tech.haveGunCheck("mine") || tech.haveGunCheck("spores") || m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing") && !tech.isEnergyHealth }, requires: "drones, spores, mines, or bots", effect() { @@ -742,7 +738,7 @@ maxCount: 3, count: 0, allowed() { - return tech.totalBots() > 0 && !tech.sporesOnDeath && !tech.nailsDeathMob && !tech.isExplodeMob + return b.totalBots() > 0 && !tech.sporesOnDeath && !tech.nailsDeathMob && !tech.isExplodeMob }, requires: "a bot and no other mob death tech", effect() { @@ -757,6 +753,7 @@ description: "a bot fires nails at mobs in line of sight", maxCount: 9, count: 0, + isBotTech: true, allowed() { return true }, @@ -771,15 +768,16 @@ }, { name: "nail-bot upgrade", - description: "500% increased fire rate
applies to all current and future nail-bots", + description: "convert all your permanent bots to nail-bots
500% increased nail-bot fire rate", maxCount: 1, count: 0, allowed() { - return tech.nailBotCount > 1 + return tech.nailBotCount > 1 && !b.hasBotUpgrade() }, - requires: "2 or more nail bots", + requires: "2 or more nail bots and only 1 bot upgrade", effect() { tech.isNailBotUpgrade = true + b.convertBotsTo("nailBotCount") for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'nail') bullet[i].isUpgraded = true } @@ -796,6 +794,7 @@ description: "a bot fires foam at nearby mobs", maxCount: 9, count: 0, + isBotTech: true, allowed() { return true }, @@ -810,15 +809,16 @@ }, { name: "foam-bot upgrade", - description: "250% increased foam size and fire rate
applies to all current and future foam-bots", + description: "convert all your permanent bots to foam-bots
250% increased foam-bot size and fire rate", maxCount: 1, count: 0, allowed() { - return tech.foamBotCount > 1 + return tech.foamBotCount > 1 && !b.hasBotUpgrade() }, - requires: "2 or more foam bots", + requires: "2 or more foam bots and only 1 bot upgrade", effect() { tech.isFoamBotUpgrade = true + b.convertBotsTo("foamBotCount") for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'foam') bullet[i].isUpgraded = true } @@ -835,6 +835,7 @@ description: "a bot defends the space around you
ignites an explosion after hitting a mob", maxCount: 9, count: 0, + isBotTech: true, allowed() { return true }, @@ -849,15 +850,16 @@ }, { name: "boom-bot upgrade", - description: "250% increased explosion damage and size
applies to all current and future boom-bots", + description: "convert all your permanent bots to boom-bots
250% increased explosion damage and size", maxCount: 1, count: 0, allowed() { - return tech.boomBotCount > 1 + return tech.boomBotCount > 1 && !b.hasBotUpgrade() }, - requires: "2 or more boom bots", + requires: "2 or more boom bots and only 1 bot upgrade", effect() { tech.isBoomBotUpgrade = true + b.convertBotsTo("boomBotCount") for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'boom') bullet[i].isUpgraded = true } @@ -874,6 +876,7 @@ description: "a bot uses energy to emit a laser beam
that targets nearby mobs", maxCount: 9, count: 0, + isBotTech: true, allowed() { return m.maxEnergy > 0.5 }, @@ -888,15 +891,16 @@ }, { name: "laser-bot upgrade", - description: "400% increased laser damage
applies to all current and future laser-bots", + description: "convert all your permanent bots to laser-bots
400% increased laser-bot laser damage", maxCount: 1, count: 0, allowed() { - return tech.laserBotCount > 1 + return tech.laserBotCount > 1 && !b.hasBotUpgrade() }, - requires: "2 or more laser bots", + requires: "2 or more laser bots and only 1 bot upgrade", effect() { tech.isLaserBotUpgrade = true + b.convertBotsTo("laserBotCount") for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'laser') bullet[i].isUpgraded = true } @@ -913,6 +917,7 @@ description: "a bot is locked in orbit around you
stuns and damages mobs on contact", maxCount: 9, count: 0, + isBotTech: true, allowed() { return true }, @@ -927,15 +932,16 @@ }, { name: "orbital-bot upgrade", - description: "increase damage by 200% and radius by 30%
applies to all current and future orbit-bots", + description: "convert all your permanent bots to orbital-bots
increase damage by 200% and radius by 30%", maxCount: 1, count: 0, allowed() { - return tech.orbitBotCount > 1 + return tech.orbitBotCount > 1 && !b.hasBotUpgrade() }, - requires: "2 or more orbital bots", + requires: "2 or more orbital bots and only 1 bot upgrade", effect() { tech.isOrbitBotUpgrade = true + b.convertBotsTo("orbitBotCount") const range = 190 + 60 * tech.isOrbitBotUpgrade for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'orbit') { @@ -962,6 +968,7 @@ description: "a bot damages mobs while it traces your path
regen 6 energy per second when it's near", maxCount: 9, count: 0, + isBotTech: true, allowed() { return true }, @@ -976,15 +983,16 @@ }, { name: "dynamo-bot upgrade", - description: "dynamo-bots regen 24 energy per second
applies to all current and future dynamo-bots", + description: "convert your permanent bots to dynamo-bots
dynamo-bots regen 24 energy per second", maxCount: 1, count: 0, allowed() { - return tech.dynamoBotCount > 1 + return tech.dynamoBotCount > 1 && !b.hasBotUpgrade() }, - requires: "2 or more dynamo bots", + requires: "2 or more dynamo bots and only 1 bot upgrade", effect() { tech.isDynamoBotUpgrade = true + b.convertBotsTo("dynamoBotCount") for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'dynamo') bullet[i].isUpgraded = true } @@ -1014,33 +1022,13 @@ tech.isRerollBots = false; } }, - { - name: "electroactive polymers", - description: "build 2 random bots
switching guns cycles bots to the same type", - maxCount: 1, - isNonRefundable: true, - count: 0, - allowed() { - return tech.totalBots() > 2 && b.inventory.length > 1 - }, - requires: "at least 3 bots and 2 guns", - effect() { - tech.isBotSwap = true - b.randomBot() - b.randomBot() - }, - remove() { - tech.isBotSwap = false - tech.botSwapCycleIndex = 0 - } - }, { name: "perimeter defense", description: "reduce harm by 6%
for each of your permanent bots", maxCount: 1, count: 0, allowed() { - return tech.totalBots() > 3 && !tech.isEnergyHealth + return b.totalBots() > 3 && !tech.isEnergyHealth }, requires: "at least 4 bots", effect() { @@ -1055,7 +1043,7 @@ maxCount: 1, count: 0, allowed() { - return tech.totalBots() > 3 + return b.totalBots() > 3 }, requires: "at least 4 bots", effect() { @@ -1073,7 +1061,7 @@ isNonRefundable: true, isExperimentHide: true, allowed() { - return tech.totalBots() > 3 + return b.totalBots() > 3 }, requires: "at least 4 bots", effect() { @@ -1836,6 +1824,22 @@ tech.isImmortal = false; } }, + { + name: "many-worlds", + description: "on each new level enter an alternate reality
find 2 tech power ups in that reality", + maxCount: 1, + count: 0, + allowed() { + return tech.isImmortal + }, + requires: "quantum immortality", + effect() { + tech.isSwitchReality = true; + }, + remove() { + tech.isSwitchReality = false; + } + }, { name: "bubble fusion", description: "after destroying a mob's shield
spawn 1-2 heals, ammo, or research", @@ -2096,9 +2100,9 @@ isExperimentHide: true, count: 0, allowed() { - return powerUps.research.count === 0 && level.onLevel < 6 + return level.onLevel < 8 && level.onLevel > 0 }, - requires: "no research, and in the first 5 levels", + requires: "between levels 1 and 7", effect() { level.difficultyDecrease(simulation.difficultyMode) simulation.makeTextLog(`simulation.difficultyMode--`) @@ -2183,7 +2187,7 @@ } }, { - name: "many-worlds", + name: "ansatz", description: "after choosing a field, tech, or gun
if you have no research spawn 2", maxCount: 1, count: 0, @@ -2306,7 +2310,7 @@ maxCount: 1, count: 0, allowed() { - return (tech.totalBots() > 5 || m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" || m.fieldUpgrades[m.fieldMode].name === "plasma torch" || m.fieldUpgrades[m.fieldMode].name === "pilot wave") && !tech.isEnergyHealth && !tech.isRewindAvoidDeath //build.isExperimentSelection || + return (b.totalBots() > 5 || m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" || m.fieldUpgrades[m.fieldMode].name === "plasma torch" || m.fieldUpgrades[m.fieldMode].name === "pilot wave") && !tech.isEnergyHealth && !tech.isRewindAvoidDeath //build.isExperimentSelection || }, requires: "bots > 5, plasma torch, nano-scale, pilot wave, not mass-energy equivalence, CPT", effect() { @@ -2933,6 +2937,7 @@ isGunTech: true, maxCount: 1, count: 0, + isBotTech: true, allowed() { return tech.haveGunCheck("missiles") }, @@ -3597,7 +3602,7 @@ }, requires: "standing wave harmonics", effect() { - tech.blockDmg += 0.75 //if you change this value also update the for loop in the electricity graphics in m.pushMass + tech.blockDmg += 1.25 //if you change this value also update the for loop in the electricity graphics in m.pushMass }, remove() { tech.blockDmg = 0; @@ -3605,7 +3610,7 @@ }, { name: "frequency resonance", - description: "standing wave harmonics shield is retuned
increase size and blocking efficiency by 40%", + description: "standing wave harmonics shield is retuned
increase size and blocking efficiency by 50%", isFieldTech: true, maxCount: 9, count: 0, @@ -3614,8 +3619,8 @@ }, requires: "standing wave harmonics", effect() { - m.fieldRange += 175 * 0.2 - m.fieldShieldingScale *= 0.55 + m.fieldRange += 175 * 0.25 + m.fieldShieldingScale *= 0.5 }, remove() { m.fieldRange = 175; @@ -3624,38 +3629,21 @@ }, { name: "flux pinning", - description: "blocking with perfect diamagnetism
stuns mobs for +1 second", + description: "blocking with your field
stuns mobs for +2 second", isFieldTech: true, maxCount: 9, count: 0, allowed() { - return m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" + return m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" || m.fieldUpgrades[m.fieldMode].name === "standing wave harmonics" || m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" }, - requires: "perfect diamagnetism", + requires: "a field that can block", effect() { - tech.isStunField += 60; + tech.isStunField += 120; }, remove() { tech.isStunField = 0; } }, - { - name: "eddy current brake", - description: "your stored energy projects a field that
limits the top speed of mobs", - isFieldTech: true, - maxCount: 1, - count: 0, - allowed() { - return m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" - }, - requires: "perfect diamagnetism", - effect() { - tech.isPerfectBrake = true; - }, - remove() { - tech.isPerfectBrake = false; - } - }, { name: "fracture analysis", description: "bullet impacts do 400% damage
to stunned mobs", @@ -3673,6 +3661,23 @@ tech.isCrit = false; } }, + { + name: "eddy current brake", + description: "your stored energy projects a field that
limits the top speed of mobs", + isFieldTech: true, + maxCount: 1, + count: 0, + allowed() { + return m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" + }, + requires: "perfect diamagnetism", + effect() { + tech.isPerfectBrake = true; + }, + remove() { + tech.isPerfectBrake = false; + } + }, { name: "pair production", description: "picking up a power up gives you 250 energy", @@ -3955,6 +3960,7 @@ isFieldTech: true, maxCount: 1, count: 0, + isBotTech: true, allowed() { return m.fieldUpgrades[m.fieldMode].name === "plasma torch" }, @@ -4323,6 +4329,46 @@ // }, // remove() {} // }, + { + name: "sliders", + description: "become an alternate version of yourself
every 20 seconds", + maxCount: 1, + count: 0, + numberInPool: 0, + isNonRefundable: true, + isExperimentHide: true, + isJunk: true, + allowed() { + return true + }, + requires: "", + effect() { + setInterval(() => { + m.switchWorlds() + }, 20000); //every 30 sections + }, + remove() {} + }, + { + name: "pop-ups", + description: "sign up to learn endless easy ways to win n-gon
that landgreen doesn't want you to know about!!!1!!", + maxCount: 1, + count: 0, + numberInPool: 0, + isNonRefundable: true, + isExperimentHide: 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 sections + }, + remove() {} + }, { name: "music", description: "add music to n-gon", @@ -4882,11 +4928,11 @@ isExperimentHide: true, isJunk: true, allowed() { - return tech.totalBots() > 2 + return b.totalBots() > 2 }, requires: "at least 3 bots", effect() { - const total = tech.totalBots(); + const total = b.totalBots(); tech.dynamoBotCount = 0; tech.nailBotCount = 0; tech.laserBotCount = 0; @@ -5258,8 +5304,7 @@ isBlockPowerUps: null, isBlockHarm: null, foamFutureFire: null, - isBotSwap: null, - botSwapCycleIndex: null, isDamageAfterKill: null, - isHarmReduceAfterKill: null + isHarmReduceAfterKill: null, + isSwitchReality: null } \ No newline at end of file diff --git a/todo.txt b/todo.txt index c9ad888..e0d07ed 100644 --- a/todo.txt +++ b/todo.txt @@ -1,13 +1,11 @@ ******************************************************** NEXT PATCH ******************************************************** -mob effect: freeze - now only slows mobs down - all freeze effects are about 50% longer +many worlds renamed to ansatz +new tech many-worlds: at the start of each new level switch realities -junk tech: music - adds background music to n-gon -junk tech: performance - adds fps tracker to n-gon - -tech: dormancy - if a mob has died in the last 5 seconds increase damage by 50% else decrease damage by 50% -tech: torpor - if a mob has died in the last 5 seconds reduce harm by 66% else increase harm by 33% +removed tech: electroactive polymers - convert bots to the same type on weapon swap +all bot upgrades convert current bots to the upgraded type + only one bot upgrade allowed ******************************************************** BUGS ******************************************************** @@ -37,7 +35,6 @@ use the floor of portal sensor on the player? to unstuck player ******************************************************** TODO ******************************************************** - decrease healing effects by 50% decrease level scaling healing reduction net effect: healing at difficulty 40 (level 10 hard) should be 25% higher then current levels @@ -373,7 +370,7 @@ n-gon outreach ideas ******************************************************** LORE ******************************************************** cool names for tech - strange loop, ansatz, perturbation theory + strange loop, perturbation theory voice singing with pitch?