From 66f2cce2b7a45e255b071d5373566ff36ce21022 Mon Sep 17 00:00:00 2001 From: landgreen Date: Fri, 29 Jan 2021 05:13:44 -0800 Subject: [PATCH] cloning tech: cloning - chance to spawn another level boss = 3x your duplication chance tech: dynamo-bot: a bot follows your history, damages mobs, and regens energy when it gets close tech: dynamo upgrade: more energy regen --- js/bullet.js | 129 +++++++++++++++++++++++++++++++++++++++++++---- js/index.js | 2 +- js/level.js | 102 +++++++++++++++++++++---------------- js/player.js | 8 +-- js/simulation.js | 3 +- js/spawn.js | 14 ++--- js/tech.js | 94 ++++++++++++++++++++++++++++++---- todo.txt | 46 ++++------------- 8 files changed, 289 insertions(+), 109 deletions(-) diff --git a/js/bullet.js b/js/bullet.js index 1789b7e..6480b49 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -1713,7 +1713,7 @@ const b = { friction: 0, frictionAir: 0.025, thrust: (tech.isFastSpores ? 0.001 : 0.0004) * (1 + 0.3 * (Math.random() - 0.5)), - dmg: tech.isMutualism ? 10 : 4, //2x bonus damage from tech.isMutualism + dmg: tech.isMutualism ? 12 : 5, //bonus damage from tech.isMutualism lookFrequency: 100 + Math.floor(117 * Math.random()), classType: "bullet", collisionFilter: { @@ -1722,7 +1722,7 @@ const b = { }, endCycle: simulation.cycle + Math.floor((600 + Math.floor(Math.random() * 420)) * tech.isBulletsLastLonger), minDmgSpeed: 0, - playerOffPosition: { //used when following player to keep spores separate + playerOffPosition: { //used when moving towards player to keep spores separate x: 100 * (Math.random() - 0.5), y: 100 * (Math.random() - 0.5) }, @@ -2223,6 +2223,7 @@ const b = { // ************************************************************************************************** // ************************************************************************************************** respawnBots() { + for (let i = 0; i < tech.dynamoBotCount; i++) b.dynamoBot({ x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) }, false) for (let i = 0; i < tech.laserBotCount; i++) b.laserBot({ x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) }, false) for (let i = 0; i < tech.nailBotCount; i++) b.nailBot({ x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) }, false) for (let i = 0; i < tech.foamBotCount; i++) b.foamBot({ x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) }, false) @@ -2237,7 +2238,10 @@ const b = { } }, randomBot(where = m.pos, isKeep = true, isAll = true) { - if (Math.random() < 0.2 && isAll) { + if (Math.random() < 0.167 && isAll) { + b.dynamoBot(where) + if (isKeep) tech.dynamoBotCount++; + } else if (Math.random() < 0.25 && isAll) { b.laserBot(where) if (isKeep) tech.laserBotCount++; } else if (Math.random() < 0.25 && isAll) { @@ -2254,6 +2258,113 @@ const b = { if (isKeep) tech.boomBotCount++; } }, + setDynamoBotDelay() { + //reorder orbital bot positions around a circle + let total = 0 + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType === 'dynamo') total++ + } + let count = 0 + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType === 'dynamo') { + count++ + const step = Math.max(60 - 3 * total, 20) + bullet[i].followDelay = (step * count) % 600 + } + } + }, + dynamoBot(position = m.pos, isConsole = true) { + if (isConsole) simulation.makeTextLog(`b.dynamoBot()`); + const me = bullet.length; + bullet[me] = Bodies.polygon(position.x, position.y, 5, 10, { + isUpgraded: tech.isDynamoBotUpgrade, + botType: "dynamo", + friction: 0, + frictionStatic: 0, + frictionAir: 1, + isStatic: true, + isSensor: true, + restitution: 0, + dmg: 0, // 0.14 //damage done in addition to the damage from momentum + minDmgSpeed: 0, + endCycle: Infinity, + classType: "bullet", + collisionFilter: { + category: cat.bullet, + mask: 0 //cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield + }, + beforeDmg() {}, + onEnd() { + b.setDynamoBotDelay() + }, + followDelay: 0, + phase: Math.floor(60 * Math.random()), + do() { + // if (Vector.magnitude(Vector.sub(this.position, m.pos)) < 150) { + // ctx.fillStyle = "rgba(0,0,0,0.06)"; + // ctx.beginPath(); + // 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, m.pos)) < 250) { //give energy + // Matter.Body.setAngularVelocity(this, 10) + if (this.isUpgraded) { + m.energy += 0.06 + 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.02 + 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 + } + }) + for (let i = 0; i < q.length; i++) { + // 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 + } + }) + World.add(engine.world, bullet[me]); //add bullet to world + b.setDynamoBotDelay() + }, nailBot(position = { x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) }, isConsole = true) { if (isConsole) simulation.makeTextLog(`b.nailBot()`); const me = bullet.length; @@ -2435,7 +2546,7 @@ const b = { drainThreshold: tech.isEnergyHealth ? 0.5 : 0.33, acceleration: 0.0015 * (1 + 0.3 * Math.random()), range: 700 * (1 + 0.1 * Math.random()) + 300 * tech.isLaserBotUpgrade, - followRange: 150 + Math.floor(30 * Math.random()), + playerRange: 150 + Math.floor(30 * Math.random()), offPlayer: { x: 0, y: 0, @@ -2453,7 +2564,7 @@ const b = { onEnd() {}, do() { const playerPos = Vector.add(Vector.add(this.offPlayer, m.pos), Vector.mult(player.velocity, 20)) //also include an offset unique to this bot to keep many bots spread out - const farAway = Math.max(0, (Vector.magnitude(Vector.sub(this.position, playerPos))) / this.followRange) //linear bounding well + const farAway = Math.max(0, (Vector.magnitude(Vector.sub(this.position, playerPos))) / this.playerRange) //linear bounding well const mag = Math.min(farAway, 4) * this.mass * this.acceleration this.force = Vector.mult(Vector.normalise(Vector.sub(playerPos, this.position)), mag) //manual friction to not lose rotational velocity @@ -3520,13 +3631,13 @@ const b = { name: "spores", description: "fire a sporangium that discharges spores
spores seek out nearby mobs", ammo: 0, - ammoPack: 3, + ammoPack: 3.5, have: false, fire() { const me = bullet.length; const dir = m.angle; bullet[me] = Bodies.polygon(m.pos.x + 30 * Math.cos(m.angle), m.pos.y + 30 * Math.sin(m.angle), 20, 4.5, b.fireAttributes(dir, false)); - b.fireProps(m.crouch ? 50 : 30, m.crouch ? 30 : 16, dir, me); //cd , speed + b.fireProps(m.crouch ? 45 : 25, m.crouch ? 30 : 16, dir, me); //cd , speed Matter.Body.setDensity(bullet[me], 0.000001); bullet[me].endCycle = Infinity; bullet[me].frictionAir = 0; @@ -3683,10 +3794,10 @@ const b = { name: "foam", description: "spray bubbly foam that sticks to mobs
slows mobs and does damage over time", ammo: 0, - ammoPack: 35, + ammoPack: 36, have: false, fire() { - m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 20 : 6) * b.fireCD); // cool down + m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 15 : 5) * b.fireCD); // cool down const radius = (m.crouch ? 10 + 5 * Math.random() : 4 + 6 * Math.random()) + (tech.isAmmoFoamSize && this.ammo < 300) * 12 const SPEED = 18 - radius * 0.4; const dir = m.angle + 0.2 * (Math.random() - 0.5) diff --git a/js/index.js b/js/index.js index 4a8fdef..15c0cff 100644 --- a/js/index.js +++ b/js/index.js @@ -857,7 +857,7 @@ window.addEventListener("keydown", function(event) { x: 0, y: 0 }); - // move bots to follow player + // move bots to player for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType) { Matter.Body.setPosition(bullet[i], Vector.add(player.position, { diff --git a/js/level.js b/js/level.js index e9f25be..a220bf1 100644 --- a/js/level.js +++ b/js/level.js @@ -19,7 +19,7 @@ const level = { // m.setField("plasma torch") // b.giveGuns("nail gun") // tech.isExplodeRadio = true - // tech.giveTech("needle gun") + for (let i = 0; i < 1; i++) tech.giveTech("dynamo-bot") // tech.giveTech("supercritical fission") // tech.giveTech("irradiated nails") // tech.giveTech("cardinality") @@ -299,9 +299,10 @@ const level = { // spawn.laserTargetingBoss(1600, -400) // spawn.striker(1600, -500) // spawn.shooter(1700, -120) - spawn.bomberBoss(1400, -500) + // spawn.bomberBoss(1400, -500) // spawn.sniper(1800, -120) // spawn.cellBossCulture(1600, -500) + // spawn.cellBossCulture(1600, -500) // spawn.streamBoss(1600, -500) // spawn.beamer(1200, -500) // spawn.shield(mob[mob.length - 1], 1800, -120, 1); @@ -348,6 +349,7 @@ const level = { // spawn.randomBoss(1700, -900, 0.4); // if (simulation.difficulty > 3) spawn.randomLevelBoss(2200, -1300); powerUps.addRerollToLevel() //needs to run after mobs are spawned + // if (tech.isDuplicateBoss && Math.random() < 3 * tech.duplicationChance()) spawn.randomLevelBoss(4800, -500); }, final() { level.bossKilled = false; // if a boss needs to be killed @@ -398,6 +400,7 @@ const level = { spawn.mapRect(5700, -3300, 1800, 5100); //right wall spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump spawn.mapRect(5425, -650, 375, 450); //blocking exit + if (tech.isDuplicateBoss && Math.random() < 3 * tech.duplicationChance()) spawn.randomLevelBoss(4800, -500); }, gauntlet() { level.bossKilled = true; //if there is no boss this needs to be true to increase levels @@ -460,6 +463,7 @@ const level = { } } powerUps.addRerollToLevel() //needs to run after mobs are spawned + if (tech.isDuplicateBoss && Math.random() < 3 * tech.duplicationChance()) spawn.randomLevelBoss(4125, -350); }, intro() { level.bossKilled = true; //if there is no boss this needs to be true to increase levels @@ -636,45 +640,45 @@ const level = { spawn.wireKneeLeft(); spawn.wireHead(); } else { - const say = [] - if (localSettings.runCount > 200) { //experienced - say.push( - "I've been here before...", - "How many times have I done this?", - ) - } else if (localSettings.runCount < 20) { //new - say.push( - "Am I still alive?", - "And I'm back here again...", - "Is this another simulation?", - "I'm alive...", - "Last time was a simulation. Is this one a simulation too?", - ) - } - if (simulation.difficultyMode < 4 && localSettings.levelsClearedLastGame > 10) { //too easy - say.push( - "That felt too easy.
Maybe I should increase the difficulty of the simulation.", - "That was fun, but maybe I should increase the difficulty of the simulation.", - "I should increase the difficulty of the simulation, that didn't feel realistic.", - ) - } else if (simulation.difficultyMode > 3 && localSettings.levelsClearedLastGame > 10) { //great run on a hard or why - say.push( - "What do I do after I escape?", - "I'm almost ready to stop these simulations and actually escape.", - "I think I'm getting closer to something, but what?", - "I'm getting stronger.", - "What happens after I escape?", - "I found a good combination of technology last time." - ) - } else { //resolve - say.push( - "I'll try some different techs this time.", - "I've got to escape.", - "I'll find a way out.", - "I keep forgetting that these are just simulated escapes." - ) - } - simulation.makeTextLog(say[Math.floor(say.length * Math.random())], 1000) + // const say = [] + // if (localSettings.runCount > 200) { //experienced + // say.push( + // "I've been here before...", + // "How many times have I done this?", + // ) + // } else if (localSettings.runCount < 20) { //new + // say.push( + // "Am I still alive?", + // "And I'm back here again...", + // "Is this another simulation?", + // "I'm alive...", + // "Last time was a simulation. Is this one a simulation too?", + // ) + // } + // if (simulation.difficultyMode < 4 && localSettings.levelsClearedLastGame > 10) { //too easy + // say.push( + // "That felt too easy.
Maybe I should increase the difficulty of the simulation.", + // "That was fun, but maybe I should increase the difficulty of the simulation.", + // "I should increase the difficulty of the simulation, that didn't feel realistic.", + // ) + // } else if (simulation.difficultyMode > 3 && localSettings.levelsClearedLastGame > 10) { //great run on a hard or why + // say.push( + // "What do I do after I escape?", + // "I'm almost ready to stop these simulations and actually escape.", + // "I think I'm getting closer to something, but what?", + // "I'm getting stronger.", + // "What happens after I escape?", + // "I found a good combination of technology last time." + // ) + // } else { //resolve + // say.push( + // "I'll try some different techs this time.", + // "I've got to escape.", + // "I'll find a way out.", + // "I keep forgetting that these are just simulated escapes." + // ) + // } + // simulation.makeTextLog(say[Math.floor(say.length * Math.random())], 1000) const swapPeriod = 150 const len = 30 @@ -695,6 +699,7 @@ const level = { } } powerUps.spawnStartingPowerUps(2300, -150); + if (tech.isDuplicateBoss && Math.random() < 3 * tech.duplicationChance()) spawn.randomLevelBoss(1900, -675); }, testChamber() { level.setPosToSpawn(0, -50); //lower start @@ -768,7 +773,6 @@ const level = { } } - buttonDoor.query(); buttonDoor.draw(); if (buttonDoor.isUp) { @@ -961,6 +965,7 @@ const level = { } } powerUps.addRerollToLevel() //needs to run after mobs are spawned + if (tech.isDuplicateBoss && Math.random() < 3 * tech.duplicationChance()) spawn.randomLevelBoss(1925, -1250); }, sewers() { level.bossKilled = false; // if a boss needs to be killed @@ -1106,6 +1111,7 @@ const level = { spawn.randomMob(2825, 400, 0.9); if (simulation.difficulty > 3) spawn.randomLevelBoss(6000, 2300, ["spiderBoss", "launcherBoss", "laserTargetingBoss", "streamBoss"]); powerUps.addRerollToLevel() //needs to run after mobs are spawned + if (tech.isDuplicateBoss && Math.random() < 3 * tech.duplicationChance()) spawn.randomLevelBoss(7725, 2275); }, satellite() { level.bossKilled = false; // if a boss needs to be killed @@ -1312,6 +1318,7 @@ const level = { } } powerUps.addRerollToLevel() //needs to run after mobs are spawned + if (tech.isDuplicateBoss && Math.random() < 3 * tech.duplicationChance()) spawn.randomLevelBoss(3950, -850); }, rooftops() { level.bossKilled = false; // if a boss needs to be killed @@ -1535,6 +1542,7 @@ const level = { spawn.randomBoss(4900, -1200, 0); if (simulation.difficulty > 3) spawn.randomLevelBoss(3200, -2050); powerUps.addRerollToLevel() //needs to run after mobs are spawned + if (tech.isDuplicateBoss && Math.random() < 3 * tech.duplicationChance()) spawn.randomLevelBoss(2175, -2425); }, aerie() { level.bossKilled = false; // if a boss needs to be killed @@ -1744,6 +1752,7 @@ const level = { } } powerUps.addRerollToLevel() //needs to run after mobs are spawned + if (tech.isDuplicateBoss && Math.random() < 3 * tech.duplicationChance()) spawn.randomLevelBoss(5350, -325); }, skyscrapers() { level.bossKilled = false; // if a boss needs to be killed @@ -1905,6 +1914,7 @@ const level = { spawn.randomBoss(1700, -900, 0.4); if (simulation.difficulty > 3) spawn.randomLevelBoss(2600, -2300); powerUps.addRerollToLevel() //needs to run after mobs are spawned + if (tech.isDuplicateBoss && Math.random() < 3 * tech.duplicationChance()) spawn.randomLevelBoss(3075, -2050); }, highrise() { level.bossKilled = false; // if a boss needs to be killed @@ -2104,6 +2114,7 @@ const level = { if (simulation.difficulty > 3) spawn.randomLevelBoss(-2400, -3000); powerUps.addRerollToLevel() //needs to run after mobs are spawned + if (tech.isDuplicateBoss && Math.random() < 3 * tech.duplicationChance()) spawn.randomLevelBoss(-1825, -1975); }, warehouse() { level.bossKilled = false; // if a boss needs to be killed @@ -2275,10 +2286,12 @@ const level = { if (Math.random() < 0.25) { spawn.randomLevelBoss(-800, -1300) } else { - spawn.snakeBoss(-1000 + Math.random() * 1500, -2200); //boss snake with head + spawn.snakeBoss(-1000 + Math.random() * 2500, -1300); //boss snake with head } } powerUps.addRerollToLevel() //needs to run after mobs are spawned + + if (tech.isDuplicateBoss && Math.random() < 3 * tech.duplicationChance()) spawn.randomLevelBoss(300, -800); }, office() { let button, door @@ -2478,6 +2491,7 @@ const level = { } } powerUps.addRerollToLevel() //needs to run after mobs are spawned + if (tech.isDuplicateBoss && Math.random() < 3 * tech.duplicationChance()) spawn.randomLevelBoss(1875, -675); }, stronghold() { // player made level by Francois 👑 from discord level.custom = () => { @@ -4452,7 +4466,7 @@ const level = { } let v = Vector.mult(this.portalPair.unit, mag) Matter.Body.setVelocity(player, v); - // move bots to follow player + // move bots to player for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType) { // Matter.Body.setPosition(bullet[i], this.portalPair.portal.position); diff --git a/js/player.js b/js/player.js index 6162488..54ec8d5 100644 --- a/js/player.js +++ b/js/player.js @@ -52,7 +52,7 @@ const m = { }); World.add(engine.world, m.holdConstraint); }, - cycle: 300, //starts at 300 cycles instead of 0 to prevent bugs with m.history + cycle: 600, //starts at 600 cycles instead of 0 to prevent bugs with m.history lastKillCycle: 0, lastHarmCycle: 0, width: 50, @@ -467,7 +467,7 @@ const m = { }, displayHealth() { id = document.getElementById("health"); - // health display follows a x^1.5 rule to make it seem like the player has lower health, this makes the player feel more excitement + // health display is a x^1.5 rule to make it seem like the player has lower health, this makes the player feel more excitement id.style.width = Math.floor(300 * m.maxHealth * Math.pow(m.health / m.maxHealth, 1.4)) + "px"; //css animation blink if health is low if (m.health < 0.3) { @@ -556,7 +556,7 @@ const m = { // simulation.updateGunHUD(); // simulation.boldActiveGunHUD(); - // move bots to follow player + // move bots to player for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType) { Matter.Body.setPosition(bullet[i], Vector.add(player.position, { @@ -2540,7 +2540,7 @@ const m = { y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer }); m.immuneCycle = m.cycle + 15; //player is immune to collision damage - // move bots to follow player + // move bots to player for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType) { Matter.Body.setPosition(bullet[i], Vector.add(player.position, { diff --git a/js/simulation.js b/js/simulation.js index 4bd0387..aa0e867 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -530,9 +530,10 @@ const simulation = { if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod() if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod() } + tech.dynamoBotCount = 0; + tech.nailBotCount = 0; tech.laserBotCount = 0; tech.orbitBotCount = 0; - tech.nailBotCount = 0; tech.foamBotCount = 0; tech.boomBotCount = 0; tech.plasmaBotCount = 0; diff --git a/js/spawn.js b/js/spawn.js index 59824f7..9ea18ce 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -507,15 +507,17 @@ const spawn = { }; }, cellBossCulture(x, y, radius = 20, num = 5) { + const cellID = Math.random() for (let i = 0; i < num; i++) { - spawn.cellBoss(x, y, radius) + spawn.cellBoss(x, y, radius, cellID) } }, - cellBoss(x, y, radius = 20) { + cellBoss(x, y, radius = 20, cellID) { mobs.spawn(x + Math.random(), y + Math.random(), 20, radius * (1 + 1.2 * Math.random()), "rgba(0,150,155,0.7)"); let me = mob[mob.length - 1]; me.isBoss = true; me.isCell = true; + me.cellID = cellID me.accelMag = 0.00015 * simulation.accelScale; me.memory = 40; me.isVerticesChange = true @@ -531,7 +533,7 @@ const spawn = { me.split = function() { Matter.Body.scale(this, 0.4, 0.4); this.radius = Math.sqrt(this.mass * k / Math.PI) - spawn.cellBoss(this.position.x, this.position.y, this.radius); + spawn.cellBoss(this.position.x, this.position.y, this.radius, this.cellID); mob[mob.length - 1].health = this.health } me.onHit = function() { //run this function on hitting player @@ -571,9 +573,10 @@ const spawn = { }; me.onDeath = function() { this.isCell = false; - let count = 0 //count other cells + let count = 0 //count other cells by id + // console.log(this.cellID) for (let i = 0, len = mob.length; i < len; i++) { - if (mob[i].isCell) count++ + if (mob[i].isCell && mob[i].cellID === this.cellID) count++ } if (count < 1) { //only drop a power up if this is the last cell powerUps.spawnBossPowerUp(this.position.x, this.position.y) @@ -2420,7 +2423,6 @@ const spawn = { stiffness: 0.05 }); World.add(engine.world, consBB[consBB.length - 1]); - }, snakeBody(x, y, radius = 20) { mobs.spawn(x, y, 4, radius, "rgb(55,170,170)"); diff --git a/js/tech.js b/js/tech.js index e0ef900..7d43739 100644 --- a/js/tech.js +++ b/js/tech.js @@ -9,12 +9,6 @@ const tech = { lore.techCount = 0; tech.removeLoreTechFromPool(); tech.addLoreTechToPool(); - // tech.nailBotCount = 0; - // tech.foamBotCount = 0; - // tech.boomBotCount = 0; - // tech.laserBotCount = 0; - // tech.orbitalBotCount = 0; - // tech.plasmaBotCount = 0; tech.armorFromPowerUps = 0; tech.totalCount = 0; simulation.updateTechHUD(); @@ -116,7 +110,7 @@ const tech = { return (tech.isBayesian ? 0.2 : 0) + tech.cancelCount * 0.04 + tech.duplicateChance + m.duplicateChance }, totalBots() { - return tech.foamBotCount + tech.nailBotCount + tech.laserBotCount + tech.boomBotCount + tech.orbitBotCount + tech.plasmaBotCount + tech.missileBotCount + return tech.dynamoBotCount + tech.foamBotCount + tech.nailBotCount + tech.laserBotCount + tech.boomBotCount + tech.orbitBotCount + tech.plasmaBotCount + tech.missileBotCount }, tech: [{ name: "integrated armament", @@ -922,6 +916,45 @@ const tech = { } } }, + { + name: "dynamo-bot", + description: "a bot damages mobs while it traces your path
regen 4 energy per second when it's near", + maxCount: 9, + count: 0, + allowed() { + return true + }, + requires: "", + effect() { + tech.dynamoBotCount++; + b.dynamoBot(); + }, + remove() { + tech.dynamoBotCount -= this.count; + } + }, + { + name: "dynamo-bot upgrade", + description: "dynamo-bots regen 12 energy per second
applies to all current and future orbit-bots", + maxCount: 1, + count: 0, + allowed() { + return tech.dynamoBotCount > 1 + }, + requires: "2 or more dynamo bots", + effect() { + tech.isDynamoBotUpgrade = true + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType === 'dynamo') bullet[i].isUpgraded = true + } + }, + remove() { + tech.isDynamoBotUpgrade = false + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType === 'dynamo') bullet[i].isUpgraded = false + } + } + }, { name: "bot fabrication", description: "anytime you collect 5 research
use them to build a random bot", @@ -1076,7 +1109,7 @@ const tech = { }, requires: "", effect() { - tech.cyclicImmunity += 60 - this.count * 6; + tech.cyclicImmunity += 60; }, remove() { tech.cyclicImmunity = 0; @@ -1759,6 +1792,22 @@ const tech = { tech.isDupDamage = false; } }, + { + name: "cloning", + description: "each level has a chance to spawn a level boss
equal to triple your duplication chance", + maxCount: 1, + count: 0, + allowed() { + return tech.duplicationChance() > 0 + }, + requires: "some duplication chance", + effect() { + tech.isDuplicateBoss = true; + }, + remove() { + tech.isDuplicateBoss = false; + } + }, { name: "futures exchange", description: "clicking × to cancel a field, tech, or gun
adds 4% power up duplication chance", @@ -3535,6 +3584,7 @@ const tech = { b.nailBot() tech.nailBotCount++; } + simulation.makeTextLog(`tech.isNailBotUpgrade = true`) }) if (!tech.isFoamBotUpgrade) notUpgradedBots.push(() => { tech.giveTech("foam-bot upgrade") @@ -3543,6 +3593,7 @@ const tech = { b.foamBot() tech.foamBotCount++; } + simulation.makeTextLog(`tech.isFoamBotUpgrade = true`) }) if (!tech.isBoomBotUpgrade) notUpgradedBots.push(() => { tech.giveTech("boom-bot upgrade") @@ -3551,6 +3602,7 @@ const tech = { b.boomBot() tech.boomBotCount++; } + simulation.makeTextLog(`tech.isBoomBotUpgrade = true`) }) if (!tech.isLaserBotUpgrade) notUpgradedBots.push(() => { tech.giveTech("laser-bot upgrade") @@ -3559,6 +3611,7 @@ const tech = { b.laserBot() tech.laserBotCount++; } + simulation.makeTextLog(`tech.isLaserBotUpgrade = true`) }) if (!tech.isOrbitBotUpgrade) notUpgradedBots.push(() => { tech.giveTech("orbital-bot upgrade") @@ -3567,6 +3620,26 @@ const tech = { b.orbitBot() tech.orbitBotCount++; } + simulation.makeTextLog(`tech.isOrbitalBotUpgrade = true`) + }) + if (!tech.isDynamoBotUpgrade) notUpgradedBots.push(() => { + tech.giveTech("dynamo-bot upgrade") + tech.setTechoNonRefundable("dynamo-bot upgrade") + for (let i = 0; i < 2; i++) { + b.orbitBot() + tech.dynamoBotCount++; + } + simulation.makeTextLog(`tech.isDynamoBotUpgrade = true`) + }) + //double chance for dynamo-bot, since it's very good for nano-scale + if (!tech.isDynamoBotUpgrade) notUpgradedBots.push(() => { + tech.giveTech("dynamo-bot upgrade") + tech.setTechoNonRefundable("dynamo-bot upgrade") + for (let i = 0; i < 2; i++) { + b.orbitBot() + tech.dynamoBotCount++; + } + simulation.makeTextLog(`tech.isDynamoBotUpgrade = true`) }) //choose random function from the array and run it notUpgradedBots[Math.floor(Math.random() * notUpgradedBots.length)]() @@ -4093,6 +4166,7 @@ const tech = { isMassEnergy: null, isExtraChoice: null, laserBotCount: null, + dynamoBotCount: null, nailBotCount: null, foamBotCount: null, boomBotCount: null, @@ -4261,5 +4335,7 @@ const tech = { isNeedles: null, isExplodeRadio: null, isGunSwitchField: null, - isNeedleShieldPierce: null + isNeedleShieldPierce: null, + isDuplicateBoss: null, + isDynamoBotUpgrade: null } \ No newline at end of file diff --git a/todo.txt b/todo.txt index 96d01ea..4ae3fc8 100644 --- a/todo.txt +++ b/todo.txt @@ -1,11 +1,18 @@ ******************************************************** NEXT PATCH ******************************************************** -unified field theory doesn't require research to cycle fields +tech: cloning - chance to spawn another level boss = 3x your duplication chance -game resets after beating final boss (in 20s) +tech: dynamo-bot: a bot follows your history, damages mobs, and regens energy when it gets close +tech: dynamo upgrade: more energy regen ******************************************************** BUGS ******************************************************** +(only once on my computer) once every 7 second check isn't running code + power ups don't teleport to exit + complex spin statistics isn't activating + wasn't able to understand bug after extensive testing + had tech: complex spin statistics + (a few times) wormhole teleportation can leave the player in a stuck jump state seems to be easily fixed, by porting, firing or something @@ -24,7 +31,7 @@ game resets after beating final boss (in 20s) ******************************************************** TODO ******************************************************** -exiting the final boss room without 10/10 takes you to the start menu +smooth history following for dynamo-bot? give undefined tech different effects at different localSettings.loreCount values or just random effects @@ -34,8 +41,6 @@ give undefined tech different effects at different localSettings.loreCount value 3. 1/1: reduce max energy and take more harm 4. 1/1: add 5? more levels -lore add console command for unlocking testing mode - rename ? health -> integrity, unity heal -> also integrity, unity @@ -46,28 +51,16 @@ mechanic: use gun swap as an active ability trigger damage immunity for 3 seconds, but drain ammo push away nearby mobs, but drain energy produce ammo, but take 1 damage - rewind, still uses energy bot: ice blast, long CD AOE freeze RPG default or tech: grenades detonate on your cursor / where your cursor was when they were fired -tech: double your rerolls +tech: double your research set your duplication chance to zero requires 5 rerolls and 20% duplication chance might want to use a single variable for all duplication -bot that follows the players history - could have the same shape as the m circle head - 1st bot is at 5s, 2nd is at 4.5s, ... - bots don't get too close to player - run smoothing on position update, don't update if close to player, based on ordering - effect: (one of these can be the upgrade effect) - give player energy overfill - AOE damage to mobs - push away mobs - when close to player: damage bonus damage reduction - tech: dodge chance for cloaking, harmonic fields, also pilot wave 20% chance up to 3 stacks, not additive 0.8^count @@ -85,8 +78,6 @@ tech: time dilation - when you exit time dilation rewind to the state you entere mob ability bombs/bullets that suck in player -tech where you can't stop firing, how to code? - mechanic: technological dead end - add tech to the tech pool with a dumb effect don't show up in custom? negative effect (one time effects are better to avoid code clutter) @@ -106,23 +97,8 @@ mechanic: technological dead end - add tech to the tech pool with a dumb effect remove your bots (requires you to have some bots) your bots are changed to random bots -tech "Expansion Formula": Permanently increase the size of Negative Mass field by 16%(Max 96%) - - -tech "High Risk": Spawn two bosses per level. - maybe limit to just the power up boss and spawn it at the exit every time to keep it simple - also weaken the player - remove a tech? - lower harm reduction? - increase game difficulty by one level - tech that requires integrated armament -tech- reset level - you trade a tech for a chance at killing a new level boss and farming more ammo - resets health, ammo (but not tech, fields, guns, ... ?) - scramble level order? or same level - mechanic - Your energy regen is only active when field and gun have not been used for 5 seconds. be able to open up custom mode in the normal game