From a5aea4ccc5fa263ed841bd58fa485ec84ef29245 Mon Sep 17 00:00:00 2001 From: landgreen Date: Thu, 15 Apr 2021 05:23:26 -0700 Subject: [PATCH] spawns experiment and junk tech: decomposers - mobs leave behind spawns when they die new levelBoss - a cluster of larger spawns while it's alive all mobs other leave behind spawns added block collisions to most no collide mobs (this should buff block throwing and pilot wave) --- .DS_Store | Bin 6148 -> 6148 bytes js/bullet.js | 36 ++-- js/engine.js | 4 +- js/index.js | 3 +- js/level.js | 63 ++++--- js/mob.js | 35 +++- js/player.js | 17 +- js/simulation.js | 1 + js/spawn.js | 482 +++++++++++++++++++++++++++++------------------ js/tech.js | 61 +++++- todo.txt | 45 ++++- 11 files changed, 484 insertions(+), 263 deletions(-) diff --git a/.DS_Store b/.DS_Store index d3548a0903c36c476bb4d6332b7a34c8d71617f3..7abd6eef19df52cdedb2da187b787422fdcc06c5 100644 GIT binary patch delta 22 dcmZoMXffEJ#msbQ 0) { // aim near a random target in array @@ -2859,7 +2859,7 @@ const b = { let closeDist = this.range; for (let i = 0, len = mob.length; i < len; ++i) { const DIST = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius; - if (DIST < closeDist && mob[i].dropPowerUp && + if (DIST < closeDist && mob[i].isDropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0 && Matter.Query.ray(body, this.position, mob[i].position).length === 0) { closeDist = DIST; diff --git a/js/engine.js b/js/engine.js index a5c02d7..87d11d4 100644 --- a/js/engine.js +++ b/js/engine.js @@ -138,7 +138,7 @@ function collisionChecks(event) { y: mob[k].velocity.y - 8 * Math.sin(angle) }); - if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].dropPowerUp && m.energy > 0.34 * m.maxEnergy) { + if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.34 * m.maxEnergy) { m.energy -= 0.33 * m.maxEnergy m.immuneCycle = 0; //player doesn't go immune to collision damage mob[k].death(); @@ -184,7 +184,7 @@ function collisionChecks(event) { let dmg = 0.05 * b.dmgScale * v * obj.mass * tech.throwChargeRate; if (mob[k].isShielded) dmg *= 0.35 mob[k].damage(dmg, true); - if (tech.isBlockPowerUps && !mob[k].alive && mob[k].dropPowerUp) { + if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp) { let type = tech.isEnergyNoAmmo ? "heal" : "ammo" if (Math.random() < 0.4) { type = "heal" diff --git a/js/index.js b/js/index.js index 234ca92..1cccdb7 100644 --- a/js/index.js +++ b/js/index.js @@ -331,7 +331,8 @@ const build = { // text += `
  ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
` techID.innerHTML = `
  ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}` } else if (tech.tech[i].isExperimentalMode) { - techID.innerHTML = `${tech.tech[i].description}` + // techID.innerHTML = `${tech.tech[i].description}` + text += `
${tech.tech[i].name}
${tech.tech[i].description}
` } else { techID.innerHTML = `
  ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}` } diff --git a/js/level.js b/js/level.js index 32d9bc0..07e686d 100644 --- a/js/level.js +++ b/js/level.js @@ -12,7 +12,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(50) + // level.difficultyIncrease(11) // simulation.zoomScale = 1000; // simulation.setZoom(); // m.setField("nano-scale manufacturing") @@ -772,6 +772,33 @@ const level = { mapB.portalPair = mapA return [portalA, portalB, mapA, mapB] }, + drip(x, yMin, yMax, period = 100, color = "hsla(160, 100%, 35%, 0.5)") { + return { + x: x, + y: yMin, + period: period, + dropCycle: 0, + speed: 0, + draw() { + if (!m.isBodiesAsleep) { + if (this.dropCycle < simulation.cycle) { //reset + this.dropCycle = simulation.cycle + this.period + Math.floor(40 * Math.random()) + this.y = yMin + this.speed = 1 + } else { //fall + this.speed += 0.35 //acceleration from gravity + this.y += this.speed + } + } + if (this.y < yMax) { //draw + ctx.fillStyle = color //"hsla(160, 100%, 35%,0.75)" + ctx.beginPath(); + ctx.arc(this.x, this.y, 8, 0, 2 * Math.PI); + ctx.fill(); + } + } + } + }, hazard(x, y, width, height, damage = 0.003, color = "hsla(160, 100%, 35%,0.75)") { return { min: { @@ -1086,18 +1113,18 @@ const level = { // spawn.ghoster(2900, -500) // spawn.launcherBoss(1200, -500) // spawn.laserTargetingBoss(1600, -400) - // spawn.striker(1600, -500) + // spawn.striker(4600, -500) // spawn.laserTargetingBoss(1700, -120) // spawn.bomberBoss(1400, -500) // spawn.sniper(1800, -120) // spawn.streamBoss(1600, -500) // spawn.orbitalBoss(1600, -500) - // spawn.cellBossCulture(1600, -500) + spawn.spawnerBossCulture(1600, -500) // spawn.shieldingBoss(1600, -500) // spawn.beamer(1200, -500) // spawn.shield(mob[mob.length - 1], 1800, -120, 1); - spawn.nodeGroup(1200, -500, "pulsar") + // spawn.nodeGroup(1200, -500, "pulsar") // spawn.snakeBoss(1200, -500) // spawn.powerUpBoss(2900, -500) // spawn.randomMob(1600, -500) @@ -1714,29 +1741,13 @@ const level = { const balance3 = level.spinner(2608, 1900, 584, 25, 0.001) //falling const balance4 = level.spinner(9300, 2205, 25, 380, 0.001) //exit - const drip = { - x: 7150, - y: 0, - speed: 0 - } + const drip1 = level.drip(6100, 1900, 2900, 100) + const drip2 = level.drip(7300, 1900, 2900, 150) + const drip3 = level.drip(8750, 1900, 2900, 70) level.custom = () => { - const dripCycle = (simulation.cycle % 200) //drips - if (dripCycle < 70) { - if (!m.isBodiesAsleep) { - if (dripCycle === 0) { - drip.y = 1900 - drip.x = 4600 + 4400 * Math.random() - drip.speed = 1 - } - drip.speed += 0.35 //acceleration from gravity - drip.y += drip.speed - } - // if (drip.y > 2900) console.log(dripCycle) - ctx.fillStyle = "hsla(160, 100%, 35%, 0.5)" //"hsla(160, 100%, 35%,0.75)" - ctx.beginPath(); - ctx.arc(drip.x, drip.y, 8, 0, 2 * Math.PI); - ctx.fill(); - } + drip1.draw(); + drip2.draw(); + drip3.draw(); button.query(); button.draw(); diff --git a/js/mob.js b/js/mob.js index 5902131..d5a9c34 100644 --- a/js/mob.js +++ b/js/mob.js @@ -307,6 +307,12 @@ const mobs = { this.seePlayer.position.y = player.position.y; } }, + // alwaysSeePlayerIfRemember() { + // if (!m.isCloak && this.seePlayer.recall) { + // this.seePlayer.position.x = player.position.x; + // this.seePlayer.position.y = player.position.y; + // } + // }, seePlayerCheck() { if (!(simulation.cycle % this.seePlayerFreq)) { if ( @@ -980,7 +986,7 @@ const mobs = { explode(mass = this.mass) { if (m.immuneCycle < m.cycle) { m.damage(Math.min(Math.max(0.02 * Math.sqrt(mass), 0.01), 0.35) * simulation.dmgScale); - this.dropPowerUp = false; + this.isDropPowerUp = false; this.death(); //death with no power up or body } }, @@ -988,7 +994,7 @@ const mobs = { if (!m.isBodiesAsleep) { this.timeLeft--; if (this.timeLeft < 0) { - this.dropPowerUp = false; + this.isDropPowerUp = false; this.death(); //death with no power up } } @@ -1014,9 +1020,9 @@ const mobs = { if (this.isBoss) dmg *= 0.25 //energy and heal drain should be calculated after damage boosts - if (tech.energySiphon && dmg !== Infinity && this.dropPowerUp) m.energy += Math.min(this.health, dmg) * tech.energySiphon + if (tech.energySiphon && dmg !== Infinity && this.isDropPowerUp) m.energy += Math.min(this.health, dmg) * tech.energySiphon - if (tech.healthDrain && dmg !== Infinity && this.dropPowerUp) { + if (tech.healthDrain && dmg !== Infinity && this.isDropPowerUp) { m.addHealth(Math.min(this.health, dmg) * tech.healthDrain) if (m.health > m.maxHealth) m.health = m.maxHealth } @@ -1036,12 +1042,24 @@ const mobs = { // to use declare custom method in mob spawn }, leaveBody: true, - dropPowerUp: true, + isDropPowerUp: true, death() { this.onDeath(this); //custom death effects this.removeConsBB(); this.alive = false; //triggers mob removal in mob[i].replace(i) - if (this.dropPowerUp) { + + if (this.isDropPowerUp) { + if (tech.deathSpawnsFromBoss || (tech.deathSpawns && this.isDropPowerUp)) { + const spawns = tech.deathSpawns + tech.deathSpawnsFromBoss + const len = Math.min(12, spawns * Math.ceil(Math.random() * simulation.difficulty * spawns)) + for (let i = 0; i < len; i++) { + spawn.spawns(this.position.x + (Math.random() - 0.5) * radius * 2.5, this.position.y + (Math.random() - 0.5) * radius * 2.5); + Matter.Body.setVelocity(mob[mob.length - 1], { + x: this.velocity.x + (Math.random() - 0.5) * 10, + y: this.velocity.x + (Math.random() - 0.5) * 10 + }); + } + } if (tech.isEnergyLoss) m.energy *= 0.75; powerUps.spawnRandomPowerUp(this.position.x, this.position.y); m.lastKillCycle = m.cycle; //tracks the last time a kill was made, mostly used in simulation.checks() @@ -1055,7 +1073,10 @@ const mobs = { } if (tech.isBotSpawnerReset) { for (let i = 0, len = bullet.length; i < len; i++) { - if (bullet[i].botType && !bullet[i].isKeep) bullet[i].endCycle = simulation.cycle + 660 //10 seconds and 1 extra second for fun + if (bullet[i].botType && bullet[i].endCycle !== Infinity) { + console.log(bullet[i].endCycle) + bullet[i].endCycle = simulation.cycle + 660 //10 seconds and 1 extra second for fun + } } } if (Math.random() < tech.botSpawner) { diff --git a/js/player.js b/js/player.js index 52dc45b..bd97ab4 100644 --- a/js/player.js +++ b/js/player.js @@ -348,6 +348,7 @@ const m = { // tech.removeLoreTechFromPool(); // tech.addLoreTechToPool(); // tech.removeJunkTechFromPool(); + tech.cancelCount = 0; tech.armorFromPowerUps = 0; tech.totalCount = 0; const randomBotCount = b.totalBots() @@ -1317,7 +1318,7 @@ const m = { x: player.velocity.x - (20 * unit.x) / massRoot, y: player.velocity.y - (20 * unit.y) / massRoot }); - if (who.dropPowerUp && player.speed < 12) { + if (who.isDropPowerUp && player.speed < 12) { const massRootCap = Math.sqrt(Math.min(10, Math.max(0.4, who.mass))); // masses above 12 can start to overcome the push back Matter.Body.setVelocity(player, { x: 0.9 * player.velocity.x + 0.6 * unit.x * massRootCap, @@ -1880,6 +1881,14 @@ const m = { simulation.isTimeSkipping = true; m.cycle++; simulation.gravity(); + if (tech.isFireMoveLock && input.fire) { + // Matter.Body.setVelocity(player, { + // x: 0, + // y: -55 * player.mass * simulation.g //undo gravity before it is added + // }); + player.force.x = 0 + player.force.y = 0 + } Engine.update(engine, simulation.delta); // level.checkZones(); // level.checkQuery(); @@ -2125,7 +2134,7 @@ const m = { // //draw outline of shield // ctx.fillStyle = `rgba(140,217,255,0.5)` // ctx.fill() - // } else if (tech.superposition && inPlayer[i].dropPowerUp) { + // } else if (tech.superposition && inPlayer[i].isDropPowerUp) { // // inPlayer[i].damage(0.4 * b.dmgScale); //damage mobs inside the player // // m.energy += 0.005; @@ -2919,7 +2928,7 @@ const m = { y: mob[k].velocity.y - 8 * Math.sin(angle) }); - if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].dropPowerUp && m.energy > 0.34 * m.maxEnergy) { + if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.34 * m.maxEnergy) { m.energy -= 0.33 * m.maxEnergy m.immuneCycle = 0; //player doesn't go immune to collision damage mob[k].death(); @@ -2965,7 +2974,7 @@ const m = { let dmg = 0.05 * b.dmgScale * v * obj.mass * tech.throwChargeRate; if (mob[k].isShielded) dmg *= 0.35 mob[k].damage(dmg, true); - if (tech.isBlockPowerUps && !mob[k].alive && mob[k].dropPowerUp) { + if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp) { let type = tech.isEnergyNoAmmo ? "heal" : "ammo" if (Math.random() < 0.4) { type = "heal" diff --git a/js/simulation.js b/js/simulation.js index a3dfd59..ee6b480 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -710,6 +710,7 @@ const simulation = { let holdTarget; //if player is holding something this remembers it before it gets deleted if (m.holdingTarget) holdTarget = m.holdingTarget; + tech.deathSpawnsFromBoss = 0; simulation.fallHeight = 3000; m.fireCDcycle = 0 m.drop(); diff --git a/js/spawn.js b/js/spawn.js index 5d06edd..1d88b80 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -83,7 +83,7 @@ const spawn = { } } }, - randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss"]) { + randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture"]) { // 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) }, @@ -472,7 +472,7 @@ const spawn = { //tether to other blocks ctx.beginPath(); for (let i = 0, len = mob.length; i < len; i++) { - if (mob[i].isGrouper && mob[i] != this && mob[i].dropPowerUp) { //don't tether to self, bullets, shields, ... + if (mob[i].isGrouper && mob[i] != this && mob[i].isDropPowerUp) { //don't tether to self, bullets, shields, ... const distance2 = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)) if (distance2 < this.groupingRangeMax) { if (!mob[i].seePlayer.recall) mob[i].seePlayerCheck(); //wake up sleepy mobs @@ -529,7 +529,7 @@ const spawn = { me.seePlayerFreq = Math.floor(11 + 7 * Math.random()) me.seeAtDistance2 = 1400000; me.cellMassMax = 70 - me.collisionFilter.mask = cat.player | cat.bullet //| cat.map | cat.body + me.collisionFilter.mask = cat.player | cat.bullet | cat.body //| cat.map | cat.body Matter.Body.setDensity(me, 0.00035) // normal density is 0.001 // this reduces life by half and decreases knockback const k = 642 //k=r^2/m me.split = function() { @@ -584,10 +584,103 @@ const spawn = { powerUps.spawnBossPowerUp(this.position.x, this.position.y) } else { this.leaveBody = false; - this.dropPowerUp = false; + this.isDropPowerUp = false; } } }, + spawnerBossCulture(x, y, radius = 50, num = 8 + Math.min(20, simulation.difficulty * 0.4)) { + tech.deathSpawnsFromBoss += 0.4 + const spawnID = Math.random() + for (let i = 0; i < num; i++) spawn.spawnerBoss(x, y, radius, spawnID) + }, + spawnerBoss(x, y, radius, spawnID) { + mobs.spawn(x + Math.random(), y + Math.random(), 4, radius, "rgba(255,60,0,0.3)") //); + let me = mob[mob.length - 1]; + me.isBoss = true; + me.isSpawnBoss = true; + me.spawnID = spawnID + me.accelMag = 0.0002 * simulation.accelScale; + me.memory = Infinity; + me.showHealthBar = false; + me.isVerticesChange = true + me.frictionAir = 0.012 + me.seePlayerFreq = Math.floor(11 + 7 * Math.random()) + me.seeAtDistance2 = 200000 //1400000; + me.cellMassMax = 70 + me.stroke = "transparent" + me.collisionFilter.mask = cat.player | cat.bullet | cat.body //| cat.map //"rgba(255,60,0,0.3)" + // Matter.Body.setDensity(me, 0.0014) // normal density is 0.001 + Matter.Body.setAngularVelocity(me, 0.12 * (Math.random() - 0.5)) + // spawn.shield(me, x, y, 1); + + me.onHit = function() { //run this function on hitting player + this.explode(); + }; + me.doAwake = function() { + if (!m.isBodiesAsleep) { + this.alwaysSeePlayer(); + this.checkStatus(); + this.attraction(); + + // if (this.seePlayer.recall && this.mass < this.cellMassMax) { //grow cell radius + // const scale = 1 + 0.0002 * this.cellMassMax / this.mass; + // Matter.Body.scale(this, scale, scale); + // this.radius = Math.sqrt(this.mass * k / Math.PI) + // } + if (!(simulation.cycle % this.seePlayerFreq)) { //move away from other mobs + const repelRange = 40 + const attractRange = 240 + for (let i = 0, len = mob.length; i < len; i++) { + if (mob[i].isSpawnBoss && mob[i].id !== this.id) { + const sub = Vector.sub(this.position, mob[i].position) + const dist = Vector.magnitude(sub) + if (dist < repelRange) { + this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.002) + } else if (dist > attractRange) { + this.force = Vector.mult(Vector.normalise(sub), -this.mass * 0.002) + } + } + } + } + } + } + me.do = function() { + this.checkStatus(); + if (this.seePlayer.recall) { + this.do = this.doAwake + //awaken other spawnBosses + for (let i = 0, len = mob.length; i < len; i++) { + if (mob[i].isSpawnBoss && mob[i].spawnID === this.spawnID) mob[i].seePlayer.recall = 1 + } + } + }; + me.onDeath = function() { + this.isSpawnBoss = false; + let count = 0 //count other cells by id + // console.log(this.spawnID) + for (let i = 0, len = mob.length; i < len; i++) { + if (mob[i].isSpawnBoss && mob[i].spawnID === this.spawnID) count++ + } + if (count < 1) { //only drop a power up if this is the last cell + powerUps.spawnBossPowerUp(this.position.x, this.position.y) + tech.deathSpawnsFromBoss -= 0.4 + } else { + this.leaveBody = false; + this.isDropPowerUp = false; + } + + const spawns = tech.deathSpawns + tech.deathSpawnsFromBoss + const len = Math.min(12, spawns * Math.ceil(Math.random() * simulation.difficulty * spawns)) + for (let i = 0; i < len; i++) { + spawn.spawns(this.position.x + (Math.random() - 0.5) * radius * 2.5, this.position.y + (Math.random() - 0.5) * radius * 2.5); + Matter.Body.setVelocity(mob[mob.length - 1], { + x: this.velocity.x + (Math.random() - 0.5) * 10, + y: this.velocity.x + (Math.random() - 0.5) * 10 + }); + } + + } + }, powerUpBoss(x, y, vertices = 9, radius = 130) { mobs.spawn(x, y, vertices, radius, "transparent"); let me = mob[mob.length - 1]; @@ -596,10 +689,9 @@ const spawn = { me.seeAtDistance2 = 1000000; me.accelMag = 0.0005 * simulation.accelScale; Matter.Body.setDensity(me, 0.00035); //normal is 0.001 - me.collisionFilter.mask = cat.bullet | cat.player + me.collisionFilter.mask = cat.bullet | cat.player | cat.body me.memory = Infinity; me.seePlayerFreq = 30 - me.lockedOn = null; if (vertices === 9) { //on primary spawn @@ -616,17 +708,15 @@ const spawn = { }; me.onDeath = function() { this.leaveBody = false; - this.dropPowerUp = false; if (vertices > 3) { + this.isDropPowerUp = false; spawn.powerUpBoss(this.position.x, this.position.y, vertices - 1) Matter.Body.setVelocity(mob[mob.length - 1], { x: this.velocity.x, y: this.velocity.y }) } - for (let i = 0; i < powerUp.length; i++) { - powerUp[i].collisionFilter.mask = cat.map | cat.powerUp - } + for (let i = 0; i < powerUp.length; i++) powerUp[i].collisionFilter.mask = cat.map | cat.powerUp }; me.do = function() { this.stroke = `hsl(0,0%,${80+25*Math.sin(simulation.cycle*0.01)}%)` @@ -829,7 +919,7 @@ const spawn = { me.seeAtDistance2 = (me.eventHorizon + 400) * (me.eventHorizon + 400); //vision limit is event horizon me.accelMag = 0.0001 * simulation.accelScale; me.frictionAir = 0.025; - me.collisionFilter.mask = cat.player | cat.bullet + me.collisionFilter.mask = cat.player | cat.bullet | cat.body me.memory = Infinity; Matter.Body.setDensity(me, 0.008); //extra dense //normal is 0.001 //makes effective life much larger me.do = function() { @@ -906,7 +996,7 @@ const spawn = { me.eventHorizon = 1100; //required for black hole me.seeAtDistance2 = (me.eventHorizon + 1200) * (me.eventHorizon + 1200); //vision limit is event horizon me.accelMag = 0.00003 * simulation.accelScale; - me.collisionFilter.mask = cat.player | cat.bullet + me.collisionFilter.mask = cat.player | cat.bullet | cat.body // me.frictionAir = 0.005; me.memory = 1600; Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger @@ -1132,7 +1222,7 @@ const spawn = { this.fill = `rgba(0,0,0,${0.4+0.6*Math.random()})` this.stroke = "#014" this.isShielded = false; - this.dropPowerUp = true; + this.isDropPowerUp = true; this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob; //can't touch bullets ctx.beginPath(); @@ -1160,7 +1250,7 @@ const spawn = { // ctx.stroke(); } else { this.isShielded = true; - this.dropPowerUp = false; + this.isDropPowerUp = false; this.seePlayer.recall = false this.fill = "transparent" this.stroke = "transparent" @@ -1192,7 +1282,7 @@ const spawn = { }, historyBoss(x, y, radius = 30) { if (tech.dynamoBotCount > 0) { - spawn.randomLevelBoss(x, y, ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss"]) + spawn.randomLevelBoss(x, y, ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture"]) return } mobs.spawn(x, y, 0, radius, "transparent"); @@ -1204,7 +1294,7 @@ const spawn = { me.delayLimit = 60 + Math.floor(60 * Math.random()); me.followDelay = 600 - Math.floor(60 * Math.random()) me.stroke = "transparent"; //used for drawGhost - me.collisionFilter.mask = cat.bullet + me.collisionFilter.mask = cat.bullet | cat.body me.memory = Infinity me.onDeath = function() { powerUps.spawnBossPowerUp(this.position.x, this.position.y) @@ -1505,83 +1595,85 @@ const spawn = { } me.fire = function() { this.checkStatus(); - if (!m.isBodiesAsleep && !m.isCloak && !this.isStunned) { - if (this.isFiring) { - if (this.fireCycle > this.fireDelay) { //fire - this.isFiring = false - this.fireCycle = 0 - this.torque += (0.00008 + 0.00007 * Math.random()) * this.inertia * (Math.round(Math.random()) * 2 - 1) //randomly spin around after firing - //is player in beam path - if (Matter.Query.ray([player], this.fireTarget, this.position).length) { + if (!m.isBodiesAsleep) { + if (!m.isCloak && !this.isStunned) { + if (this.isFiring) { + if (this.fireCycle > this.fireDelay) { //fire + this.isFiring = false + this.fireCycle = 0 + this.torque += (0.00008 + 0.00007 * Math.random()) * this.inertia * (Math.round(Math.random()) * 2 - 1) //randomly spin around after firing + //is player in beam path + if (Matter.Query.ray([player], this.fireTarget, this.position).length) { + unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100) + this.fireTarget = Vector.add(this.vertices[1], unit) + } + //damage player if in range + if (Vector.magnitude(Vector.sub(player.position, this.fireTarget)) < this.pulseRadius && m.immuneCycle < m.cycle) { + m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage + m.damage(0.045 * simulation.dmgScale); + } + simulation.drawList.push({ //add dmg to draw queue + x: this.fireTarget.x, + y: this.fireTarget.y, + radius: this.pulseRadius, + color: "rgba(120,0,255,0.6)", + time: simulation.drawTime + }); + ctx.beginPath(); + ctx.moveTo(this.vertices[1].x, this.vertices[1].y) + ctx.lineTo(this.fireTarget.x, this.fireTarget.y) + ctx.lineWidth = 20; + ctx.strokeStyle = "rgba(120,0,255,0.2)"; + ctx.stroke(); + ctx.lineWidth = 4; + ctx.strokeStyle = "rgba(120,0,255,1)"; + ctx.stroke(); + } else { //delay before firing + this.fireCycle++ + //draw explosion outline + ctx.beginPath(); + ctx.arc(this.fireTarget.x, this.fireTarget.y, this.pulseRadius, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay + ctx.fillStyle = "rgba(120,0,255,0.05)"; + ctx.fill(); + //draw path from mob to explosion + ctx.beginPath(); + ctx.moveTo(this.vertices[1].x, this.vertices[1].y) + ctx.lineTo(this.fireTarget.x, this.fireTarget.y) + ctx.setLineDash([40 * Math.random(), 200 * Math.random()]); + ctx.lineWidth = 2; + ctx.strokeStyle = "rgba(120,0,255,0.2)"; + ctx.stroke(); + ctx.setLineDash([0, 0]); + } + } else { //aim at player + this.fireCycle++ + this.fireDir = Vector.normalise(Vector.sub(m.pos, this.position)); //set direction to turn to fire + //rotate towards fireAngle + const angle = this.angle + Math.PI / 2; + const c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y; + const threshold = 0.04; + if (c > threshold) { + this.torque += 0.0000015 * this.inertia; + } else if (c < -threshold) { + this.torque -= 0.0000015 * this.inertia; + } else if (this.fireCycle > 45) { //fire unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100) this.fireTarget = Vector.add(this.vertices[1], unit) - } - //damage player if in range - if (Vector.magnitude(Vector.sub(player.position, this.fireTarget)) < this.pulseRadius && m.immuneCycle < m.cycle) { - m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage - m.damage(0.045 * simulation.dmgScale); - } - simulation.drawList.push({ //add dmg to draw queue - x: this.fireTarget.x, - y: this.fireTarget.y, - radius: this.pulseRadius, - color: "rgba(120,0,255,0.6)", - time: simulation.drawTime - }); - ctx.beginPath(); - ctx.moveTo(this.vertices[1].x, this.vertices[1].y) - ctx.lineTo(this.fireTarget.x, this.fireTarget.y) - ctx.lineWidth = 20; - ctx.strokeStyle = "rgba(120,0,255,0.2)"; - ctx.stroke(); - ctx.lineWidth = 4; - ctx.strokeStyle = "rgba(120,0,255,1)"; - ctx.stroke(); - } else { //delay before firing - this.fireCycle++ - //draw explosion outline - ctx.beginPath(); - ctx.arc(this.fireTarget.x, this.fireTarget.y, this.pulseRadius, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay - ctx.fillStyle = "rgba(120,0,255,0.05)"; - ctx.fill(); - //draw path from mob to explosion - ctx.beginPath(); - ctx.moveTo(this.vertices[1].x, this.vertices[1].y) - ctx.lineTo(this.fireTarget.x, this.fireTarget.y) - ctx.setLineDash([40 * Math.random(), 200 * Math.random()]); - ctx.lineWidth = 2; - ctx.strokeStyle = "rgba(120,0,255,0.2)"; - ctx.stroke(); - ctx.setLineDash([0, 0]); - } - } else { //aim at player - this.fireCycle++ - this.fireDir = Vector.normalise(Vector.sub(m.pos, this.position)); //set direction to turn to fire - //rotate towards fireAngle - const angle = this.angle + Math.PI / 2; - const c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y; - const threshold = 0.04; - if (c > threshold) { - this.torque += 0.0000015 * this.inertia; - } else if (c < -threshold) { - this.torque -= 0.0000015 * this.inertia; - } else if (this.fireCycle > 45) { //fire - unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100) - this.fireTarget = Vector.add(this.vertices[1], unit) - if (Vector.magnitude(Vector.sub(m.pos, this.fireTarget)) < 1000) { //if's possible for this to be facing 180 degrees away from the player, this makes sure that doesn't occur - Matter.Body.setAngularVelocity(this, 0) - this.fireLockCount = 0 - this.isFiring = true - this.fireCycle = 0 + if (Vector.magnitude(Vector.sub(m.pos, this.fireTarget)) < 1000) { //if's possible for this to be facing 180 degrees away from the player, this makes sure that doesn't occur + Matter.Body.setAngularVelocity(this, 0) + this.fireLockCount = 0 + this.isFiring = true + this.fireCycle = 0 + } } } + //gently return to starting location + const sub = Vector.sub(this.homePosition, this.position) + const dist = Vector.magnitude(sub) + if (dist > 250) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.0002) + } else { + this.isFiring = false } - //gently return to starting location - const sub = Vector.sub(this.homePosition, this.position) - const dist = Vector.magnitude(sub) - if (dist > 250) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.0002) - } else { - this.isFiring = false } }; }, @@ -1622,88 +1714,90 @@ const spawn = { me.do = function() { this.seePlayerByLookingAt(); this.checkStatus(); - if (!m.isBodiesAsleep && this.seePlayer.recall) { - if (this.isFiring) { - if (this.fireCycle > this.fireDelay) { //fire - if (!this.canSeeTarget()) return - this.isFiring = false - this.fireCycle = 0 - this.torque += (0.00002 + 0.0002 * Math.random()) * this.inertia * (Math.round(Math.random()) * 2 - 1) //randomly spin around after firing - //is player in beam path - if (Matter.Query.ray([player], this.fireTarget, this.position).length) { + if (!m.isBodiesAsleep) { + if (this.seePlayer.recall) { + if (this.isFiring) { + if (this.fireCycle > this.fireDelay) { //fire + if (!this.canSeeTarget()) return + this.isFiring = false + this.fireCycle = 0 + this.torque += (0.00002 + 0.0002 * Math.random()) * this.inertia * (Math.round(Math.random()) * 2 - 1) //randomly spin around after firing + //is player in beam path + if (Matter.Query.ray([player], this.fireTarget, this.position).length) { + unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100) + this.fireTarget = Vector.add(this.vertices[1], unit) + } + //damage player if in range + if (Vector.magnitude(Vector.sub(player.position, this.fireTarget)) < this.pulseRadius && m.immuneCycle < m.cycle) { + m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage + m.damage(0.03 * simulation.dmgScale); + } + simulation.drawList.push({ //add dmg to draw queue + x: this.fireTarget.x, + y: this.fireTarget.y, + radius: this.pulseRadius, + color: "rgba(255,0,100,0.6)", + time: simulation.drawTime + }); + ctx.beginPath(); + ctx.moveTo(this.vertices[1].x, this.vertices[1].y) + ctx.lineTo(this.fireTarget.x, this.fireTarget.y) + ctx.lineWidth = 20; + ctx.strokeStyle = "rgba(255,0,100,0.2)"; + ctx.stroke(); + ctx.lineWidth = 4; + ctx.strokeStyle = "rgba(255,0,100,1)"; + ctx.stroke(); + } else { //delay before firing + this.fireCycle++ + if (!(simulation.cycle % 3)) { + if (!this.canSeeTarget()) return //if can't see stop firing + } + //draw explosion outline + ctx.beginPath(); + ctx.arc(this.fireTarget.x, this.fireTarget.y, this.pulseRadius, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay + ctx.fillStyle = "rgba(255,0,100,0.05)"; + ctx.fill(); + //draw path from mob to explosion + ctx.beginPath(); + ctx.moveTo(this.vertices[1].x, this.vertices[1].y) + ctx.lineTo(this.fireTarget.x, this.fireTarget.y) + ctx.setLineDash([40 * Math.random(), 200 * Math.random()]); + ctx.lineWidth = 2; + ctx.strokeStyle = "rgba(255,0,100,0.2)"; + ctx.stroke(); + ctx.setLineDash([0, 0]); + } + } else { //aim at player + this.fireCycle++ + // this.fireDir = ; //set direction to turn to fire + const angle = this.angle + Math.PI / 2; + const dot = Vector.dot({ + x: Math.cos(angle), + y: Math.sin(angle) + }, Vector.normalise(Vector.sub(this.seePlayer.position, this.position))) + const threshold = 0.04; + if (dot > threshold) { //rotate towards fireAngle + this.torque += 0.0000015 * this.inertia; + } else if (dot < -threshold) { + this.torque -= 0.0000015 * this.inertia; + } else if (this.fireCycle > 60) { // aim unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100) this.fireTarget = Vector.add(this.vertices[1], unit) + if (!this.canSeeTarget()) return + Matter.Body.setAngularVelocity(this, 0) + this.fireLockCount = 0 + this.isFiring = true + this.fireCycle = 0 } - //damage player if in range - if (Vector.magnitude(Vector.sub(player.position, this.fireTarget)) < this.pulseRadius && m.immuneCycle < m.cycle) { - m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage - m.damage(0.03 * simulation.dmgScale); - } - simulation.drawList.push({ //add dmg to draw queue - x: this.fireTarget.x, - y: this.fireTarget.y, - radius: this.pulseRadius, - color: "rgba(255,0,100,0.6)", - time: simulation.drawTime - }); - ctx.beginPath(); - ctx.moveTo(this.vertices[1].x, this.vertices[1].y) - ctx.lineTo(this.fireTarget.x, this.fireTarget.y) - ctx.lineWidth = 20; - ctx.strokeStyle = "rgba(255,0,100,0.2)"; - ctx.stroke(); - ctx.lineWidth = 4; - ctx.strokeStyle = "rgba(255,0,100,1)"; - ctx.stroke(); - } else { //delay before firing - this.fireCycle++ - if (!(simulation.cycle % 3)) { - if (!this.canSeeTarget()) return //if can't see stop firing - } - //draw explosion outline - ctx.beginPath(); - ctx.arc(this.fireTarget.x, this.fireTarget.y, this.pulseRadius, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay - ctx.fillStyle = "rgba(255,0,100,0.05)"; - ctx.fill(); - //draw path from mob to explosion - ctx.beginPath(); - ctx.moveTo(this.vertices[1].x, this.vertices[1].y) - ctx.lineTo(this.fireTarget.x, this.fireTarget.y) - ctx.setLineDash([40 * Math.random(), 200 * Math.random()]); - ctx.lineWidth = 2; - ctx.strokeStyle = "rgba(255,0,100,0.2)"; - ctx.stroke(); - ctx.setLineDash([0, 0]); - } - } else { //aim at player - this.fireCycle++ - // this.fireDir = ; //set direction to turn to fire - const angle = this.angle + Math.PI / 2; - const dot = Vector.dot({ - x: Math.cos(angle), - y: Math.sin(angle) - }, Vector.normalise(Vector.sub(this.seePlayer.position, this.position))) - const threshold = 0.04; - if (dot > threshold) { //rotate towards fireAngle - this.torque += 0.0000015 * this.inertia; - } else if (dot < -threshold) { - this.torque -= 0.0000015 * this.inertia; - } else if (this.fireCycle > 60) { // aim - unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100) - this.fireTarget = Vector.add(this.vertices[1], unit) - if (!this.canSeeTarget()) return - Matter.Body.setAngularVelocity(this, 0) - this.fireLockCount = 0 - this.isFiring = true - this.fireCycle = 0 } + //gently return to starting location + const sub = Vector.sub(this.homePosition, this.position) + const dist = Vector.magnitude(sub) + if (dist > 350) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.0002) + } else { + this.isFiring = false } - //gently return to starting location - const sub = Vector.sub(this.homePosition, this.position) - const dist = Vector.magnitude(sub) - if (dist > 350) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.0002) - } else { - this.isFiring = false } }; }, @@ -2054,7 +2148,7 @@ const spawn = { me.alpha = 1; //used in drawGhost me.canTouchPlayer = false; //used in drawGhost // me.leaveBody = false; - me.collisionFilter.mask = cat.bullet + me.collisionFilter.mask = cat.bullet | cat.body me.showHealthBar = false; me.memory = 480; me.do = function() { @@ -2165,7 +2259,7 @@ const spawn = { 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 + me.collisionFilter.mask = cat.player | cat.bullet | cat.body spawn.shield(me, x, y, 1); @@ -2271,7 +2365,7 @@ const spawn = { me.frictionAir = 0; me.restitution = 0.8; me.leaveBody = false; - me.dropPowerUp = false; + me.isDropPowerUp = false; me.showHealthBar = false; me.collisionFilter.category = cat.mobBullet; @@ -2322,7 +2416,7 @@ const spawn = { me.frictionAir = 0; me.restitution = 1; me.leaveBody = false; - me.dropPowerUp = false; + me.isDropPowerUp = false; me.showHealthBar = false; me.collisionFilter.category = cat.mobBullet; me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet; @@ -2460,14 +2554,14 @@ const spawn = { me.frictionAir = 0; me.restitution = 0; me.leaveBody = false; - me.dropPowerUp = false; + me.isDropPowerUp = false; me.showHealthBar = false; me.collisionFilter.category = cat.mobBullet; me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet; me.do = function() { this.timeLimit(); if (Matter.Query.collides(this, map).length > 0 || Matter.Query.collides(this, body).length > 0 && this.speed < 3) { - this.dropPowerUp = false; + this.isDropPowerUp = false; this.death(); //death with no power up } }; @@ -2552,6 +2646,7 @@ const spawn = { me.frictionStatic = 0; me.friction = 0; me.frictionAir = 0.5; + me.homePosition = { x: x, y: y }; spawn.shield(me, x, y, 1); spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random()) @@ -2582,10 +2677,9 @@ const spawn = { this.cycle = 0 ctx.beginPath(); for (let i = 0; i < mob.length; i++) { - if (!mob[i].isShielded && !mob[i].shield && mob[i].dropPowerUp && mob[i].alive) { + if (!mob[i].isShielded && !mob[i].shield && mob[i].isDropPowerUp && mob[i].alive) { ctx.moveTo(this.position.x, this.position.y) ctx.lineTo(mob[i].position.x, mob[i].position.y) - spawn.shield(mob[i], mob[i].position.x, mob[i].position.y, 1, true); } } @@ -2593,6 +2687,10 @@ const spawn = { // ctx.lineCap = "round"; ctx.strokeStyle = "rgba(200,200,255,0.9)" ctx.stroke(); + //return to starting location + const sub = Vector.sub(this.homePosition, this.position) + const dist = Vector.magnitude(sub) + if (dist > 350) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.05) } } }; @@ -2690,7 +2788,7 @@ const spawn = { me.frictionAir = 0.01 //* (0.8 + 0.4 * Math.random()); me.restitution = 0.5; me.leaveBody = false; - me.dropPowerUp = false; + me.isDropPowerUp = false; me.showHealthBar = false; me.collisionFilter.category = cat.mobBullet; me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet; @@ -2706,7 +2804,7 @@ const spawn = { let me = mob[mob.length - 1]; me.g = 0.0004; //required if using 'gravity' me.leaveBody = false; - // me.dropPowerUp = false; + // me.isDropPowerUp = false; me.onDeath = function() { //run this function on death for (let i = 0; i < Math.ceil(this.mass * 0.15 + Math.random() * 2.5); ++i) { spawn.spawns(this.position.x + (Math.random() - 0.5) * radius * 2.5, this.position.y + (Math.random() - 0.5) * radius * 2.5); @@ -2724,25 +2822,33 @@ const spawn = { this.attraction(); }; }, - spawns(x, y, radius = 15 + Math.ceil(Math.random() * 5)) { + spawns(x, y, radius = 15) { mobs.spawn(x, y, 4, radius, "rgb(255,0,0)"); let me = mob[mob.length - 1]; me.onHit = function() { //run this function on hitting player this.explode(); }; + // me.stroke = "transparent" + me.collisionFilter.mask = cat.player | cat.bullet | cat.body | cat.map + me.showHealthBar = false; Matter.Body.setDensity(me, 0.0005); //normal is 0.001 me.g = 0.0001; //required if using 'gravity' - me.accelMag = 0.0003 * simulation.accelScale; + me.accelMag = 0.00008 * simulation.accelScale; me.memory = 30; me.leaveBody = false; + me.isDropPowerUp = false; me.seePlayerFreq = Math.round((80 + 50 * Math.random()) * simulation.lookFreqScale); - me.frictionAir = 0.002; + me.frictionAir = 0.004; me.do = function() { this.gravity(); this.seePlayerCheck(); this.checkStatus(); this.attraction(); + + // this.alwaysSeePlayer(); + // this.checkStatus(); + // this.attraction(); }; }, // exploder(x, y, radius = 40 + Math.ceil(Math.random() * 50)) { @@ -2859,7 +2965,7 @@ const spawn = { // //run this function on hitting player // this.explode(); // }; - me.collisionFilter.mask = cat.bullet | cat.player | cat.mob + me.collisionFilter.mask = cat.bullet | cat.player | cat.mob | cat.body me.accelMag = 0.0004 * simulation.accelScale; me.leaveBody = false; me.frictionAir = 0.02; @@ -2943,7 +3049,7 @@ const spawn = { this.fill = `rgba(220,220,255,${0.3 + 0.6 *this.health})` }; me.leaveBody = false; - me.dropPowerUp = false; + me.isDropPowerUp = false; me.showHealthBar = false; me.shieldTargetID = target.id @@ -3000,7 +3106,7 @@ const spawn = { } }; me.leaveBody = false; - me.dropPowerUp = false; + me.isDropPowerUp = false; me.showHealthBar = false; mob[mob.length - 1] = mob[mob.length - 1 - nodes]; mob[mob.length - 1 - nodes] = me; @@ -3023,7 +3129,7 @@ const spawn = { me.stroke = "transparent"; Matter.Body.setDensity(me, 0.1); //normal is 0.001 me.leaveBody = false; - me.dropPowerUp = false; + me.isDropPowerUp = false; me.showHealthBar = false; // me.isShielded = true me.collisionFilter.category = cat.mobBullet; @@ -3062,7 +3168,7 @@ const spawn = { me.memory = Infinity; me.frictionAir = 0.01; me.accelMag = 0.00004 * simulation.accelScale; - me.collisionFilter.mask = cat.player | cat.bullet + me.collisionFilter.mask = cat.player | cat.bullet | cat.body spawn.shield(me, x, y, 1); const rangeInnerVsOuter = Math.random() @@ -3240,7 +3346,7 @@ const spawn = { me.frictionStatic = 1; me.friction = 1; me.frictionAir = 0.01; - me.dropPowerUp = false; + me.isDropPowerUp = false; me.showHealthBar = false; me.do = function() { @@ -3307,7 +3413,7 @@ const spawn = { me.frictionStatic = 1; me.friction = 1; me.frictionAir = 0.01; - me.dropPowerUp = false; + me.isDropPowerUp = false; me.showHealthBar = false; me.do = function() { @@ -3357,7 +3463,7 @@ const spawn = { me.frictionStatic = 1; me.friction = 1; me.frictionAir = 0.01; - me.dropPowerUp = false; + me.isDropPowerUp = false; me.showHealthBar = false; me.do = function() { @@ -3406,7 +3512,7 @@ const spawn = { // me.frictionStatic = 1; // me.friction = 1; me.frictionAir = 0.01; - me.dropPowerUp = false; + me.isDropPowerUp = false; me.showHealthBar = false; me.do = function() { @@ -3455,7 +3561,7 @@ const spawn = { // me.frictionStatic = 1; // me.friction = 1; me.frictionAir = 0.01; - me.dropPowerUp = false; + me.isDropPowerUp = false; me.showHealthBar = false; me.do = function() { diff --git a/js/tech.js b/js/tech.js index df49cc6..a1c15f9 100644 --- a/js/tech.js +++ b/js/tech.js @@ -154,7 +154,7 @@ if (tech.is100Duplicate && tech.duplicationChance() > 0.99) { tech.is100Duplicate = false const range = 1000 - const bossOptions = ["historyBoss", "cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss"] + const bossOptions = ["historyBoss", "cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture"] spawn.randomLevelBoss(m.pos.x + range, m.pos.y, bossOptions); spawn.randomLevelBoss(m.pos.x, m.pos.y + range, bossOptions); spawn.randomLevelBoss(m.pos.x - range, m.pos.y, bossOptions); @@ -230,7 +230,7 @@ }, { name: "active cooling", - description: "17% decreased delay after firing
for each gun in your inventory", + description: "14% decreased delay after firing
for each gun in your inventory", maxCount: 1, count: 0, frequency: 2, @@ -2641,13 +2641,13 @@ }, requires: "below 100% duplication chance, below level 5, not determinism", effect() { + // tech.cancelCount = 0 tech.isCancelDuplication = true - tech.cancelCount = 0 simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw }, remove() { - tech.isCancelDuplication = false // tech.cancelCount = 0 + tech.isCancelDuplication = false if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal } }, @@ -5015,7 +5015,7 @@ effect() { setInterval(() => { for (let i = 0; i < mob.length; i++) { - if (!mob[i].isShielded && !mob[i].shield && mob[i].dropPowerUp) spawn.shield(mob[i], mob[i].position.x, mob[i].position.y, 1, true); + 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 }, @@ -5048,7 +5048,7 @@ }, { name: "panopticon", - description: "experiment: mobs can see you all the time", + description: "experiment: mobs can always see you", maxCount: 1, count: 0, frequency: 0, @@ -5062,7 +5062,7 @@ effect() { setInterval(() => { for (let i = 0; i < mob.length; i++) { - if (!mob[i].shield && mob[i].dropPowerUp) { + if (!mob[i].shield && mob[i].isDropPowerUp) { mob[i].locatePlayer() mob[i].seePlayer.yes = true; } @@ -5071,6 +5071,26 @@ }, remove() {} }, + { + 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 + } + }, + //************************************************** //************************************************** JUNK //************************************************** tech @@ -5093,9 +5113,29 @@ // }, // remove() {} // }, + { + name: "decomposers", + description: "after they die mobs leave behind spawns", + maxCount: 1, + count: 0, + frequency: 0, + isExperimentHide: true, + isNonRefundable: true, + isJunk: true, + allowed() { + return build.isExperimentSelection + }, + requires: "", + effect() { + tech.deathSpawns = 0.2 + }, + remove() { + tech.deathSpawns = 0 + } + }, { name: "panopticon", - description: "experiment: mobs can see you all the time", + description: "mobs can always see you", maxCount: 1, count: 0, frequency: 0, @@ -5109,7 +5149,7 @@ effect() { setInterval(() => { for (let i = 0; i < mob.length; i++) { - if (!mob[i].shield && mob[i].dropPowerUp) { + if (!mob[i].shield && mob[i].isDropPowerUp) { mob[i].locatePlayer() mob[i].seePlayer.yes = true; } @@ -6365,5 +6405,6 @@ isNoHeals: null, frequencyResonance: null, isAlwaysFire: null, - isDroneRespawn: null + isDroneRespawn: null, + deathSpawns: null } \ No newline at end of file diff --git a/todo.txt b/todo.txt index a20f323..cc8ad71 100644 --- a/todo.txt +++ b/todo.txt @@ -1,16 +1,19 @@ ******************************************************** NEXT PATCH ******************************************************** - -experiment and junk: panopticon - mobs can see you all the time -scrap bots now have a 33% chance to spawn for 10 seconds after killing a mob - (was 20% chance for 20 seconds) -tech: scrap refit - killing a mob resets your functional scrap bots back to 10 seconds of operation +experiment and junk tech: decomposers - mobs leave behind spawns when they die -several damage tech have reduced damage by about 10% -spores do 20% more damage, but last 1 second shorter +new levelBoss - a cluster of larger spawns + while it's alive all mobs other leave behind spawns + +added block collisions to most no collide mobs + (this should buff block throwing and pilot wave) ******************************************************** BUGS ******************************************************** +Copied build urls broke. You get the guns but none of the tech + +spawns are forming node groups, but why?? + you have to press z once to get copy to work for simulation.enableConstructMode() sometimes not sure how to reproduce, but it happens often on the first draw @@ -39,6 +42,34 @@ fix door.isOpen actually meaning isClosed? ******************************************************** TODO ******************************************************** +tech plasma field - plasma field becomes an aoe damage field with the same radius + 200% more energy drain, 100% more damage + draw a square (or two) that rapidly spins + +blocking produces ice-IX + at the block location? + how to get bullets to not hit the blocked mob + spawn at player head? + only applies to blocking with a cool down + nano-scale? + standing wave harmonics + maybe just a chance to proc for perfect diamagnetism + +laser beam splitter should only increase by 1,2,3,4 not 1,3,5 + +tech field: while _____ is active take 100% more harm and do 100% more damage + while firing + or while plasma field is active + +make a boss that increases tech.deathSpawns while it is alive + tech.deathSpawns += 2 + on death tech.deathSpawns -= 2 + how to make it clear that the bos is producing the spawns? + boss is make of many spawn-like mobs + but they need to have a different color from spawns + similar to how cellBoss works + with stronger flocking/attracting forces + quantum foam: hold fire to charge up foam, release fire to let go an amount relative to hold long you held fire foam gun fires a bullet that tracks how long mouse is down when mouse is up it streams out a hose of foam based on how long foam was down