From 05a263e31fd395cb455dca7c6a9c6737cee45ff1 Mon Sep 17 00:00:00 2001 From: landgreen Date: Mon, 1 Aug 2022 08:54:24 -0700 Subject: [PATCH] Hey Listen! snakeBoss is now dragonFlyBoss snakeSpitBoss till exists, don't worry flutter and beetle mobs changes Noether violation has 50% less forward recoil for shotgun --- js/bullet.js | 12 +++--- js/level.js | 21 ++++++---- js/mob.js | 6 +-- js/spawn.js | 116 +++++++++++++++++++++++++++++++++++++-------------- js/tech.js | 2 +- todo.txt | 19 +++------ 6 files changed, 112 insertions(+), 64 deletions(-) diff --git a/js/bullet.js b/js/bullet.js index 1ad5f6e..8ace739 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -5433,8 +5433,8 @@ const b = { } if (tech.isShotgunReversed) { - player.force.x += 4 * knock * Math.cos(m.angle) - player.force.y += 4 * knock * Math.sin(m.angle) - 6 * player.mass * simulation.g + player.force.x += 1.6 * knock * Math.cos(m.angle) + player.force.y += 1.6 * knock * Math.sin(m.angle) - 3 * player.mass * simulation.g } else if (tech.isShotgunRecoil) { m.fireCDcycle -= 0.66 * (56 * b.fireCDscale) player.force.x -= 2 * knock * Math.cos(m.angle) @@ -5585,16 +5585,16 @@ const b = { b.iceIX(25 + 20 * Math.random(), m.angle + spread * (Math.random() - 0.5)) } } else if (tech.isFoamShot) { - const spread = (input.down ? 0.2 : 0.6) + const spread = (input.down ? 0.15 : 0.4) const where = { x: m.pos.x + 25 * Math.cos(m.angle), y: m.pos.y + 25 * Math.sin(m.angle) } - const number = 15 * (tech.isShotgunReversed ? 1.6 : 1) + const number = 16 * (tech.isShotgunReversed ? 1.6 : 1) for (let i = 0; i < number; i++) { - const SPEED = 13 + 4 * Math.random(); + const SPEED = 11 + 4 * Math.random(); const angle = m.angle + spread * (Math.random() - 0.5) - b.foam(where, { x: SPEED * Math.cos(angle), y: SPEED * Math.sin(angle) }, 6 + 8 * Math.random()) + b.foam(where, { x: SPEED * Math.cos(angle), y: SPEED * Math.sin(angle) }, 8 + 7 * Math.random()) } } else if (tech.isNeedles) { const number = 9 * (tech.isShotgunReversed ? 1.6 : 1) diff --git a/js/level.js b/js/level.js index e8381e2..dd46a4b 100644 --- a/js/level.js +++ b/js/level.js @@ -16,7 +16,7 @@ const level = { start() { if (level.levelsCleared === 0) { //this code only runs on the first level // simulation.enableConstructMode() //used to build maps in testing mode - // level.difficultyIncrease(8 * 4) //30 is near max on hard //60 is near max on why + // level.difficultyIncrease(2 * 4) //30 is near max on hard //60 is near max on why // simulation.isHorizontalFlipped = true // m.maxHealth = m.health = 100 // powerUps.research.changeRerolls(100000) @@ -24,8 +24,9 @@ const level = { // powerUps.research.changeRerolls(100) // tech.tech[297].frequency = 100 // b.guns[0].ammo = 10000 + // m.setField("time dilation") //molecular assembler time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass - // b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 matter wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser + // b.giveGuns("shotgun") //0 nail gun 1 shotgun 2 super balls 3 matter wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // tech.giveTech("infrared diode"); // tech.giveTech("active cooling"); // tech.giveTech("pulse") @@ -35,10 +36,12 @@ const level = { // for (let i = 0; i < 1; i++) tech.giveTech("dynamic equilibrium") // for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "research"); + // spawn.starter(1900, -500, 200) // spawn.starter(1900, -500, 50) + // spawn.dragonFlyBoss(1900, -400) // spawn.beetleBoss(1900, -400) - // for (let i = 0; i < 10; ++i) spawn.flutter(1900 + 300 * Math.random(), -500 + 300 * Math.random()) + // for (let i = 0; i < 2; ++i) spawn.flutter(1900 + 300 * Math.random(), -500 + 300 * Math.random()) // level.testing(); //not in rotation, used for testing // for (let i = 0; i < 7; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research"); // for (let i = 0; i < 4; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech"); @@ -2805,7 +2808,7 @@ const level = { // spawn.laserTargetingBoss(1700, -500) // spawn.powerUpBoss(1900, -500) // spawn.powerUpBossBaby(3200, -500) - // spawn.snakeBoss(1700, -500) + // spawn.dragonFlyBoss(1700, -500) // spawn.streamBoss(3200, -500) // spawn.pulsarBoss(1700, -500) // spawn.spawnerBossCulture(3200, -500) @@ -5863,10 +5866,10 @@ const level = { spawn.randomSmallMob(-900, 825); if (simulation.difficulty > 1) { - if (Math.random() < 0.70) { + if (Math.random() < 0.80) { spawn.randomLevelBoss(-800, -1300) } else { - spawn.snakeBoss(-1000 + Math.random() * 2500, -1300); //boss snake with head + spawn.dragonFlyBoss(-1000 + Math.random() * 2500, -1300); //boss snake with head } } powerUps.addResearchToLevel() //needs to run after mobs are spawned @@ -6546,7 +6549,7 @@ const level = { spawn.tetherBoss(2300, -1300, { x: 2300, y: -1750 }) if (simulation.difficulty > 4) spawn.nodeGroup(2350, -1300, "spawns", 8, 20, 105); } else { - spawn.randomLevelBoss(2300, -1400, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "snakeBoss", "pulsarBoss"]); + spawn.randomLevelBoss(2300, -1400, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "dragonFlyBoss", "pulsarBoss"]); } } } @@ -7394,7 +7397,7 @@ const level = { spawn.tetherBoss(3380, -1775, { x: 3775, y: -1775 }) if (simulation.difficulty > 4) spawn.nodeGroup(3380, -1775, "spawns", 8, 20, 105); //chance to spawn a ring of exploding mobs around this boss } else { - spawn.randomLevelBoss(3100, -1850, ["shooterBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "snakeBoss", "laserBoss"]); + spawn.randomLevelBoss(3100, -1850, ["shooterBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "dragonFlyBoss", "laserBoss"]); } } }, @@ -7843,7 +7846,7 @@ const level = { // spawn.randomGroup(7700, -1100, 0.5); spawn.randomGroup(9800, -1100, 0.5); - if (simulation.difficulty > 3) spawn.randomLevelBoss(8600, -600, ["powerUpBoss", "bomberBoss", "snakeBoss", "spiderBoss", "historyBoss"]) + if (simulation.difficulty > 3) spawn.randomLevelBoss(8600, -600, ["powerUpBoss", "bomberBoss", "dragonFlyBoss", "spiderBoss", "historyBoss"]) spawn.secondaryBossChance(7900, -400) //Boss Spawning diff --git a/js/mob.js b/js/mob.js index 54f277f..3e6a57e 100644 --- a/js/mob.js +++ b/js/mob.js @@ -589,7 +589,7 @@ const mobs = { ctx.setLineDash([]); } }, - wing(a, radius = 250, ellipticity = 0.4) { + wing(a, radius = 250, ellipticity = 0.4, dmg = 0.0004) { const minorRadius = radius * ellipticity const perp = { x: Math.cos(a), y: Math.sin(a) } // const where = Vector.add(this.position, Vector.mult(perp, radius + 0.8 * this.radius)) @@ -601,8 +601,8 @@ const mobs = { //check for wing -> player damage const hitPlayer = Matter.Query.ray([player], this.position, Vector.add(this.position, Vector.mult(perp, radius * 2.05)), minorRadius) if (hitPlayer.length && m.immuneCycle < m.cycle) { - m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage - m.damage(0.00008 * radius * simulation.dmgScale); + m.damage(dmg * simulation.dmgScale); + // m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage } }, searchSpring() { diff --git a/js/spawn.js b/js/spawn.js index adb3294..e7a2572 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -5,8 +5,8 @@ const spawn = { randomBossList: [ "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "powerUpBossBaby", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", - "snakeBoss", "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss", "shieldingBoss", "timeSkipBoss", - "beetleBoss" + "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss", "shieldingBoss", "timeSkipBoss", + "dragonFlyBoss", "beetleBoss" ], bossTypeSpawnOrder: [], //preset list of boss names calculated at the start of a run by the randomSeed bossTypeSpawnIndex: 0, //increases as the boss type cycles @@ -21,11 +21,11 @@ const spawn = { }, pickList: ["starter", "starter"], fullPickList: [ + "flutter", "flutter", "flutter", "hopper", "hopper", "hopper", "slasher", "slasher", "slasher", "stabber", "stabber", "stabber", "springer", "springer", "springer", - "flutter", "flutter", "shooter", "shooter", "grenadier", "grenadier", "striker", "striker", @@ -2696,7 +2696,7 @@ const spawn = { mobs.spawn(x, y, 7, radius, '#16576b'); let me = mob[mob.length - 1]; me.isBoss = true; - Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger + Matter.Body.setDensity(me, 0.0016); //extra dense //normal is 0.001 //makes effective life much larger // me.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front @@ -2714,7 +2714,7 @@ const spawn = { // me.onDeath = function() {}; me.flapRate = 0.3 + Math.floor(3 * Math.random()) / 10 + 100 * me.accelMag - me.flapRadius = 100 + 75 * Math.random() + radius * 2 + me.flapRadius = 75 + 50 * Math.random() + radius * 2 me.do = function() { this.seePlayerByHistory() this.checkStatus(); @@ -2764,9 +2764,12 @@ const spawn = { me.nextHealthThreshold = 0.75 me.invulnerableCount = 0 + me.flapRate = 0.25 + me.wingSize = 0 + me.wingGoal = 250 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.0006 + 0.0006 * Math.sqrt(simulation.accelScale); + me.accelMag = 0.0005 + 0.0005 * Math.sqrt(simulation.accelScale); me.frictionAir = 0.05; me.seePlayerFreq = 30 me.memory = 420; @@ -2777,22 +2780,53 @@ const spawn = { me.fireDir = { x: 0, y: 0 } spawn.shield(me, x, y); - // for (let i = 0, len = 4 + 0.2 * simulation.difficulty; i < len; ++i) { - // const phase = i / len * 2 * Math.PI - // const where = Vector.add(me.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5)) - // spawn.flutter(where.x, where.y) + // len = 0.3 * simulation.difficulty //spawn some baby flutters + // if (len > 3) { + // for (let i = 0; i < len; ++i) { + // const phase = i / len * 2 * Math.PI + // const where = Vector.add(me.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5)) + // spawn.flutter(where.x, where.y) + // } // } + if (Math.random() < 0.3) { + const len = 0.1 * simulation.difficulty //spawn some baby flutters + let i = 0 + let spawnFlutters = () => { + if (i < len) { + if (!(simulation.cycle % 30) && !simulation.paused && !simulation.isChoosing) { + const phase = i / len * 2 * Math.PI + const where = Vector.add(me.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5)) + spawn.flutter(where.x, where.y) + i++ + } + requestAnimationFrame(spawnFlutters); + } + } + requestAnimationFrame(spawnFlutters); + me.isAlreadyHadBabies = true + } + + + me.onDeath = function() { powerUps.spawnBossPowerUp(this.position.x, this.position.y) - len = 0.2 * simulation.difficulty - if (len > 3) { - for (let i = 0; i < len; ++i) { - const phase = i / len * 2 * Math.PI - const where = Vector.add(this.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5)) - spawn.flutter(where.x, where.y) + const len = 0.1 * simulation.difficulty //spawn some baby flutters + if (len > 3 && !this.isAlreadyHadBabies) { + let i = 0 + let spawnFlutters = () => { + if (i < len) { + if (!(simulation.cycle % 20) && !simulation.paused && !simulation.isChoosing) { + const phase = i / len * 2 * Math.PI + const where = Vector.add(me.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5)) + spawn.flutter(where.x, where.y) + i++ + } + requestAnimationFrame(spawnFlutters); + } } + requestAnimationFrame(spawnFlutters); } }; me.onDamage = function() { @@ -2803,6 +2837,10 @@ const spawn = { this.isInvulnerable = true this.damageReduction = 0 this.frictionAir = 0 + this.wingGoal = 0 + this.wingSize = 0 + this.flapRate += 0.1 + this.accelMag *= 1.25 } }; me.do = function() { @@ -2814,6 +2852,7 @@ const spawn = { this.isInvulnerable = false this.damageReduction = this.startingDamageReduction this.frictionAir = 0.05 + this.wingGoal = 250 } // //draw wings as if they are protecting // const wingShield = (a, size) => { @@ -2868,11 +2907,13 @@ const spawn = { } else if (c < -threshold) { this.torque -= turn; } - const flapRate = 0.5 const flapArc = 0.7 //don't go past 1.57 for normal flaps + this.wingSize = 0.98 * this.wingSize + 0.02 * this.wingGoal ctx.fillStyle = this.fill = `hsla(${160+40*Math.random()}, 100%, ${25 + 25*Math.random()*Math.random()}%, 0.9)`; //"rgba(0,235,255,0.3)"; // ctx.fillStyle = `hsla(44, 79%, 31%,0.4)`; //"rgba(0,235,255,0.3)"; - this.wing(this.angle + Math.PI / 2 + flapArc * Math.sin(simulation.cycle * flapRate), 250, 0.5) - this.wing(this.angle - Math.PI / 2 - flapArc * Math.sin(simulation.cycle * flapRate), 250, 0.5) + this.wing(this.angle + Math.PI / 2 + flapArc * Math.sin(simulation.cycle * this.flapRate), this.wingSize, 0.5, 0.0008) + this.wing(this.angle - Math.PI / 2 - flapArc * Math.sin(simulation.cycle * this.flapRate), this.wingSize, 0.5, 0.0008) + } else { + this.wingSize = 0.96 * this.wingSize + 0 //shrink while stunned } }; }, @@ -5944,13 +5985,13 @@ const spawn = { Composite.add(engine.world, consBB[consBB.length - 1]); // spawn.shield(me, x, y, 1); }, - snakeBoss(x, y, radius = 50) { //snake boss with a laser head + dragonFlyBoss(x, y, radius = 42) { //snake boss with a laser head const nodes = Math.min(8 + Math.ceil(0.5 * simulation.difficulty), 40) let angle = Math.PI let mag = 300 - const color1 = "#f27" - mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, color1); //"rgb(55,170,170)" + const color1 = "#00bfd9" //"#f27" + mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, "#000"); //"rgb(55,170,170)" let me = mob[mob.length - 1]; me.isBoss = true; me.accelMag = 0.0009 + 0.0002 * Math.sqrt(simulation.accelScale) @@ -5971,18 +6012,34 @@ const spawn = { this.seePlayerByHistory() this.checkStatus(); this.attraction(); - this.harmZone(); + + let a //used to set the angle of wings if (this.isInvulnerable) { ctx.beginPath(); let vertices = this.vertices; ctx.moveTo(vertices[0].x, vertices[0].y); for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y); ctx.lineTo(vertices[0].x, vertices[0].y); - ctx.lineWidth = 20; - ctx.strokeStyle = "rgba(255,255,255,0.7)"; + ctx.lineWidth = 12; + ctx.strokeStyle = "rgba(255,255,255,0.9)"; ctx.stroke(); + const sub = Vector.sub(this.position, this.snakeBody1.position) + a = Math.atan2(sub.y, sub.x) + } else { + a = Math.atan2(this.velocity.y, this.velocity.x) } + + ctx.fillStyle = `hsla(${160+40*Math.random()}, 100%, ${25 + 25*Math.random()*Math.random()}%, 0.9)`; //"rgba(0,235,255,0.3)"; // ctx.fillStyle = `hsla(44, 79%, 31%,0.4)`; //"rgba(0,235,255,0.3)"; + this.wing(a + Math.PI / 2 + this.angleOff + this.flapArc * Math.sin(simulation.cycle * this.flapRate), this.wingLength, this.ellipticity) + this.wing(a - Math.PI / 2 - this.angleOff - this.flapArc * Math.sin(simulation.cycle * this.flapRate), this.wingLength, this.ellipticity) + this.wing(a - Math.PI / 2 + this.angleOff + this.flapArc * Math.sin(simulation.cycle * this.flapRate), this.wingLength, this.ellipticity) + this.wing(a + Math.PI / 2 - this.angleOff - this.flapArc * Math.sin(simulation.cycle * this.flapRate), this.wingLength, this.ellipticity) }; + me.flapRate = 0.4 + me.flapArc = 0.2 //don't go past 1.57 for normal flaps + me.wingLength = 150 + me.ellipticity = 0.3 + me.angleOff = 0.4 //extra space to give head room angle -= 0.1 mag -= 10 @@ -5992,16 +6049,13 @@ const spawn = { mag -= (i < 2) ? -15 : 5 spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), i === 0 ? 25 : 20); if (i < 3) mob[mob.length - 1].snakeHeadID = me.id + if (i === 0) me.snakeBody1 = mob[mob.length - 1] //track this segment, so the difference in position between this segment and the head can be used to angle the wings mob[mob.length - 1].previousTailID = previousTailID previousTailID = mob[mob.length - 1].id } this.constrain2AdjacentMobs(nodes, Math.random() * 0.06 + 0.01); for (let i = mob.length - 1, len = i - nodes; i > len; i--) { //set alternating colors - if (i % 2) { - mob[i].fill = "#333" - } else { - mob[i].fill = color1 - } + mob[i].fill = `hsla(${160+40*Math.random()}, 100%, ${5 + 25*Math.random()*Math.random()}%, 0.9)` } //constraint with first 3 mobs in line consBB[consBB.length] = Constraint.create({ @@ -6028,7 +6082,7 @@ const spawn = { mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)"); let me = mob[mob.length - 1]; me.collisionFilter.mask = cat.bullet | cat.player | cat.mob //| cat.body - me.damageReduction = 0.2 + me.damageReduction = 0.23 Matter.Body.setDensity(me, 0.005); //normal is 0.001 // me.accelMag = 0.0007 * simulation.accelScale; diff --git a/js/tech.js b/js/tech.js index c5c094d..f55feb3 100644 --- a/js/tech.js +++ b/js/tech.js @@ -4164,7 +4164,7 @@ const tech = { { name: "Noether violation", link: `Noether violation`, - description: "+60% shotgun damage
shotgun recoil is increased and reversed", + description: "+60% shotgun damage
shotgun recoil is reversed", isGunTech: true, maxCount: 1, count: 0, diff --git a/todo.txt b/todo.txt index 8ab7dbc..1d32582 100644 --- a/todo.txt +++ b/todo.txt @@ -1,27 +1,18 @@ ******************************************************** NEXT PATCH ************************************************** -mob: beetleBoss -mob: flutter +snakeBoss is now dragonFlyBoss + snakeSpitBoss till exists, don't worry -balance: all mobs at every level are about 2%-3% harder to kill +flutter and beetle mobs changes + +Noether violation has 50% less forward recoil for shotgun *********************************************************** TODO ***************************************************** -wings - put in mob as a method? - add parameter for ellipticity - give snakeBoss wings? - - - mob mechanics bullets hit player and stay attached for 4-5 seconds, slowing player hopperBullets? black hole sucker effect on tail - flickering wings - draw pair of circles at 2 different locations, like beetle wings flapping - draw as ellipse - damage player if caught in wings vines attached to map and grows, a series of spheres connected by vines if node dies it's removed from tree