From feb8824bc758d3aa07ba88455064edada2acc697 Mon Sep 17 00:00:00 2001 From: landgreen Date: Wed, 28 Dec 2022 12:35:03 -0800 Subject: [PATCH] not a full patch, just syncing between my 2 computers --- .DS_Store | Bin 10244 -> 10244 bytes js/bullet.js | 274 +++++++++++++++++++---------------------------- js/index.js | 2 +- js/level.js | 14 +-- js/mob.js | 40 ++++--- js/player.js | 2 +- js/powerup.js | 4 +- js/simulation.js | 2 +- js/spawn.js | 195 +++++++++++++++++++++++++++------ js/tech.js | 94 ++++++++++++---- style.css | 125 +++++++++++++-------- todo.txt | 34 +++--- 12 files changed, 473 insertions(+), 313 deletions(-) diff --git a/.DS_Store b/.DS_Store index bd2f5c8cac999defc2733979a1dde8cb8fc09970..42f9a31a655fdebaff48e34ff8e79aee9f3eb052 100644 GIT binary patch delta 532 zcmZn(XbG6$aFU^hRb>Si7RZpM0UhBSsmhBAgshGd3(hCBv62+K1kKRGEUKZ${X zK>&yyfmrW97ywxe49q}PxeV!Os@7vyl~i6_05xkzQbA5;afyM!HAW_87FIU)$yS1i z>Jrt}hUR8E3PuKIwK@vbmPQ6T3MR&8wY8iaqRRT#LGjr+xq10rljljuGj?x&EGWPh z$^~>l9zzO4DnkX($r%hKK(&Jj39R-YvBND$Onc;K2SpmFic9&tN{4}s(xeQJ?72q3cpx3 JFB4&A1^_=}nE3zz delta 132 zcmZn(XbG6$&nUAoU^hRb%w`?|ZpO*Qfq*6Ju!8=4yf zITl8SwY8iaqRRT#LGjr+xq12BlLIB?8GAO{2??;VGBIQ^6i=3wIyt#SvU#(tlt1If hloHm>> 60) this.do = this.collidePlayerDo + this.force.y += this.mass * 0.0012; + }; + } else { + bullet[me].do = function() { + this.cycle++ + this.force.y += this.mass * 0.0012; + }; + } + bullet[me].beforeDmg = function(who) { + if (tech.oneSuperBall) mobs.statusStun(who, 120) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds) + // if (tech.isIncendiary) { + // b.explosion(this.position, this.mass * (240+70 * Math.random()) ); //makes bullet do explosive damage at end + // this.endCycle = 0 + // } + if (tech.isFoamBall) { + for (let i = 0, len = 6 * this.mass; i < len; i++) { + const radius = 5 + 8 * Math.random() + // const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 } + const velocity = { + x: Math.max(0.5, 2 - radius * 0.1), + y: 0 + } + b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius) + } + this.endCycle = 0 + } + }; + }, // plasmaBall(position, velocity, radius) { // // radius *= Math.sqrt(tech.bulletSize) // const me = bullet.length; @@ -6110,181 +6171,59 @@ const b = { do() {}, foamBall() { + }, fireOne() { - const SPEED = input.down ? 40 : 33 m.fireCDcycle = m.cycle + Math.floor((input.down ? 27 : 19) * b.fireCDscale); // cool down - let dir = m.angle - const me = bullet.length; - bullet[me] = Bodies.polygon(m.pos.x + 30 * Math.cos(m.angle), m.pos.y + 30 * Math.sin(m.angle), 12, 21 * tech.bulletSize, b.fireAttributes(dir, false)); - Composite.add(engine.world, bullet[me]); //add bullet to world - Matter.Body.setVelocity(bullet[me], { - x: SPEED * Math.cos(dir), - y: SPEED * Math.sin(dir) - }); - // Matter.Body.setDensity(bullet[me], 0.0001); - bullet[me].endCycle = simulation.cycle + Math.floor(300 + 90 * Math.random()); - bullet[me].minDmgSpeed = 0; - bullet[me].restitution = 1; - bullet[me].friction = 0; - bullet[me].do = function() { - this.force.y += this.mass * 0.0012; - }; - if (tech.isIncendiary) { - bullet[me].do = function() { - this.force.y += this.mass * 0.0012; - if (Matter.Query.collides(this, map).length) { - b.explosion(this.position, this.mass * 280); //makes bullet do explosive damage at end - this.endCycle = 0 - } - }; - } else { - bullet[me].do = function() { - this.force.y += this.mass * 0.0012; - }; - } - bullet[me].beforeDmg = function(who) { - mobs.statusStun(who, 120) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds) - if (tech.isIncendiary) { - b.explosion(this.position, this.mass * 280); //makes bullet do explosive damage at end - this.endCycle = 0 - } - if (tech.isFoamBall) { - for (let i = 0, len = 6 * this.mass; i < len; i++) { - const radius = 5 + 8 * Math.random() - // const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 } - const velocity = { - x: Math.max(0.5, 2 - radius * 0.1), - y: 0 - } - b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius) - } - this.endCycle = 0 - } - }; + const speed = input.down ? 43 : 36 + b.superBall({ + x:m.pos.x + 30 * Math.cos(m.angle), + y:m.pos.y + 30 * Math.sin(m.angle) + },{ + x: speed * Math.cos(m.angle), + y: speed * Math.sin(m.angle) + }, 21 * tech.bulletSize) }, fireMulti() { - const SPEED = input.down ? 43 : 36 m.fireCDcycle = m.cycle + Math.floor((input.down ? 23 : 15) * b.fireCDscale); // cool down const SPREAD = input.down ? 0.08 : 0.13 const num = 3 + Math.floor(tech.extraSuperBalls * Math.random()) - const radius = 11 * tech.bulletSize + const speed = input.down ? 43 : 36 let dir = m.angle - SPREAD * (num - 1) / 2; for (let i = 0; i < num; i++) { - const me = bullet.length; - bullet[me] = Bodies.polygon(m.pos.x + 30 * Math.cos(m.angle), m.pos.y + 30 * Math.sin(m.angle), 12, radius, b.fireAttributes(dir, false)); - Composite.add(engine.world, bullet[me]); //add bullet to world - Matter.Body.setVelocity(bullet[me], { - x: SPEED * Math.cos(dir), - y: SPEED * Math.sin(dir) - }); - // Matter.Body.setDensity(bullet[me], 0.0001); - bullet[me].endCycle = simulation.cycle + Math.floor((300 + 90 * Math.random()) * tech.isBulletsLastLonger); - bullet[me].minDmgSpeed = 0; - bullet[me].restitution = 0.99; - bullet[me].friction = 0; - if (tech.isIncendiary) { - bullet[me].do = function() { - this.force.y += this.mass * 0.0012; - if (Matter.Query.collides(this, map).length) { - b.explosion(this.position, this.mass * 280); //makes bullet do explosive damage at end - this.endCycle = 0 - } - }; - } else { - bullet[me].do = function() { - this.force.y += this.mass * 0.0012; - }; - } - bullet[me].beforeDmg = function() { - if (tech.isIncendiary) { - b.explosion(this.position, this.mass * 320 + 70 * Math.random()); //makes bullet do explosive damage at end - this.endCycle = 0 - } - if (tech.isFoamBall) { - for (let i = 0, len = 6 * this.mass; i < len; i++) { - const radius = 5 + 8 * Math.random() - const velocity = { - x: Math.max(0.5, 2 - radius * 0.1), - y: 0 - } - b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius) - } - this.endCycle = 0 - // this.mass = 0 //prevent damage - } - }; + b.superBall({ + x:m.pos.x + 30 * Math.cos(dir), + y:m.pos.y + 30 * Math.sin(dir) + },{ + x: speed * Math.cos(dir), + y: speed * Math.sin(dir) + }, 11 * tech.bulletSize) dir += SPREAD; } }, fireQueue() { - // const dir = m.angle - // const x = m.pos.x - // const y = m.pos.y - const SPEED = input.down ? 43 : 36 + m.fireCDcycle = m.cycle + Math.floor((input.down ? 23 : 15) * b.fireCDscale); // cool down const num = 1 + 3 + Math.floor(tech.extraSuperBalls * Math.random()) //1 extra + const speed = input.down ? 43 : 36 + const delay = Math.floor((input.down ? 18 : 12) * b.fireCDscale) m.fireCDcycle = m.cycle + delay; // cool down - - const fireBall = () => { - const me = bullet.length; - bullet[me] = Bodies.polygon(m.pos.x, m.pos.y, 12, 11 * tech.bulletSize, b.fireAttributes(m.angle, false)); - Composite.add(engine.world, bullet[me]); //add bullet to world - Matter.Body.setVelocity(bullet[me], { - x: SPEED * Math.cos(m.angle), - y: SPEED * Math.sin(m.angle) - }); - bullet[me].endCycle = simulation.cycle + Math.floor(330 * tech.isBulletsLastLonger); - bullet[me].minDmgSpeed = 0; - bullet[me].restitution = 0.99; - bullet[me].friction = 0; - if (tech.isIncendiary) { - bullet[me].do = function() { - this.force.y += this.mass * 0.0012; - if (Matter.Query.collides(this, map).length) { - b.explosion(this.position, this.mass * 280); //makes bullet do explosive damage at end - this.endCycle = 0 - } - }; - } else { - bullet[me].do = function() { - this.force.y += this.mass * 0.0012; - }; - } - bullet[me].beforeDmg = function() { - if (tech.isIncendiary) { - b.explosion(this.position, this.mass * 320 + 70 * Math.random()); //makes bullet do explosive damage at end - this.endCycle = 0 - } - if (tech.isFoamBall) { - for (let i = 0, len = 6 * this.mass; i < len; i++) { - const radius = 5 + 8 * Math.random() - const velocity = { - x: Math.max(0.5, 2 - radius * 0.1), - y: 0 - } - b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius) - } - this.endCycle = 0 - // this.mass = 0 //prevent damage - } - }; - m.fireCDcycle = m.cycle + delay; // cool down - } - function cycle() { - // if (simulation.paused || m.isBodiesAsleep) { - // requestAnimationFrame(cycle) - // } else { count++ - // if (count % 2) - fireBall() + b.superBall({ + x:m.pos.x + 30 * Math.cos(m.angle), + y:m.pos.y + 30 * Math.sin(m.angle) + },{ + x: speed * Math.cos(m.angle), + y: speed * Math.sin(m.angle) + }, 11 * tech.bulletSize) if (count < num && m.alive) requestAnimationFrame(cycle); - // } + m.fireCDcycle = m.cycle + delay; // cool down } let count = 0 requestAnimationFrame(cycle); - // fireBall(); + + }, chooseFireMethod() { //set in simulation.startGame if (tech.oneSuperBall) { @@ -6871,17 +6810,13 @@ const b = { }); that.do = that.grow; } - const mobCollisions = Matter.Query.collides(this, mob) if (mobCollisions.length) { onCollide(this) this.stuckTo = mobCollisions[0].bodyA - + if (tech.isZombieMobs) this.stuckTo.isSoonZombie = true if (this.stuckTo.isVerticesChange) { - this.stuckToRelativePosition = { - x: 0, - y: 0 - } + this.stuckToRelativePosition = {x: 0, y: 0} } else { //find the relative position for when the mob is at angle zero by undoing the mobs rotation this.stuckToRelativePosition = Vector.rotate(Vector.sub(this.position, this.stuckTo.position), -this.stuckTo.angle) @@ -6968,7 +6903,6 @@ const b = { }; //spawn bullets on end bullet[me].onEnd = function() { - let count = 0 //used in for loop below const things = [ () => { //spore @@ -7000,6 +6934,14 @@ const b = { () => { //nail b.targetedNail(this.position, 1, 39 + 6 * Math.random()) }, + () => { //super ball + const speed = 36 + const angle = 2*Math.PI*Math.random() + b.superBall(this.position,{ + x: speed * Math.cos(angle), + y: speed * Math.sin(angle) + }, 11 * tech.bulletSize) + }, ] for (len = this.totalSpores; count < len; count++) { diff --git a/js/index.js b/js/index.js index 679bd70..d65b6e4 100644 --- a/js/index.js +++ b/js/index.js @@ -588,7 +588,7 @@ ${simulation.isCheating ? "

