diff --git a/.DS_Store b/.DS_Store index 75d098a..4e3bbc2 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/js/bullet.js b/js/bullet.js index 225f7fb..56bc584 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -329,7 +329,7 @@ const b = { if (Vector.magnitude(Vector.sub(where, player.position)) < radius) { const DRAIN = (tech.isExplosionHarm ? 0.5 : 0.25) * (tech.isRadioactiveResistance ? 0.25 : 1) // * (tech.isImmuneExplosion ? Math.min(1, Math.max(1 - m.energy * 0.7, 0)) : 1) - m.energy -= DRAIN + if (m.immuneCycle < m.cycle) m.energy -= DRAIN if (m.energy < 0) { m.energy = 0 m.damage(0.03 * (tech.isRadioactiveResistance ? 0.25 : 1)); @@ -1036,7 +1036,7 @@ const b = { if (Vector.magnitude(Vector.sub(player.position, this.position)) < this.damageRadius) { const DRAIN = tech.isRadioactiveResistance ? 0.0025 * 0.25 : 0.0025 if (m.energy > DRAIN) { - m.energy -= DRAIN + if (m.immuneCycle < m.cycle) m.energy -= DRAIN } else { m.energy = 0; m.damage(tech.isRadioactiveResistance ? 0.00016 * 0.25 : 0.00016) //0.00015 @@ -1861,7 +1861,7 @@ const b = { }, onEnd() { if (tech.isMutualism && this.isMutualismActive && !tech.isEnergyHealth) { - m.health += 0.005 + m.health += 0.005 + 0.005 * tech.isSporeWorm if (m.health > m.maxHealth) m.health = m.maxHealth; m.displayHealth(); } @@ -1919,7 +1919,7 @@ const b = { }); World.add(engine.world, bullet[bIndex]); //add bullet to world if (tech.isMutualism && m.health > 0.02) { - m.health -= 0.005 + m.health -= 0.005 - 0.005 * tech.isSporeWorm m.displayHealth(); bullet[bIndex].isMutualismActive = true } @@ -1957,7 +1957,7 @@ const b = { }, onEnd() { if (tech.isMutualism && this.isMutualismActive && !tech.isEnergyHealth) { - m.health += 0.005 + m.health += 0.005 + 0.005 * tech.isSporeWorm if (m.health > m.maxHealth) m.health = m.maxHealth; m.displayHealth(); } @@ -2040,7 +2040,7 @@ const b = { World.add(engine.world, bullet[bIndex]); //add bullet to world if (tech.isMutualism && m.health > 0.02) { - m.health -= 0.005 + m.health -= 0.005 - 0.005 * tech.isSporeWorm m.displayHealth(); bullet[bIndex].isMutualismActive = true } @@ -2048,17 +2048,18 @@ const b = { }, iceIX(speed = 0, dir = m.angle + Math.PI * 2 * Math.random(), where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }) { const me = bullet.length; - const THRUST = 0.004 + const THRUST = 0.0006 const RADIUS = 18 + const SCALE = 1 - 0.08 / tech.isBulletsLastLonger bullet[me] = Bodies.polygon(where.x, where.y, 3, RADIUS, { angle: dir - Math.PI, inertia: Infinity, friction: 0, - frictionAir: 0.10, - restitution: 0.3, - dmg: 0.42, //damage done in addition to the damage from momentum + frictionAir: 0.023, + restitution: 0.9, + dmg: 0.5, //damage done in addition to the damage from momentum lookFrequency: 14 + Math.floor(8 * Math.random()), - endCycle: simulation.cycle + 140 * tech.isBulletsLastLonger, + endCycle: simulation.cycle + 150 * tech.isBulletsLastLonger + Math.floor(25 * Math.random()), classType: "bullet", collisionFilter: { category: cat.bullet, @@ -2071,13 +2072,8 @@ const b = { mobs.statusSlow(who, 180) this.endCycle = simulation.cycle // if (tech.isHeavyWater) mobs.statusDoT(who, 0.15, 300) - if (m.immuneCycle < m.cycle && tech.iceEnergy && !who.shield && !who.isShielded && who.isDropPowerUp && who.alive && m.immuneCycle < m.cycle) { - setTimeout(function() { - if (!who.alive) { - m.energy += tech.iceEnergy * 0.8 - // m.addHealth(tech.iceEnergy * 0.04) - } - }, 10); + if (tech.iceEnergy && !who.shield && !who.isShielded && who.isDropPowerUp && who.alive && m.immuneCycle < m.cycle) { + setTimeout(() => { if (!who.alive) m.energy += tech.iceEnergy * 0.8 }, 10); } }, onEnd() {}, @@ -2085,8 +2081,7 @@ const b = { // this.force.y += this.mass * 0.0002; //find mob targets if (!(simulation.cycle % this.lookFrequency)) { - const scale = 1 - 0.08 / tech.isBulletsLastLonger //0.9 * tech.isBulletsLastLonger; - Matter.Body.scale(this, scale, scale); + Matter.Body.scale(this, SCALE, SCALE); this.lockedOn = null; let closeDist = Infinity; for (let i = 0, len = mob.length; i < len; ++i) { @@ -2380,7 +2375,7 @@ const b = { if (Vector.magnitude(Vector.sub(player.position, this.position)) < this.radioRadius) { const DRAIN = tech.isRadioactiveResistance ? 0.0023 * 0.25 : 0.0023 if (m.energy > DRAIN) { - m.energy -= DRAIN + if (m.immuneCycle < m.cycle) m.energy -= DRAIN } else { m.energy = 0; m.damage(tech.isRadioactiveResistance ? 0.00015 * 0.25 : 0.00015) //0.00015 @@ -2543,14 +2538,11 @@ const b = { // radius *= Math.sqrt(tech.bulletSize) const me = bullet.length; bullet[me] = Bodies.polygon(position.x, position.y, 20, radius, { - // angle: 0, density: 0.000001, // 0.001 is normal density inertia: Infinity, frictionAir: 0.003, - // friction: 0.2, - // restitution: 0.2, dmg: 0, //damage on impact - damage: (tech.isFastFoam ? 0.048 : 0.012) * (tech.isFoamTeleport ? 1.66 : 1), //damage done over time + damage: (tech.isFastFoam ? 0.044 : 0.011) * (tech.isFoamTeleport ? 1.66 : 1), //damage done over time scale: 1 - 0.006 / tech.isBulletsLastLonger * (tech.isFastFoam ? 1.6 : 1), classType: "bullet", collisionFilter: { @@ -2610,9 +2602,6 @@ const b = { this.radius *= this.scale; if (this.radius < 8) this.endCycle = 0; } - - - if (this.target && this.target.alive) { //if stuck to a target const rotate = Vector.rotate(this.targetRelativePosition, this.target.angle) //add in the mob's new angle to the relative position vector if (this.target.isVerticesChange) { @@ -2622,12 +2611,10 @@ const b = { } Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.9)) Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9); - // Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9) if (this.target.isShielded) { this.target.damage(b.dmgScale * this.damage, true); //shield damage bypass - //shrink if mob is shielded - const SCALE = 1 - 0.01 / tech.isBulletsLastLonger + const SCALE = 1 - 0.004 / tech.isBulletsLastLonger //shrink if mob is shielded Matter.Body.scale(this, SCALE, SCALE); this.radius *= SCALE; } else { @@ -2641,9 +2628,7 @@ const b = { let targets = [] for (let i = 0, len = mob.length; i < len; i++) { const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)); - if (dist < 1000000) { - targets.push(mob[i]) - } + if (dist < 1000000) targets.push(mob[i]) } const radius = Math.min(this.radius * 0.5, 10) const len = bullet.length < 100 ? 2 : 1 @@ -2682,7 +2667,6 @@ const b = { this.radius *= SCALE; } else { this.force.y += this.mass * tech.foamGravity; //gravity - if (tech.isFoamAttract) { for (let i = 0, len = mob.length; i < len; i++) { if (!mob[i].isBadTarget && Vector.magnitude(Vector.sub(mob[i].position, this.position)) < 375 && mob[i].alive && Matter.Query.ray(map, this.position, mob[i].position).length === 0) { @@ -2768,6 +2752,71 @@ const b = { }; bullet[me].do = function() {}; }, + needle(angle = m.angle) { + const me = bullet.length; + bullet[me] = Bodies.rectangle(m.pos.x + 40 * Math.cos(m.angle), m.pos.y + 40 * Math.sin(m.angle), 75, 0.75, b.fireAttributes(angle)); + bullet[me].collisionFilter.mask = tech.isNeedleShieldPierce ? cat.body : cat.body | cat.mobShield + Matter.Body.setDensity(bullet[me], 0.00001); //0.001 is normal + bullet[me].endCycle = simulation.cycle + 180; + bullet[me].immuneList = [] + bullet[me].do = function() { + const whom = Matter.Query.collides(this, mob) + if (whom.length && this.speed > 20) { //if touching a mob + for (let i = 0, len = whom.length; i < len; i++) { + who = whom[i].bodyA + if (who && who.mob) { + let immune = false + for (let i = 0; i < this.immuneList.length; i++) { //check if this needle has hit this mob already + if (this.immuneList[i] === who.id) { + immune = true + break + } + } + if (!immune) { + if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.975) { + b.explosion(this.position, 220 + 50 * Math.random()); //makes bullet do explosive damage at end + } + this.immuneList.push(who.id) //remember that this needle has hit this mob once already + who.foundPlayer(); + if (tech.isNailRadiation) { + mobs.statusDoT(who, tech.isFastRadiation ? 12 : 3, tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles + } else { + let dmg = b.dmgScale * 5.5 + if (tech.isCrit && who.isStunned) dmg *= 4 + who.damage(dmg, tech.isNeedleShieldPierce); + simulation.drawList.push({ //add dmg to draw queue + x: this.position.x, + y: this.position.y, + radius: Math.log(2 * dmg + 1.1) * 40, + color: simulation.playerDmgColor, + time: simulation.drawTime + }); + } + } + } + } + } else if (Matter.Query.collides(this, map).length) { //stick in walls + this.collisionFilter.mask = 0; + Matter.Body.setAngularVelocity(this, 0) + Matter.Body.setVelocity(this, { + x: 0, + y: 0 + }); + this.do = function() { + if (!Matter.Query.collides(this, map).length) this.force.y += this.mass * 0.001; + } + } else if (this.speed < 30) { + this.force.y += this.mass * 0.001; //no gravity until it slows down to improve aiming + } + }; + const SPEED = 90 + Matter.Body.setVelocity(bullet[me], { + x: m.Vx / 2 + SPEED * Math.cos(angle), + y: m.Vy / 2 + SPEED * Math.sin(angle) + }); + // Matter.Body.setDensity(bullet[me], 0.00001); + World.add(engine.world, bullet[me]); //add bullet to world + }, // ************************************************************************************************** // ************************************************************************************************** // ******************************** Bots ********************************************* @@ -3629,91 +3678,19 @@ const b = { this.baseFire(m.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (m.crouch ? 1.35 : 3.2) / CD) }, fireNeedles() { - function makeNeedle(angle = m.angle) { - const me = bullet.length; - bullet[me] = Bodies.rectangle(m.pos.x + 40 * Math.cos(m.angle), m.pos.y + 40 * Math.sin(m.angle), 75, 0.75, b.fireAttributes(angle)); - bullet[me].collisionFilter.mask = tech.isNeedleShieldPierce ? cat.body : cat.body | cat.mobShield - Matter.Body.setDensity(bullet[me], 0.00001); //0.001 is normal - bullet[me].endCycle = simulation.cycle + 180; - bullet[me].immuneList = [] - bullet[me].do = function() { - const whom = Matter.Query.collides(this, mob) - if (whom.length && this.speed > 20) { //if touching a mob - for (let i = 0, len = whom.length; i < len; i++) { - who = whom[i].bodyA - if (who && who.mob) { - let immune = false - for (let i = 0; i < this.immuneList.length; i++) { //check if this needle has hit this mob already - if (this.immuneList[i] === who.id) { - immune = true - break - } - } - if (!immune) { - if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.975) { - b.explosion(this.position, 220 + 50 * Math.random()); //makes bullet do explosive damage at end - } - this.immuneList.push(who.id) //remember that this needle has hit this mob once already - who.foundPlayer(); - if (tech.isNailRadiation) { - mobs.statusDoT(who, tech.isFastRadiation ? 12 : 3, tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles - } else { - let dmg = b.dmgScale * 5.5 - if (tech.isCrit && who.isStunned) dmg *= 4 - who.damage(dmg, tech.isNeedleShieldPierce); - simulation.drawList.push({ //add dmg to draw queue - x: this.position.x, - y: this.position.y, - radius: Math.log(2 * dmg + 1.1) * 40, - color: simulation.playerDmgColor, - time: simulation.drawTime - }); - } - } - } - } - } else if (Matter.Query.collides(this, map).length) { //stick in walls - this.collisionFilter.mask = 0; - Matter.Body.setAngularVelocity(this, 0) - Matter.Body.setVelocity(this, { - x: 0, - y: 0 - }); - this.do = function() { - if (!Matter.Query.collides(this, map).length) this.force.y += this.mass * 0.001; - } - } else if (this.speed < 30) { - this.force.y += this.mass * 0.001; //no gravity until it slows down to improve aiming - } - }; - const SPEED = 90 - Matter.Body.setVelocity(bullet[me], { - x: m.Vx / 2 + SPEED * Math.cos(angle), - y: m.Vy / 2 + SPEED * Math.sin(angle) - }); - // Matter.Body.setDensity(bullet[me], 0.00001); - World.add(engine.world, bullet[me]); //add bullet to world - } - if (m.crouch) { m.fireCDcycle = m.cycle + 45 * b.fireCDscale; // cool down - makeNeedle() + b.needle() for (let i = 1; i < 4; i++) { //4 total needles - setTimeout(() => { if (!simulation.paused) makeNeedle() }, 60 * i); + setTimeout(() => { if (!simulation.paused) b.needle() }, 60 * i); } } else { m.fireCDcycle = m.cycle + 25 * b.fireCDscale; // cool down - makeNeedle() + b.needle() for (let i = 1; i < 3; i++) { //3 total needles - setTimeout(() => { if (!simulation.paused) makeNeedle() }, 60 * i); + setTimeout(() => { if (!simulation.paused) b.needle() }, 60 * i); } } - - - // const spread = (m.crouch ? 0.013 : 0.06) - // makeNeedle(m.angle + spread) - // makeNeedle() - // makeNeedle(m.angle - spread) }, fireRivets() { m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 25 : 17) * b.fireCDscale); // cool down @@ -3806,11 +3783,11 @@ const b = { let knock, spread if (m.crouch) { spread = 0.65 - m.fireCDcycle = m.cycle + Math.floor(55 * b.fireCDscale); // cool down + m.fireCDcycle = m.cycle + Math.floor(55 * b.fireCDscale) // cool down if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(58 * b.fireCDscale)) m.immuneCycle = m.cycle + Math.floor(58 * b.fireCDscale); //player is immune to damage for 30 cycles knock = 0.01 } else { - m.fireCDcycle = m.cycle + Math.floor(45 * b.fireCDscale); // cool down + m.fireCDcycle = m.cycle + Math.floor(45 * b.fireCDscale) // cool down if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(47 * b.fireCDscale)) m.immuneCycle = m.cycle + Math.floor(47 * b.fireCDscale); //player is immune to damage for 30 cycles spread = 1.3 knock = 0.1 @@ -3900,7 +3877,7 @@ const b = { y: speed * Math.sin(dirOff) }); bullet[me].onEnd = function() { - b.explosion(this.position, 150 * (tech.isShotgunReversed ? 1.6 : 1) + (Math.random() - 0.5) * 40); //makes bullet do explosive damage at end + b.explosion(this.position, 160 * (tech.isShotgunReversed ? 1.6 : 1) + (Math.random() - 0.5) * 40); //makes bullet do explosive damage at end } bullet[me].beforeDmg = function() { this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion @@ -3910,7 +3887,7 @@ const b = { } } else if (tech.isNailShot) { spread *= 0.65 - const dmg = 1.4 * (tech.isShotgunReversed ? 1.6 : 1) + const dmg = 2 * (tech.isShotgunReversed ? 1.6 : 1) if (m.crouch) { for (let i = 0; i < 17; i++) { speed = 38 + 15 * Math.random() @@ -3938,6 +3915,49 @@ const b = { }, dmg) } } + } else if (tech.isWormShot) { + const unit = { + x: Math.cos(m.angle), + y: Math.sin(m.angle) + } + const where = { + x: m.pos.x + 35 * unit.x, + y: m.pos.y + 35 * unit.y + } + for (let i = 0, len = 3 * (tech.isShotgunReversed ? 1.6 : 1) + Math.random(); i < len; i++) { + b.worm(where) + const SPEED = 14 + 6 * Math.random() + 20 * m.crouch; + Matter.Body.setVelocity(bullet[bullet.length - 1], { + x: SPEED * unit.x, + y: SPEED * unit.y + }); + } + } else if (tech.isIceShot) { + const spread = (m.crouch ? 0.6 : 1.6) + for (let i = 0, len = 16 * (tech.isShotgunReversed ? 1.6 : 1); i < len; i++) { + // iceIX(speed = 0, dir = m.angle + Math.PI * 2 * Math.random(), where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }) { + b.iceIX(14 + 30 * Math.random(), m.angle + spread * (Math.random() - 0.5)) + } + } else if (tech.isFoamShot) { + const spread = (m.crouch ? 0.35 : 0.7) + const where = { + x: m.pos.x + 25 * Math.cos(m.angle), + y: m.pos.y + 25 * Math.sin(m.angle) + } + const number = 14 * (tech.isShotgunReversed ? 1.6 : 1) + for (let i = 0; i < number; i++) { + const SPEED = 25 + 12 * Math.random(); + const angle = m.angle + spread * (Math.random() - 0.5) + b.foam(where, { x: SPEED * Math.cos(angle), y: SPEED * Math.sin(angle) }, 5 + 8 * Math.random()) + } + } else if (tech.isNeedleShot) { + const number = 12 * (tech.isShotgunReversed ? 1.6 : 1) + const spread = (m.crouch ? 0.04 : 0.08) + let angle = m.angle - (number - 1) * spread * 0.5 + for (let i = 0; i < number; i++) { + b.needle(angle) + angle += spread + } } else { const side = 22 for (let i = 0; i < 17; i++) { @@ -4843,7 +4863,7 @@ const b = { if (tech.isCapacitor) { if ((m.energy > 0.16 || tech.isRailEnergyGain)) { //&& m.immuneCycle < m.cycle - if (m.immuneCycle < m.cycle) m.energy += 0.16 * (tech.isRailEnergyGain ? 6 : -1) + m.energy += 0.16 * (tech.isRailEnergyGain ? 4.5 : -1) m.fireCDcycle = m.cycle + Math.floor(30 * b.fireCDscale); const me = bullet.length; bullet[me] = Bodies.rectangle(m.pos.x + 50 * Math.cos(m.angle), m.pos.y + 50 * Math.sin(m.angle), 60, 14, { @@ -4970,7 +4990,7 @@ const b = { bullet[me].charge = 0; bullet[me].do = function() { if (m.energy < 0.005 && !tech.isRailEnergyGain) { - if (m.immuneCycle < m.cycle) m.energy += 0.05 + this.charge * 0.3 + m.energy += 0.05 + this.charge * 0.2 m.fireCDcycle = m.cycle + 120; // cool down if out of energy this.endCycle = 0; return @@ -5019,7 +5039,7 @@ const b = { let smoothRate = 0.98 * (m.crouch ? 0.99 : 1) * (0.98 + 0.02 * b.fireCDscale) //small b.fireCDscale = faster shots, b.fireCDscale=1 = normal shot, big b.fireCDscale = slower chot this.charge = this.charge * smoothRate + 1 * (1 - smoothRate) if (tech.isRailEnergyGain) { - if (m.immuneCycle < m.cycle) m.energy += (this.charge - previousCharge) * 2 //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen + m.energy += (this.charge - previousCharge) * 1.5 //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen } else { m.energy -= (this.charge - previousCharge) * 0.33 //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen } diff --git a/js/level.js b/js/level.js index 7c7aaf2..0e63a6a 100644 --- a/js/level.js +++ b/js/level.js @@ -12,10 +12,15 @@ 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(60) //30 is near max on hard //60 is near max on why + // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why // simulation.isHorizontalFlipped = true // m.setField("wormhole") - // b.giveGuns("spores") + // b.giveGuns("shotgun") + // b.giveGuns("foam") + // tech.isNeedleShot = true + // tech.isIceShot = true + // tech.isFoamShot = true + // tech.isWormShot = true // tech.giveTech("CPT reversal") // tech.giveTech("causality bombs") // b.giveGuns("wave beam") @@ -966,12 +971,14 @@ const level = { ctx.fillRect(this.min.x, this.min.y + offset, this.width, this.height - offset) if (this.height > 0 && Matter.Query.region([player], this).length) { - const DRAIN = 0.002 * (tech.isRadioactiveResistance ? 0.25 : 1) + m.fieldRegen - if (m.energy > DRAIN) { - m.energy -= DRAIN - m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1) * 0.03) //still take 2% damage while you have energy - } else { - m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1)) + if (m.immuneCycle < m.cycle) { + const DRAIN = 0.002 * (tech.isRadioactiveResistance ? 0.25 : 1) + m.fieldRegen + if (m.energy > DRAIN) { + m.energy -= DRAIN + m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1) * 0.03) //still take 2% damage while you have energy + } else { + m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1)) + } } //float if (player.velocity.y > 5) player.force.y -= 0.95 * player.mass * simulation.g @@ -1621,8 +1628,10 @@ const level = { ctx.lineWidth = 2; if (Vector.magnitudeSquared(Vector.sub(m.pos, powerUp1.position)) < 90000) { //zone radius is 300 //damage player and drain energy - if (m.immuneCycle < m.cycle) m.damage(0.01); - if (m.energy > 0.1) m.energy -= 0.02 + if (m.immuneCycle < m.cycle) { + m.damage(0.01); + if (m.energy > 0.1) m.energy -= 0.02 + } //draw electricity going towards player const unit = Vector.normalise(Vector.sub(m.pos, powerUp1.position)) let xElec = powerUp1.position.x + 40 * unit.x; @@ -2256,10 +2265,10 @@ const level = { spawn.mapRect(6700, -1800, 800, 2600); //right wall spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump - // spawn.starter(1900, -500, 200) //big boy - spawn.growBossCulture(1900, -500) + spawn.starter(1900, -500, 200) //big boy + // spawn.growBossCulture(1900, -500) - // spawn.pulsarBoss(1900, -500) + // spawn.snakeBoss(1900, -500) // spawn.shieldingBoss(1900, -500) // spawn.grenadierBoss(1900, -500) diff --git a/js/mob.js b/js/mob.js index 6b1dd09..9fd8d6c 100644 --- a/js/mob.js +++ b/js/mob.js @@ -417,8 +417,10 @@ const mobs = { ctx.setLineDash([125 * Math.random(), 125 * Math.random()]); // ctx.lineDashOffset = 6*(simulation.cycle % 215); if (this.distanceToPlayer() < this.laserRange) { - if (m.immuneCycle < m.cycle) m.damage(0.0003 * simulation.dmgScale); - if (m.energy > 0.1) m.energy -= 0.003 + if (m.immuneCycle < m.cycle) { + m.damage(0.0003 * simulation.dmgScale); + if (m.energy > 0.1) m.energy -= 0.003 + } ctx.beginPath(); ctx.moveTo(this.position.x, this.position.y); ctx.lineTo(m.pos.x, m.pos.y); diff --git a/js/player.js b/js/player.js index 635b536..b4fdae7 100644 --- a/js/player.js +++ b/js/player.js @@ -635,7 +635,7 @@ const m = { } if (tech.isEnergyHealth) { - m.energy -= dmg * 1.15; + m.energy -= dmg * 1.1; if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage if (tech.isDeathAvoid && powerUps.research.count && !tech.isDeathAvoidedThisLevel) { tech.isDeathAvoidedThisLevel = true @@ -2443,7 +2443,9 @@ const m = { const unit = Vector.mult(Vector.normalise(sub), body[i].mass * tech.pilotForce * Vector.magnitude(sub)) body[i].force.x += unit.x body[i].force.y += unit.y - body[i].mass * simulation.g //remove gravity effects - if (body[i].collisionFilter.category !== cat.bullet) body[i].collisionFilter.category = cat.bullet; + // if (body[i].collisionFilter.category !== cat.bullet) { + // body[i].collisionFilter.category = cat.bullet; + // } } else { m.fieldCDcycle = m.cycle + 120; m.fieldOn = false @@ -2602,7 +2604,7 @@ const m = { Matter.World.remove(engine.world, body[i]); body.splice(i, 1); m.fieldRange *= 0.8 - if (tech.isWormholeEnergy && m.immuneCycle < m.cycle) m.energy += 0.63 + if (tech.isWormholeEnergy) m.energy += 0.63 if (tech.isWormSpores) { //pandimensionalspermia for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) { if (tech.isSporeWorm) { diff --git a/js/powerup.js b/js/powerup.js index 650b303..7dd5e6f 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -676,7 +676,7 @@ const powerUps = { onPickUp(who) { powerUps.research.currentRerollCount = 0 if (tech.isTechDamage && who.name === "tech") m.damage(0.11) - if (tech.isMassEnergy && m.immuneCycle < m.cycle) m.energy += 2; + if (tech.isMassEnergy) m.energy += 2; if (tech.isMineDrop) { if (tech.isLaserMine) { b.laserMine(who.position) diff --git a/js/simulation.js b/js/simulation.js index 33681f5..3cc9f70 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -696,7 +696,7 @@ const simulation = { if (tech.isMutualism && !tech.isEnergyHealth) { for (let i = 0; i < bullet.length; i++) { if (bullet[i].isMutualismActive) { - m.health += 0.005 + m.health += 0.005 + 0.005 * tech.isSporeWorm if (m.health > m.maxHealth) m.health = m.maxHealth; m.displayHealth(); } diff --git a/js/spawn.js b/js/spawn.js index 74ff1df..a984af9 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -188,7 +188,7 @@ const spawn = { if (m.immuneCycle < m.cycle && Vector.magnitude(Vector.sub(player.position, this.position)) < this.radius) { const DRAIN = tech.isRadioactiveResistance ? 0.07 * 0.25 : 0.07 if (m.energy > DRAIN) { - m.energy -= DRAIN + if (m.immuneCycle < m.cycle) m.energy -= DRAIN } else { m.energy = 0; m.damage((tech.isRadioactiveResistance ? 0.007 * 0.25 : 0.007) * simulation.dmgScale) @@ -504,9 +504,9 @@ const spawn = { ctx.fill(); //when player is inside event horizon if (Vector.magnitude(Vector.sub(this.position, player.position)) < eventHorizon) { - if (m.energy > 0) m.energy -= 0.01 - if (m.energy < 0.15 && m.immuneCycle < m.cycle) { - m.damage(0.0004 * simulation.dmgScale); + if (m.immuneCycle < m.cycle) { + if (m.energy > 0) m.energy -= 0.01 + if (m.energy < 0.15 && m.immuneCycle < m.cycle) m.damage(0.0004 * simulation.dmgScale); } const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x); player.force.x -= 0.0017 * Math.cos(angle) * player.mass * (m.onGround ? 1.7 : 1); @@ -704,7 +704,7 @@ const spawn = { let me = mob[mob.length - 1]; // console.log(`mass=${me.mass}, radius = ${radius}`) me.accelMag = 0.0002 - me.repulsionRange = 100000; //squared + me.repulsionRange = 100000 + radius * radius; //squared // me.memory = 120; me.seeAtDistance2 = 2000000 //1400 vision range Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback @@ -1338,9 +1338,9 @@ const spawn = { //when player is inside event horizon if (Vector.magnitude(Vector.sub(this.position, player.position)) < eventHorizon) { - if (m.energy > 0) m.energy -= 0.004 - if (m.energy < 0.1 && m.immuneCycle < m.cycle) { - m.damage(0.00015 * simulation.dmgScale); + if (m.immuneCycle < m.cycle) { + if (m.energy > 0) m.energy -= 0.004 + if (m.energy < 0.1) m.damage(0.00015 * simulation.dmgScale); } const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x); player.force.x -= 0.00125 * player.mass * Math.cos(angle) * (m.onGround ? 1.8 : 1); @@ -1447,9 +1447,9 @@ const spawn = { ctx.fill(); //when player is inside event horizon if (Vector.magnitude(Vector.sub(this.position, player.position)) < eventHorizon) { - if (m.energy > 0) m.energy -= 0.006 - if (m.energy < 0.1 && m.immuneCycle < m.cycle) { - m.damage(0.0002 * simulation.dmgScale); + if (m.immuneCycle < m.cycle) { + if (m.energy > 0) m.energy -= 0.006 + if (m.energy < 0.1) m.damage(0.0002 * simulation.dmgScale); } const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x); player.force.x -= 0.0013 * Math.cos(angle) * player.mass * (m.onGround ? 1.7 : 1); @@ -1703,10 +1703,12 @@ const spawn = { ctx.setLineDash([125 * Math.random(), 125 * Math.random()]); //the dashed effect is not set back to normal, because it looks neat for how the player is drawn // ctx.lineDashOffset = 6*(simulation.cycle % 215); if (this.distanceToPlayer() < this.laserRange) { - if (m.energy > 0.002) { - m.energy -= 0.0035 - } else if (m.immuneCycle < m.cycle) { - m.damage(0.0003 * simulation.dmgScale) + if (m.immuneCycle < m.cycle) { + if (m.energy > 0.002) { + m.energy -= 0.0035 + } else { + m.damage(0.0003 * simulation.dmgScale) + } } ctx.beginPath(); ctx.moveTo(eye.x, eye.y); @@ -3551,7 +3553,8 @@ const spawn = { }; }, snakeBoss(x, y, radius = 75) { //snake boss with a laser head - mobs.spawn(x, y, 8, radius, "rgb(55,170,170)"); + const color1 = "#f27" + mobs.spawn(x, y, 8, radius, color1); //"rgb(55,170,170)" let me = mob[mob.length - 1]; me.isBoss = true; me.damageReduction = 0.25; @@ -3579,6 +3582,14 @@ const spawn = { //snake tail const nodes = Math.min(8 + Math.ceil(0.5 * simulation.difficulty), 40) spawn.lineGroup(x + 105, y, "snakeBody", nodes); + + 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 + } + } //constraint with first 3 mobs in line consBB[consBB.length] = Constraint.create({ bodyA: mob[mob.length - nodes], @@ -3598,7 +3609,7 @@ const spawn = { stiffness: 0.05 }); World.add(engine.world, consBB[consBB.length - 1]); - spawn.shield(me, x, y, 1); + // spawn.shield(me, x, y, 1); }, snakeBody(x, y, radius = 10) { mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)"); @@ -3610,6 +3621,8 @@ const spawn = { me.collisionFilter.mask = cat.bullet | cat.player | cat.mob //| cat.body me.accelMag = 0.0004 * simulation.accelScale; me.leaveBody = false; + me.showHealthBar = false; + // Matter.Body.setDensity(me, 0.00004); //normal is 0.001 me.frictionAir = 0.02; me.isSnakeTail = true; me.stroke = "transparent" diff --git a/js/tech.js b/js/tech.js index a01f7ff..af3b062 100644 --- a/js/tech.js +++ b/js/tech.js @@ -682,7 +682,7 @@ frequency: 2, frequencyDefault: 2, allowed() { - return m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" || tech.haveGunCheck("spores") || tech.haveGunCheck("drones") || tech.haveGunCheck("missiles") || tech.haveGunCheck("foam") || tech.haveGunCheck("wave beam") || tech.isNeutronBomb || tech.isIceField || tech.relayIce || tech.blockingIce > 1 + return m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" || tech.haveGunCheck("spores") || tech.haveGunCheck("drones") || tech.haveGunCheck("missiles") || tech.haveGunCheck("foam") || tech.haveGunCheck("wave beam") || tech.isNeutronBomb || tech.isIceField || tech.isIceShot || tech.relayIce || tech.blockingIce > 1 }, requires: "drones, spores, missiles, foam, wave beam, neutron bomb, ice IX", effect() { @@ -865,9 +865,9 @@ frequency: 1, frequencyDefault: 1, allowed() { - return ((m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isDroneRadioactive) || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot + return ((m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isDroneRadioactive) || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot }, - requires: "super balls, shotgun, drones, not irradiated drones", + requires: "super balls, basic or slug shotgun, drones, not irradiated drones", effect() { tech.isIncendiary = true }, @@ -1812,7 +1812,7 @@ frequency: 2, frequencyDefault: 2, allowed() { - return (tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField || tech.relayIce || tech.blockingIce > 1) && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.nailsDeathMob + return (tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField || tech.isIceShot || tech.relayIce || tech.blockingIce > 1) && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.nailsDeathMob }, requires: "a localized freeze effect, no other mob death tech", effect() { @@ -1830,7 +1830,7 @@ frequency: 2, frequencyDefault: 2, allowed() { - return tech.isIceField || tech.relayIce || tech.blockingIce || tech.iceIXOnDeath + return tech.isIceField || tech.relayIce || tech.blockingIce || tech.iceIXOnDeath || tech.isIceShot }, requires: "ice IX", effect() { @@ -1848,7 +1848,7 @@ frequency: 2, frequencyDefault: 2, allowed() { - return tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField || tech.relayIce || tech.blockingIce > 1 || tech.iceIXOnDeath + return tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField || tech.relayIce || tech.blockingIce > 1 || tech.iceIXOnDeath || tech.isIceShot }, requires: "a localized freeze effect", effect() { @@ -1866,7 +1866,7 @@ frequency: 2, frequencyDefault: 2, allowed() { - return tech.isStunField || tech.isExplosionStun || tech.oneSuperBall || tech.isHarmFreeze || tech.isIceField || tech.relayIce || tech.isIceCrystals || tech.isSporeFreeze || tech.isAoESlow || tech.isFreezeMobs || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isWormholeDamage || tech.blockingIce > 1 || tech.iceIXOnDeath + return tech.isStunField || tech.isExplosionStun || tech.oneSuperBall || tech.isHarmFreeze || tech.isIceField || tech.relayIce || tech.isIceCrystals || tech.isSporeFreeze || tech.isAoESlow || tech.isFreezeMobs || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isWormholeDamage || tech.blockingIce > 1 || tech.iceIXOnDeath || tech.isIceShot }, requires: "a freezing or stunning effect", effect() { @@ -3461,9 +3461,9 @@ frequency: 2, frequencyDefault: 2, allowed() { - return tech.isNeedles && !tech.isNailRadiation + return (tech.isNeedles || tech.isNeedleShot) && !tech.isNailRadiation }, - requires: "needle gun, not irradiated nails", + requires: "needle gun, needle-shot, not irradiated nails", effect() { tech.isNeedleShieldPierce = true }, @@ -3729,44 +3729,6 @@ } } }, - { - name: "nailshot", - description: "the shotgun fires a burst of nails", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isSlugShot - }, - requires: "shotgun, not slug, incendiary", - effect() { - tech.isNailShot = true; - }, - remove() { - tech.isNailShot = false; - } - }, - { - name: "shotgun slug", - description: "the shotgun fires 1 large bullet", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.haveGunCheck("shotgun") && !tech.isNailShot - }, - requires: "shotgun, not nailshot", - effect() { - tech.isSlugShot = true; - }, - remove() { - tech.isSlugShot = false; - } - }, { name: "Newton's 3rd law", description: "shotgun recoil is increased
decrease shotgun delay after firing by 66%", @@ -3805,6 +3767,120 @@ tech.isShotgunReversed = false; } }, + { + name: "shotgun slug", + description: "the shotgun fires a huge dense bullet", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot + }, + requires: "shotgun, not nail-shot, foam-shot, worm-shot, ice-shot", + effect() { + tech.isSlugShot = true; + }, + remove() { + tech.isSlugShot = false; + } + }, + { + name: "nail-shot", + description: "the shotgun fires a burst of nails", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isSlugShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot + }, + requires: "shotgun, not incendiary, slug, foam-shot, worm-shot, ice-shot", + effect() { + tech.isNailShot = true; + }, + remove() { + tech.isNailShot = false; + } + }, + { + name: "worm-shot", + description: "the shotgun fires 3-4 worms", //
worms seek out nearby mobs + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isSlugShot && !tech.isIceShot && !tech.isFoamShot && !tech.isNeedleShot + }, + requires: "shotgun, not incendiary, nail-shot, slug, foam-shot, ice-shot", + effect() { + tech.isWormShot = true; + }, + remove() { + tech.isWormShot = false; + } + }, + { + name: "foam-shot", + description: "the shotgun fires 14 foam bubbles", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isSlugShot && !tech.isIceShot && !tech.isWormShot && !tech.isNeedleShot + }, + requires: "shotgun, not incendiary, nail-shot, slug, worm-shot, ice-shot", + effect() { + tech.isFoamShot = true; + }, + remove() { + tech.isFoamShot = false; + } + }, + { + name: "ice-shot", + description: "the shotgun fires 16 ice IX crystals", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isSlugShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot + }, + requires: "shotgun, not incendiary, nail-shot, slug, foam-shot, worm-shot", + effect() { + tech.isIceShot = true; + }, + remove() { + tech.isIceShot = false; + } + }, + { + name: "needle-shot", + description: "the shotgun fires 12 mob piercing needles", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isSlugShot && !tech.isFoamShot && !tech.isWormShot && !tech.isIceShot + }, + requires: "shotgun, not incendiary, nail-shot, slug, foam-shot, worm-shot, ice-shot", + effect() { + tech.isNeedleShot = true; + }, + remove() { + tech.isNeedleShot = false; + } + }, { name: "super duper", description: "fire 1 additional super ball", @@ -4318,9 +4394,9 @@ frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField + return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isWormShot }, - requires: "spores", + requires: "spores or worms", effect() { tech.isSporeFreeze = true }, @@ -4337,9 +4413,9 @@ frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField + return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isWormShot }, - requires: "spores", + requires: "spores or worms", effect() { tech.isSporeFollow = true }, @@ -4347,6 +4423,25 @@ tech.isSporeFollow = false } }, + { + name: "mutualism", + description: "increase spore damage by 150%
spores borrow 0.5 health until they die", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return (tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField) && !tech.isEnergyHealth || tech.isWormShot + }, + requires: "spores, worms, not mass-energy", + effect() { + tech.isMutualism = true + }, + remove() { + tech.isMutualism = false + } + }, { name: "nematodes", description: "spores develop into 1/2 as many worms
worms do 200% more damage", @@ -4366,25 +4461,6 @@ tech.isSporeWorm = false } }, - { - name: "mutualism", - description: "increase spore damage by 150%
spores borrow 0.5 health until they die", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return (tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField) && !tech.isEnergyHealth - }, - requires: "spores, not mass-energy", - effect() { - tech.isMutualism = true - }, - remove() { - tech.isMutualism = false - } - }, { name: "reduced tolerances", description: "increase drone ammo/efficiency by 66%
reduce the average drone lifetime by 40%", @@ -4543,6 +4619,25 @@ tech.droneRadioDamage = 1 } }, + { + name: "electrostatic induction", + description: "foam bubbles are electrically charged
causing attraction to nearby mobs", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return !tech.isFoamTeleport && (tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot) + }, + requires: "foam, not uncertainty", + effect() { + tech.isFoamAttract = true + }, + remove() { + tech.isFoamAttract = false + } + }, { name: "uncertainty principle", description: "foam bubbles randomly change position
increase foam damage per second by 66%", @@ -4552,7 +4647,7 @@ frequency: 2, frequencyDefault: 2, allowed() { - return !tech.isFoamAttract && (tech.haveGunCheck("foam") || tech.foamBotCount > 1) + return !tech.isFoamAttract && (tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot) }, requires: "foam, not electrostatic induction", effect() { @@ -4571,7 +4666,7 @@ frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("foam") || tech.foamBotCount > 1 + return tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot }, requires: "foam", effect() { @@ -4590,7 +4685,7 @@ frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("foam") || tech.foamBotCount > 1 + return tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot }, requires: "foam", effect() { @@ -4640,25 +4735,6 @@ tech.isAmmoFoamSize = false; } }, - { - name: "electrostatic induction", - description: "foam bubbles are electrically charged
causing attraction to nearby mobs", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return !tech.isFoamTeleport && (tech.haveGunCheck("foam") || tech.foamBotCount > 1) - }, - requires: "foam, not uncertainty", - effect() { - tech.isFoamAttract = true - }, - remove() { - tech.isFoamAttract = false - } - }, { name: "half-wave rectifier", description: "charging the rail gun gives you energy
instead of draining it", @@ -7553,6 +7629,10 @@ isFieldHarmReduction: null, isFastTime: null, isDroneTeleport: null, + isAnthropicTech: null, isSporeWorm: null, - isAnthropicTech: null + isWormShot: null, + isFoamShot: null, + isIceShot: null, + isNeedleShot: null } \ No newline at end of file diff --git a/todo.txt b/todo.txt index 27fb786..b70fc8b 100644 --- a/todo.txt +++ b/todo.txt @@ -1,25 +1,31 @@ ******************************************************** NEXT PATCH ******************************************************** -tech: weak anthropic principle - after anthropic principle prevents your death, gain 50% duplication for that level -anthropic principle now correctly gives 6 seconds of harm immunity after preventing your death -almost all energy regen is disabled while immune to harm - you aren't immune very often so you may not notice, but it will limit some builds that let you get almost constant immunity - Pauli exclusion gives 1 s of harm immunity (was .75 s) - CPT reversal requires 10% less energy (min energy is 60% to activate) - CPT grenades gives many more bombs - CPT bots gives many more bots +shotgun techs: + (I haven't done enough testing so let me know if these different shotgun modes aren't balanced) + worm shot + ice-IX shot + foam shot + needle shot -growBoss balance: a bit smaller and slower, and a extra high chance to drop a random power up when you kill one -sneaker mobs are a bit slower, and have much lower health -starter mobs are no longer aggressive +foam lasts much longer on shielded mobs + overall foam damage is reduced about 8% -gun tech will now only show up for your active gun -set CSS max width of the update element to match other elements +attacks that drain energy don't work when the player is immune to harm + slime, radiation fields, black holes +energy regen that consumes something (ammo, blocks, power ups) now works when immune to harm + but passive energy regen is still stopped while you are immune to harm + +pilot wave field can no longer hit intangible mobs with blocks + it was too annoying that you can't use blocks to move around so I reverted it back ******************************************************** TODO ******************************************************** +snake boss tail should shrink in size -CPT reversal should drain less energy? +mob that grows or gets a shield when player is near + and charges when player is near + charge triggers an escape mode + mob wonders and drops eggs that hatch into seekers if no player around pink seeker boss is cool as heck, make an alt version of it