lore disabled": ""} }, populateGrid() { //background-color:var(--build-bg-color); let text = ` -
+
diff --git a/js/level.js b/js/level.js index 5e52138..5a9fcc4 100644 --- a/js/level.js +++ b/js/level.js @@ -31,19 +31,21 @@ const level = { // b.giveGuns("nail gun") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("spores") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.guns[0].ammo = 10000 - // tech.giveTech("alternator") - // tech.giveTech("posture") - // for (let i = 0; i < 1; ++i) tech.giveTech("Sleipnir") + // tech.giveTech("Zectron") + // tech.giveTech("cordyceps") + // for (let i = 0; i < 1; ++i) tech.giveTech("super ball") // tech.isFoamBall = true - // for (let i = 0; i < 9; ++i) tech.giveTech("emergence") + // for (let i = 0; i < 1; ++i) tech.giveTech("incendiary ammunition") // for (let i = 0; i < 2; i++) tech.giveTech("unified field theory") - // for (let i = 0; i < 9; i++) tech.giveTech("replication") + // for (let i = 0; i < 1; i++) tech.giveTech("colony") // for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); // level.testing(); // spawn.shooter(1900, -500, 200) - // spawn.starter(1900, -500) + // spawn.sneakBoss(1900, -500) + // spawn.starter(1900, -500, 25) + // spawn.sneaker(1900, -500, 25) // spawn.hopper(2538, -950) // for (let i = 0; i < 2; ++i) spawn.starter(1000 + 1000 * Math.random(), -500 + 300 * Math.random()) // tech.addJunkTechToPool(2) diff --git a/js/mob.js b/js/mob.js index b6440f9..5a08c18 100644 --- a/js/mob.js +++ b/js/mob.js @@ -1192,23 +1192,21 @@ const mobs = { this.alive = false; //triggers mob removal in mob[i].replace(i) if (this.isDropPowerUp) { - // if (true) { //spawn zombie on death - // // console.log(this) - // this.leaveBody = false; - - // let count = 45 //delay spawn cycles - // let cycle = () => { - // if (count > 0) { - // if (m.alive) requestAnimationFrame(cycle); - // if (!simulation.paused && !simulation.isChoosing) { - // count-- - // } - // } else { - // spawn.zombie(this.position.x, this.position.y, this.radius, this.vertices.length, this.fill) // zombie(x, y, radius, sides, color) - // } - // } - // requestAnimationFrame(cycle); - // } + if (this.isSoonZombie) { //spawn zombie on death + this.leaveBody = false; + let count = 45 //delay spawn cycles + let cycle = () => { + if (count > 0) { + if (m.alive) requestAnimationFrame(cycle); + if (!simulation.paused && !simulation.isChoosing) { + count-- + } + } else { + spawn.zombie(this.position.x, this.position.y, this.radius, this.vertices.length, this.fill) // zombie(x, y, radius, sides, color) + } + } + requestAnimationFrame(cycle); + } @@ -1248,19 +1246,19 @@ const mobs = { mobs.mobDeaths++ if (Math.random() < tech.sporesOnDeath) { + const amount = Math.min(25, Math.floor(2 + this.mass * (0.5 + 0.5 * Math.random()))) if (tech.isSporeFlea) { - const len = Math.min(25, Math.floor(2 + this.mass * (0.5 + 0.5 * Math.random()))) / 2 + const len = amount / 2 for (let i = 0; i < len; i++) { const speed = 10 + 5 * Math.random() const angle = 2 * Math.PI * Math.random() b.flea(this.position, { x: speed * Math.cos(angle), y: speed * Math.sin(angle) }) } } else if (tech.isSporeWorm) { - const len = Math.min(25, Math.floor(2 + this.mass * (0.5 + 0.5 * Math.random()))) / 2 + const len = amount / 2 for (let i = 0; i < len; i++) b.worm(this.position) } else { - const len = Math.min(25, Math.floor(2 + this.mass * (0.5 + 0.5 * Math.random()))) - for (let i = 0; i < len; i++) b.spore(this.position) + for (let i = 0; i < amount; i++) b.spore(this.position) } } else if (tech.isExplodeMob) { b.explosion(this.position, Math.min(700, Math.sqrt(this.mass + 6) * (30 + 60 * Math.random()))) diff --git a/js/player.js b/js/player.js index 7c6a54a..78f1a2d 100644 --- a/js/player.js +++ b/js/player.js @@ -549,7 +549,7 @@ const m = { if (tech.isZeno) dmg *= 0.15 if (tech.isFieldHarmReduction) dmg *= 0.5 if (tech.isHarmMACHO) dmg *= 0.4 - if (tech.isImmortal) dmg *= 0.66 + if (tech.isImmortal) dmg *= 0.67 if (tech.isSlowFPS) dmg *= 0.8 if (tech.energyRegen === 0) dmg *= 0.34 if (tech.healthDrain) dmg *= 1 + 3.33 * tech.healthDrain //tech.healthDrain = 0.03 at one stack //cause more damage diff --git a/js/powerup.js b/js/powerup.js index 2184e2a..8863f29 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -636,7 +636,7 @@ const powerUps = { } else if (powerUps.research.count > 0) { text += `
` // style = "margin-left: 192px; margin-right: -192px;" text += `
` - for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `
` + for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `
` text += `
  ${tech.isResearchReality?"alternate reality": "research"}
` } else { text += `
` @@ -1300,7 +1300,6 @@ const powerUps = { if (have.length) { choose = have[Math.floor(Math.random() * have.length)] - // simulation.makeTextLog(`
  ${tech.tech[choose].name} was ejected`, 600) //message about what tech was lost simulation.makeTextLog(`tech.remove("${tech.tech[choose].name}")`) for (let i = 0; i < tech.tech[choose].count; i++) { @@ -1318,7 +1317,6 @@ const powerUps = { return false } } else if (tech.tech[choose].count && !tech.tech[choose].isNonRefundable) { - // simulation.makeTextLog(`
  ${tech.tech[choose].name} was ejected`, 600) //message about what tech was lost simulation.makeTextLog(`tech.remove("${tech.tech[choose].name}")`) for (let i = 0; i < tech.tech[choose].count; i++) { diff --git a/js/simulation.js b/js/simulation.js index 08b86b3..8f0310c 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -895,7 +895,7 @@ const simulation = { if (tech.isMutualism && !tech.isEnergyHealth) { for (let i = 0; i < bullet.length; i++) { if (bullet[i].isMutualismActive) { - m.health += 0.01 + 0.01 * (bullet[i].isSpore || bullet[i].isFlea) + m.health += 0.01 + 0.01 * ((bullet[i].isSpore || bullet[i].isFlea) ? 0: 1) if (m.health > m.maxHealth) m.health = m.maxHealth; m.displayHealth(); } diff --git a/js/spawn.js b/js/spawn.js index ad22719..4cad1be 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -6,7 +6,7 @@ const spawn = { "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "powerUpBossBaby", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss", "shieldingBoss", - "timeSkipBoss", "dragonFlyBoss", "beetleBoss" + "timeSkipBoss", "dragonFlyBoss", "beetleBoss", "sneakBoss" ], bossTypeSpawnOrder: [], //preset list of boss names calculated at the start of a run by the randomSeed bossTypeSpawnIndex: 0, //increases as the boss type cycles @@ -31,7 +31,8 @@ const spawn = { "striker", "striker", "laser", "laser", "pulsar", "pulsar", - "launcher", "launcherOne", "exploder", "sneaker", "sucker", "sniper", "spinner", "grower", "beamer", "spawner", "ghoster", + "sneaker", "sneaker", + "launcher", "launcherOne", "exploder", "sucker", "sniper", "spinner", "grower", "beamer", "spawner", "ghoster", //, "focuser" ], mobTypeSpawnOrder: [], //preset list of mob names calculated at the start of a run by the randomSeed @@ -1541,8 +1542,7 @@ const spawn = { zombie(x, y, radius, sides, color) { //mob that attacks other mobs mobs.spawn(x, y, sides, radius, color); let me = mob[mob.length - 1]; - me.damageReduction = 0.5 //take less damage - // Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback + me.damageReduction = 0 //take NO damage until targeting player, but also slowly lose health me.isZombie = true me.isBadTarget = true; me.isDropPowerUp = false; @@ -1550,9 +1550,24 @@ const spawn = { me.stroke = "#83a" me.accelMag = 0.0015 me.frictionAir = 0.01 - // me.collisionFilter.mask = cat.player | cat.map | cat.body - // me.memory = 120; + me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.mob me.seeAtDistance2 = 1000000 //1000 vision range + // me.onDeath = function() { + // const amount = Math.min(10, Math.ceil(this.mass * 0.5)) + // if (tech.isSporeFlea) { + // const len = amount / 2 + // for (let i = 0; i < len; i++) { + // const speed = 10 + 5 * Math.random() + // const angle = 2 * Math.PI * Math.random() + // b.flea(this.position, { x: speed * Math.cos(angle), y: speed * Math.sin(angle) }) + // } + // } else if (tech.isSporeWorm) { + // const len = amount / 2 + // for (let i = 0; i < len; i++) b.worm(this.position) + // } else { + // for (let i = 0; i < amount; i++) b.spore(this.position) + // } + // } me.do = function() { this.zombieHealthBar(); this.lookForMobTargets(); @@ -1572,9 +1587,11 @@ const spawn = { (Vector.magnitudeSquared(Vector.sub(this.position, mob[this.mobSearchIndex].position)) < this.seeAtDistance2 && Matter.Query.ray(map, this.position, mob[this.mobSearchIndex].position).length === 0) ) { this.target = mob[this.mobSearchIndex] - } else if (Math.random() < 0.05 && (Vector.magnitudeSquared(Vector.sub(this.position, player.position)) < this.seeAtDistance2 || Matter.Query.ray(map, this.position, player.position).length === 0)) { + } else if (Math.random() < 0.005 * player.speed && (Vector.magnitudeSquared(Vector.sub(this.position, player.position)) < this.seeAtDistance2 || Matter.Query.ray(map, this.position, player.position).length === 0)) { this.target = player this.isBadTarget = false; + this.damageReduction = 0.5 + me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob } } } @@ -1585,13 +1602,13 @@ const spawn = { Vector.magnitudeSquared(Vector.sub(this.position, this.target.position)) > this.seeAtDistance2 || Matter.Query.ray(map, this.position, this.target.position).length !== 0 ) { - if (this.target === player) this.isBadTarget = true this.target = null } } } me.zombieHealthBar = function() { - this.damage(0.001); //decay + this.health -= 0.0005 //decay + if ((this.health < 0.01 || isNaN(this.health)) && this.alive) this.death(); const h = this.radius * 0.3; const w = this.radius * 2; @@ -1624,7 +1641,7 @@ const spawn = { this.force.y -= force.y; this.target = null //look for a new target - const dmg = 0.3 * m.dmgScale + const dmg = 0.2 * m.dmgScale who.damage(dmg); who.locatePlayer(); simulation.drawList.push({ @@ -1647,7 +1664,6 @@ const spawn = { } // me.onDamage = function(dmg) { // } - }, starter(x, y, radius = Math.floor(15 + 20 * Math.random())) { //easy mob for on level 1 mobs.spawn(x, y, 8, radius, "#9ccdc6"); @@ -5703,21 +5719,132 @@ const spawn = { ctx.setLineDash([]); } }, - sneaker(x, y, radius = 15 + Math.ceil(Math.random() * 10)) { + sneakBoss(x, y, radius = 70) { mobs.spawn(x, y, 5, radius, "transparent"); let me = mob[mob.length - 1]; Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger + me.isBoss = true; + me.damageReduction = 0.4 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) + + me.accelMag = 0.0017 * Math.sqrt(simulation.accelScale); + me.frictionAir = 0.01; + me.g = 0.0001; //required if using this.gravity + me.stroke = "transparent"; //used for drawSneaker + me.alpha = 1; //used in drawSneaker + me.isCloaked = true; //used in drawSneaker + me.isBadTarget = true; + me.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player + me.showHealthBar = false; + me.memory = 30; + me.vanishesLeft = 2+simulation.difficultyMode + me.onDamage = function() { + if (this.vanishesLeft>0 && this.health < 0.1){ //if health is below 10% teleport to a random spot on player history, heal, and cloak + this.vanishesLeft-- + + // const scale = 0.95; + // Matter.Body.scale(this, scale, scale); + // this.radius *= scale; + + //flash screen to hide vanish + for(let i=0; i<8; i++){ + simulation.drawList.push({ + x: this.position.x, + y: this.position.y, + radius: 3000, + color: `rgba(0, 0, 0,${1-0.1*i})`, + time: (i+1)*3 + }); + } + //teleport to near the end of player history + const index = Math.floor( (m.history.length-1)*(0.66+0.2*Math.random() )) + let history = m.history[(m.cycle - index) % 600] + Matter.Body.setPosition(this, history.position) + Matter.Body.setVelocity(this, {x: 0,y: 0}); + + this.seePlayer.recall = 0 + this.cloak(); + this.health = 1; + } + }; + me.cloak = function() { + if (!this.isCloaked) { //stealth + this.alpha = 0; + this.isCloaked = true; + this.isBadTarget = true; + this.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player + this.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) + } + } + me.deCloak = function() { + if (this.isCloaked) { + this.damageReduction = 0.4 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) + this.isCloaked = false; + this.isBadTarget = false; + this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob; //can touch player + } + } + me.do = function() { + this.gravity(); + this.seePlayerByHistory(55); + this.checkStatus(); + this.attraction(); + //draw + if (this.seePlayer.recall) { + if (this.alpha < 1) this.alpha += 0.005 + 0.003 / simulation.CDScale; + } else { + if (this.alpha > 0) this.alpha -= 0.04; + } + if (this.alpha > 0) { + if (this.alpha > 0.7) { + this.healthBar(); + this.deCloak() + } + //draw body + ctx.beginPath(); + const vertices = this.vertices; + ctx.moveTo(vertices[0].x, vertices[0].y); + for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y); + ctx.lineTo(vertices[0].x, vertices[0].y); + ctx.fillStyle = `rgba(0,0,0,${this.alpha * this.alpha})`; + ctx.fill(); + } else { + this.cloak() + } + }; + }, + sneaker(x, y, radius = 15 + Math.ceil(Math.random() * 10)) { + mobs.spawn(x, y, 5, radius, "transparent"); + let me = mob[mob.length - 1]; + // Matter.Body.setDensity(me, 0.001); //extra dense //normal is 0.001 //makes effective life much larger me.accelMag = 0.001 * Math.sqrt(simulation.accelScale); me.frictionAir = 0.01; me.g = 0.0002; //required if using this.gravity me.stroke = "transparent"; //used for drawSneaker me.alpha = 1; //used in drawSneaker - // me.leaveBody = false; - me.canTouchPlayer = false; //used in drawSneaker + me.isNotCloaked = false; //used in drawSneaker me.isBadTarget = true; me.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player me.showHealthBar = false; me.memory = 240; + me.isVanished = false; + me.onDamage = function() { + if (!this.isVanished && this.health < 0.1){ //if health is below 10% teleport to a random spot on player history, heal, and cloak + this.health = 1; + this.isVanished = true + this.cloak(); + //teleport to near the end of player history + Matter.Body.setPosition(this, m.history[Math.floor((m.history.length-1)*(0.66+0.33*Math.random()))].position) + Matter.Body.setVelocity(this, {x: 0,y: 0}); + } + }; + me.cloak = function() { + if (this.isNotCloaked) { //stealth + this.alpha = 0; + this.isNotCloaked = false; + this.isBadTarget = true; + this.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player + } + } me.do = function() { this.gravity(); this.seePlayerByHistory(15); @@ -5732,8 +5859,8 @@ const spawn = { if (this.alpha > 0) { if (this.alpha > 0.7) { this.healthBar(); - if (!this.canTouchPlayer) { - this.canTouchPlayer = true; + if (!this.isNotCloaked) { + this.isNotCloaked = true; this.isBadTarget = false; this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob; //can touch player } @@ -5748,10 +5875,8 @@ const spawn = { ctx.lineTo(vertices[0].x, vertices[0].y); ctx.fillStyle = `rgba(0,0,0,${this.alpha * this.alpha})`; ctx.fill(); - } else if (this.canTouchPlayer) { //stealth - this.canTouchPlayer = false; - this.isBadTarget = true; - this.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player + } else { + this.cloak() } }; }, @@ -5764,7 +5889,7 @@ const spawn = { Matter.Body.setDensity(me, 0.0015); //normal is 0.001 //makes effective life much lower me.stroke = "transparent"; //used for drawGhost me.alpha = 1; //used in drawGhost - me.canTouchPlayer = false; //used in drawGhost + me.isNotCloaked = false; //used in drawGhost me.isBadTarget = true; // me.leaveBody = false; me.collisionFilter.mask = cat.bullet //| cat.body @@ -5791,8 +5916,8 @@ const spawn = { if (this.alpha > 0) { if (this.alpha > 0.8 && this.seePlayer.recall) { this.healthBar(); - if (!this.canTouchPlayer) { - this.canTouchPlayer = true; + if (!this.isNotCloaked) { + this.isNotCloaked = true; this.isBadTarget = false; this.collisionFilter.mask = cat.player | cat.bullet } @@ -5808,8 +5933,8 @@ const spawn = { ctx.lineWidth = 1; ctx.fillStyle = `rgba(255,255,255,${this.alpha * this.alpha})`; ctx.fill(); - } else if (this.canTouchPlayer) { - this.canTouchPlayer = false; + } else if (this.isNotCloaked) { + this.isNotCloaked = false; this.isBadTarget = true; this.collisionFilter.mask = cat.bullet; //can't touch player or walls } @@ -6110,7 +6235,7 @@ const spawn = { me.showHealthBar = false; me.frictionStatic = 0; me.friction = 0; - me.canTouchPlayer = false; //used in drawSneaker + me.isNotCloaked = false; //used in drawSneaker me.isBadTarget = true; me.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player @@ -6192,8 +6317,8 @@ const spawn = { if (this.alpha > 0) { if (this.alpha > 0.95) { this.healthBar(); - if (!this.canTouchPlayer) { - this.canTouchPlayer = true; + if (!this.isNotCloaked) { + this.isNotCloaked = true; this.isBadTarget = false; this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob; //can touch player } @@ -6208,8 +6333,8 @@ const spawn = { ctx.lineTo(vertices[0].x, vertices[0].y); ctx.fillStyle = `rgba(25,0,50,${this.alpha * this.alpha})`; ctx.fill(); - } else if (this.canTouchPlayer) { - this.canTouchPlayer = false; + } else if (this.isNotCloaked) { + this.isNotCloaked = false; this.isBadTarget = true this.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player } @@ -6373,7 +6498,7 @@ const spawn = { // // Matter.Body.setDensity(me, 0.001); //normal is 0.001 //makes effective life much lower // me.stroke = "transparent"; //used for drawGhost // me.alpha = 1; //used in drawGhost - // me.canTouchPlayer = false; //used in drawGhost + // me.isNotCloaked = false; //used in drawGhost // me.isBadTarget = true; // // me.leaveBody = false; // me.collisionFilter.mask = cat.bullet //| cat.body @@ -6414,8 +6539,8 @@ const spawn = { // if (this.alpha > 0) { // if (this.alpha > 0.8 && this.seePlayer.recall) { // this.healthBar(); - // if (!this.canTouchPlayer) { - // this.canTouchPlayer = true; + // if (!this.isNotCloaked) { + // this.isNotCloaked = true; // this.isBadTarget = false; // this.collisionFilter.mask = cat.player | cat.bullet // } @@ -6452,8 +6577,8 @@ const spawn = { // } - // } else if (this.canTouchPlayer) { - // this.canTouchPlayer = false; + // } else if (this.isNotCloaked) { + // this.isNotCloaked = false; // this.isBadTarget = true; // this.collisionFilter.mask = cat.bullet; //can't touch player or walls // } diff --git a/js/tech.js b/js/tech.js index 0e56f47..f4b2565 100644 --- a/js/tech.js +++ b/js/tech.js @@ -4669,9 +4669,9 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return (tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIceShot && !tech.isRivets && !tech.isFoamShot && !tech.isSporeWorm && !tech.isSporeFlea && !tech.isNeedles) || (tech.haveGunCheck("super balls") && !tech.isFoamBall) || (tech.isRivets && !tech.isNailCrit) || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && simulation.molecularMode === 3) || (tech.haveGunCheck("drones") && !tech.isForeverDrones && !tech.isDroneRadioactive && !tech.isDroneTeleport) + return (tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIceShot && !tech.isRivets && !tech.isFoamShot && !tech.isSporeWorm && !tech.isSporeFlea && !tech.isNeedles) || (tech.haveGunCheck("super balls") && !tech.isFoamBall && !tech.isSuperHarm) || (tech.isRivets && !tech.isNailCrit) || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && simulation.molecularMode === 3) || (tech.haveGunCheck("drones") && !tech.isForeverDrones && !tech.isDroneRadioactive && !tech.isDroneTeleport) }, - requires: "shotgun, super balls, rivets, drones, not irradiated drones, burst drones, polyurethane", + requires: "shotgun, super balls, rivets, drones, not irradiated drones, burst drones, polyurethane, Zectron", effect() { tech.isIncendiary = true }, @@ -4706,6 +4706,25 @@ const tech = { } } }, + { + name: "Zectron", + description: `+100% super ball density and damage
after colliding with super balls lose health`, + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("super balls") && !tech.isIncendiary + }, + requires: "super balls not incendiary ammunition", + effect() { + tech.isSuperHarm = true + }, + remove() { + tech.isSuperHarm = false + } + }, { name: "super duper", description: `randomly fire +0, +1, or +2 extra super balls
 `, @@ -5016,7 +5035,7 @@ const tech = { }, { name: "launch system", - description: `+500% missile fire rate
+20% missile ammo per ${powerUps.orb.ammo(1)}`, + description: `+500% missile gun fire rate
+20% missile ammo per ${powerUps.orb.ammo(1)}`, isGunTech: true, maxCount: 1, count: 0, @@ -5607,6 +5626,25 @@ const tech = { tech.isSporeGrowth = false } }, + { + name: "cordyceps", + description: "mobs infected by sporangium
resurrect and attack other mobs", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("spores") + }, + requires: "spores", + effect() { + tech.isZombieMobs = true + }, + remove() { + tech.isZombieMobs = false + } + }, { name: "colony", description: "+50% sporangium discharge
40% chance to discharge something different", @@ -6314,28 +6352,18 @@ const tech = { ammoBonus: 9, effect() { tech.isRailGun = true; - for (i = 0, len = b.guns.length; i < len; i++) { //find which gun - if (b.guns[i].name === "harpoon") { - b.guns[i].chooseFireMethod() - b.guns[i].ammoPack = 5; - b.guns[i].ammo = b.guns[i].ammo * 6; - simulation.updateGunHUD(); - break - } - } + b.guns[9].chooseFireMethod() + b.guns[9].ammoPack = 5; + b.guns[9].ammo = b.guns[9].ammo * 6; + simulation.updateGunHUD(); }, remove() { if (tech.isRailGun) { tech.isRailGun = false; - for (i = 0, len = b.guns.length; i < len; i++) { //find which gun - if (b.guns[i].name === "harpoon") { - b.guns[i].chooseFireMethod() - b.guns[i].ammoPack = 1.7; - b.guns[i].ammo = Math.ceil(b.guns[i].ammo / 6); - simulation.updateGunHUD(); - break - } - } + b.guns[9].chooseFireMethod() + b.guns[9].ammoPack = 1.7; + b.guns[9].ammo = Math.ceil(b.guns[9].ammo / 6); + simulation.updateGunHUD(); } } }, @@ -9288,6 +9316,28 @@ const tech = { if (this.count) m.look = m.lookDefault } }, + { + name: "p-zombie", + description: "set your health to 1
all mobs die and resurrect as zombies", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() {return true}, + requires: "", + effect() { + m.health = 0.01 //set health to 1 + m.displayHealth(); + for (let i = mob.length - 1; i > -1; i--) { //replace mobs with zombies + if (mob[i].isDropPowerUp && !mob[i].isBoss && mob[i].alive) { + mob[i].isSoonZombie = true + mob[i].death() + } + } + }, + remove() {} + }, { name: "decomposers", description: "after they die mobs leave behind spawns
 ", @@ -11256,4 +11306,6 @@ const tech = { buffedGun: 0, isGunChoice: null, railChargeRate: null, + isSuperHarm: null, + isZombieMobs: null } \ No newline at end of file diff --git a/style.css b/style.css index f5b831f..6475be7 100644 --- a/style.css +++ b/style.css @@ -192,7 +192,7 @@ summary { .choose-grid-module { /* padding: 5px; */ - line-height: 170%; + line-height: 160%; /* border-radius: 8px; */ background-color: #fafcfd; font-size: 0.75em; @@ -259,13 +259,13 @@ summary { .pause-grid-module { /* margin: -1px; padding: 10px; - line-height: 170%; + line-height: 160%; border: 1px #333 solid; border-radius: 8px; background-color: #fff; font-size: 0.65em; */ padding: 5px; - line-height: 170%; + line-height: 160%; /* border-radius: 8px; */ background-color: #fafcfd; font-size: 0.75em; @@ -308,7 +308,7 @@ summary { .experiment-grid-module { padding: 5px; - line-height: 170%; + line-height: 160%; /* border-radius: 8px; */ background-color: #fafcfd; font-size: 0.75em; @@ -331,8 +331,9 @@ summary { } .card-background { + /* width:288; */ height:340px; - width:288; + background-size: contain; background-repeat: no-repeat; display: flex; justify-content:flex-end; @@ -370,6 +371,53 @@ summary { } +/* media rules for smaller screens +4->3 at 1550 +*/ +@media (width < 0px) { + .experiment-grid-module { + line-height: 140%; + font-size: 0.65em; + } + .choose-grid-module{ + line-height: 140%; + font-size: 0.65em; + } + .pause-grid-module { + line-height: 140%; + font-size: 0.65em; + } + .card-background{ + height:270px; + } + #experiment-grid{ + grid-template-columns: repeat(auto-fit, 360px); + } + #choose-grid{ + grid-template-columns: repeat(auto-fit, 360px); + } + .pause-grid{ + grid-template-columns: repeat(auto-fit, 360px); + } +} + +/* default +.experiment-grid-module { + line-height: 160%; + font-size: 0.75em; +} +.card-background { + height:340px; +} +#experiment-grid{ + grid-template-columns: repeat(auto-fit, 384px); +} +*/ + + + + + /* .no-image-cards{ border: 1px solid #444; } */ @@ -581,7 +629,7 @@ summary { color: #222; text-align: right; opacity: 0.35; - line-height: 130%; + line-height: 120%; background-color: rgba(255, 255, 255, 0.4); user-select: none; pointer-events: none; @@ -811,7 +859,7 @@ summary { padding: 4px; border-radius: 4px; font-weight: 800; - line-height: 170%; + line-height: 160%; font-size: 1em; } @@ -851,98 +899,89 @@ summary { font-size: 90%; } -.circle { - width: 20px; - height: 20px; - border-radius: 50%; - display: inline-block; - margin-bottom: -2px; -} - .circle-grid { - width: 27px; - height: 27px; + width: 1.35em; + height: 1.35em; border-radius: 50%; display: inline-block; - margin-bottom: -7px; - /* opacity: 0; */ - /* transition: opacity 0.5s ease-in; */ + margin-bottom: -0.3em; } .research-circle { - width: 13px; - height: 13px; + width: 0.9em; + height: 0.9em; border-radius: 50%; display: inline-block; background-color: #f7b; - border: 0.5px #fff solid; + border: 0.065em #fff solid; opacity: 0.85; - margin-bottom: -2.5px; + margin-bottom: -0.1em; } .ammo-circle { - width: 11px; - height: 11px; + width: 0.75em; + height: 0.75em; border-radius: 50%; display: inline-block; background-color: #467; - border: 0.5px #fff solid; + border: 0.05em #fff solid; opacity: 0.95; margin-bottom: -1.5px; } .heal-circle { - width: 14px; - height: 14px; + width: 0.95em; + height: 0.95em; border-radius: 50%; display: inline-block; background-color: #0d9; - border: 0.5px #fff solid; + border: 0.05em #fff solid; opacity: 0.85; margin-bottom: -3px; } .heal-circle-energy { - width: 14px; - height: 14px; + width: 0.95em; + height: 0.95em; border-radius: 50%; display: inline-block; background-color: #ff0; - border: 0.5px #000 solid; + border: 0.05em #000 solid; opacity: 0.85; margin-bottom: -3px; } .coupling-circle { - width: 10px; - height: 10px; + width: 0.7em; + height: 0.7em; border-radius: 50%; display: inline-block; background-color: #0ae; - border: 0.5px #fff solid; + border: 0.05em #fff solid; margin-bottom: -0.5px; } + .boost-circle { - width: 10px; - height: 10px; + width: 0.7em; + height: 0.7em; border-radius: 50%; display: inline-block; background-color: #f03; - border: 0.5px #fff solid; + border: 0.05em #fff solid; opacity: 0.9; margin-bottom: -0.5px; } -.circle-grid-shadow { +/* .circle-grid-shadow { width: 43px; height: 43px; border-radius: 50%; display: inline-block; margin-bottom: -15px; -} +} */ -.circle-gun-tech { +/* .circle-gun-tech { box-shadow: 0 0 0 3px #025; -} +} */ .junk { background-color: hsl(254, 44%, 75%); diff --git a/todo.txt b/todo.txt index c0bc768..a9099a4 100644 --- a/todo.txt +++ b/todo.txt @@ -1,39 +1,43 @@ ******************************************************** NEXT PATCH ************************************************** +adjust card size based on window width for smaller screens + switched from px to em css units for many elements + some image updates single column power up choice for small screens or no image setting +tech Zectron - super ball can damage you, but they do more damage to mobs + superBall bullets are converted to run off generic b.superBall() + !!still needs testing for balance + +tech: cordyceps - sporangium infect mobs, making them fight for you + zombies might attack player if there are no mob targets + !!still needs testing for balance + +sneakers - after taking damage if sneakers are low on life they teleport to a random point on the player history and sneak attack again +sneakBoss - a large sneaker that can hide several times before it dies + +bug fixes + *********************************************************** TODO ***************************************************** -maybe harpoon should start with less ammo? - -tech: p-zombie - sporangium infect mobs, making them fight for you - zombies should attack player if there are no mob targets - name: cordyceps, zombie, p-zombie? - infected mobs get a status debuff. when they die they return as zombie mob type - zombie mobs run code similar to drones - they inherit color, sides, radius from host - -tech super balls - super ball can damage you, but it does more damage to mobs +tech - all mobs return as zombies? set media rules for smaller screens + should fit 4 tech per row on my laptop smaller card size set font to 0.8em set card width to 384*0.8 and set background images to fit -bug reactor boss + harpoon foam production seems to make too much foam - set mob health bar colors based on status effects? make mob damage immunity a mob status effect? physics notes: add link to double slit content https://www.youtube.com/watch?v=v_uBaBuarEM -seekers after taking damage if seekers are below 1/2 life they teleport to a random point on the player history and sneak attack again - make sure they don't teleport on top of the player -tech: railgun area damage effect, but for all harpoon mode +tech: rail gun area damage effect, but for all harpoon mode laser momentum pushed back on player? might just be annoying