diff --git a/favicon.ico b/favicon.ico index f816713..ce083ff 100644 Binary files a/favicon.ico and b/favicon.ico differ diff --git a/img/acetone peroxide.webp b/img/acetone peroxide.webp index 8889d4b..71847e6 100644 Binary files a/img/acetone peroxide.webp and b/img/acetone peroxide.webp differ diff --git a/img/ammonium nitrate.webp b/img/ammonium nitrate.webp index 7b430f4..77f2c09 100644 Binary files a/img/ammonium nitrate.webp and b/img/ammonium nitrate.webp differ diff --git a/img/chain reaction.webp b/img/chain reaction.webp index cea1259..d2a5448 100644 Binary files a/img/chain reaction.webp and b/img/chain reaction.webp differ diff --git a/img/flame test.webp b/img/flame test.webp index d4fe1d8..50c3090 100644 Binary files a/img/flame test.webp and b/img/flame test.webp differ diff --git a/img/gun/drones.webp b/img/gun/drones.webp index 6429896..a91022d 100644 Binary files a/img/gun/drones.webp and b/img/gun/drones.webp differ diff --git a/img/gun/grenades.webp b/img/gun/grenades.webp index 6b5e3d1..6a6c048 100644 Binary files a/img/gun/grenades.webp and b/img/gun/grenades.webp differ diff --git a/img/gun/laser.webp b/img/gun/laser.webp index 694a711..de8624e 100644 Binary files a/img/gun/laser.webp and b/img/gun/laser.webp differ diff --git a/img/shaped charge.webp b/img/shaped charge.webp index c1afd4f..70b7a7c 100644 Binary files a/img/shaped charge.webp and b/img/shaped charge.webp differ diff --git a/img/vacuum bomb.webp b/img/vacuum bomb.webp index 50dc56c..88011ca 100644 Binary files a/img/vacuum bomb.webp and b/img/vacuum bomb.webp differ diff --git a/js/bullet.js b/js/bullet.js index 89ecbd4..4f04a9c 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -3439,7 +3439,7 @@ const b = { for (let i = 0, len = powerUp.length; i < len; ++i) { //grab, but don't lock onto nearby power up if ( Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && - (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) && + (powerUp[i].name !== "heal" || m.health < 0.93 * m.maxHealth || tech.isDroneGrab) && (powerUp[i].name !== "field" || !tech.isSuperDeterminism) // &&(b.inventory.length > 1 || powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { @@ -3470,7 +3470,7 @@ const b = { let closeDist = Infinity; for (let i = 0, len = powerUp.length; i < len; ++i) { if ( - (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) && + (powerUp[i].name !== "heal" || m.health < 0.93 * m.maxHealth || tech.isDroneGrab) && (powerUp[i].name !== "field" || !tech.isSuperDeterminism) // &&(b.inventory.length > 1 || powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { @@ -3647,7 +3647,7 @@ const b = { for (let i = 0, len = powerUp.length; i < len; ++i) { if ( Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && - (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) && + (powerUp[i].name !== "heal" || m.health < 0.93 * m.maxHealth || tech.isDroneGrab) && (powerUp[i].name !== "field" || !tech.isSuperDeterminism) // &&(powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { @@ -3679,7 +3679,7 @@ const b = { let closeDist = Infinity; for (let i = 0, len = powerUp.length; i < len; ++i) { if ( - (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) && + (powerUp[i].name !== "heal" || m.health < 0.93 * m.maxHealth || tech.isDroneGrab) && (powerUp[i].name !== "field" || !tech.isSuperDeterminism) // &&(powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { @@ -4988,7 +4988,7 @@ const b = { cd: 0, fireCount: 0, fireLimit: 5 + 2 * tech.isFoamBotUpgrade, - delay: Math.floor((200 + (tech.isFoamBotUpgrade ? 0 : 300)) * b.fireCDscale),// + 30 - 20 * tech.isFoamBotUpgrade,//20 + Math.floor(85 * b.fireCDscale) - 20 * tech.isFoamBotUpgrade, + delay: Math.floor((175 + (tech.isFoamBotUpgrade ? 0 : 250)) * b.fireCDscale),// + 30 - 20 * tech.isFoamBotUpgrade,//20 + Math.floor(85 * b.fireCDscale) - 20 * tech.isFoamBotUpgrade, acceleration: 0.005 * (1 + 0.5 * Math.random()), range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots(), //how far from the player the bot will move endCycle: Infinity, @@ -7161,7 +7161,7 @@ const b = { } }, { name: "drones", //7 - description: "deploy drones that crash into mobs
or collect nearby power ups", //crashes reduce their lifespan by 1 second + description: "deploy autonomous drones that smash into mobs
and collect nearby power ups", //crashes reduce their lifespan by 1 second ammo: 0, ammoPack: 16, defaultAmmoPack: 16, diff --git a/js/level.js b/js/level.js index 2a446d5..dcdc7a8 100644 --- a/js/level.js +++ b/js/level.js @@ -23,7 +23,7 @@ const level = { // spawn.setSpawnList(); // m.maxHealth = m.health = 100 // tech.isRerollDamage = true - // powerUps.research.changeRerolls(500) + // powerUps.research.changeRerolls(11) // m.immuneCycle = Infinity //you can't take damage // tech.tech[297].frequency = 100 // m.couplingChange(5) @@ -35,13 +35,13 @@ const level = { // b.guns[3].ammo = 100000000 // tech.giveTech("recycling") // tech.giveTech("pressure vessel") - // for (let i = 0; i < 1; ++i) tech.giveTech("cavitation") + // for (let i = 0; i < 1; ++i) tech.giveTech("bot fabrication") // for (let i = 0; i < 1; ++i) tech.giveTech("accretion") // for (let i = 0; i < 1; ++i) tech.giveTech("superdeterminism") // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("foam-bot") }); // for (let i = 0; i < 1; i++) tech.giveTech("foam-bot upgrade") // for (let i = 0; i < 3; 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, "research"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); // level.testing(); // spawn.nodeGroup(3200, -300, "sniper") @@ -59,6 +59,7 @@ const level = { // spawn.tetherBoss(1900, -500, { x: 1900, y: -500 }) // for (let i = 0; i < 40; ++i) tech.giveTech() + level[simulation.isTraining ? "walk" : "intro"]() //normal starting level ************************************************ // simulation.isAutoZoom = false; //look in close @@ -1314,7 +1315,7 @@ const level = { Matter.Body.setVelocity(bullet[i], { x: 0, y: 0 }); } } - if (tech.isHealAttract && (m.fieldMode === 3 || m.fieldMode === 5)) { + if (tech.isHealAttract) { //send heals to next portal for (let i = 0; i < powerUp.length; i++) { if (powerUp[i].name === "heal" && Vector.magnitudeSquared(Vector.sub(powerUp[i].position, m.pos)) < 1000000) { Matter.Body.setPosition(powerUp[i], Vector.add(this.portalPair.portal.position, { x: 500 * (Math.random() - 0.5), y: 500 * (Math.random() - 0.5) })); @@ -15999,9 +16000,12 @@ const level = { commandeer() { simulation.makeTextLog(`commandeer by Desboot`); + let waterFallWidth = 400 + let waterFallX = 15900 + let waterFallSmoothX = 0 const elevator = level.elevator(-80.4, -931.6, 180, 50, -1550) 15900 && player.position.x < 16300 && player.position.y > -960.2 - const slime = level.hazard(15900, -960, 400, 6000); + //const slime = level.hazard(15900, -960, 400, 6000); const slime2 = level.hazard(15147.2, -1782.4, 2000, 822); const boost1 = level.boost(5950, -20, 700) const boost2 = level.boost(21088, -1672, 700) @@ -16037,7 +16041,6 @@ const level = { //spawn.mapRect(22330, -804.25, 400, 800);//-46.25*3 - ctx.fillStyle = "rgba(250,250,250,0.8)"//lights ctx.beginPath() ctx.moveTo(1124, -628) @@ -16073,7 +16076,6 @@ const level = { ctx.fillRect(6237, -1830.7, 550, 700) ctx.fillRect(6237, -840.4, 550, 700) - ctx.fillRect(15845.0, -1262.2, 550, 300) ctx.fillStyle = "rgba(200,200,200,0.8)" ctx.fillRect(-192, -1973, 6484, 2071) ctx.fillStyle = "rgba(240,240,240,0.8)" @@ -16099,12 +16101,10 @@ const level = { buttonDoor3.draw(); - slime.query(); + //slime.query(); slime2.query(); - ctx.fillStyle = `hsla(160, 100%, 43%,${0.3 + 0.07 * Math.random()})` - ctx.fillRect(15900 + 400 * Math.random(), -1360, 2, 6000) - ctx.fillRect(15900 + 400 * Math.random(), -1360, 2, 6000) + if (buttonDoor.isUp) { door.isClosing = true } else { @@ -16172,6 +16172,17 @@ const level = { ctx.fillRect(20820, -243, 410, 300) ctx.fillRect(5772, -609, 469, 700) ctx.fillRect(5772, -609, 469, 700) + + ctx.fillStyle = "rgba(48,184,140,255)" + ctx.fillRect(waterFallX, -960, waterFallWidth, 6000) + ctx.fillStyle = `hsla(160, 100%, 43%,${0.3 + 0.07 * Math.random()})` + ctx.fillRect(waterFallX + waterFallWidth * Math.random(), -900 - Math.random() * 400, Math.random() * 5 + 8, 6000) + ctx.fillRect(waterFallX + waterFallWidth * Math.random(), -900 - Math.random() * 400, Math.random() * 5 + 5, 6000) + waterFallWidth = 0.995 * waterFallWidth + 4 * Math.random()//4.7 + waterFalSmoothlX = 0.96 * waterFallSmoothX + 20 * Math.random()//3.5 + waterFallX = waterFallSmoothX + 15900 + + ctx.fillStyle = "rgba(0,0,0,0.4)"//wires ctx.fillRect(20990, -2672, 20, 112) ctx.fillRect(21090, -2506, 72, 20) @@ -16304,7 +16315,7 @@ const level = { if (player.position.x > 15900 && player.position.x < 16300 && player.position.y > -1360.2) { Matter.Body.setVelocity(player, { x: player.velocity.x, - y: player.velocity.y + 10 + y: player.velocity.y + 2 }); } else { if (Math.abs(player.velocity.x) > 0.5) { @@ -16576,9 +16587,7 @@ const level = { - let randomBoss = Math.floor(Math.random() * 5);//change the bosses - spawn[["blinkBoss", "shooterBoss", "launcherBoss", "pulsarBoss", "beetleBoss", "bladeBoss", "revolutionBoss", "dragonFlyBoss", "spiderBoss"][randomBoss]](17902, -1689, 100, false); - + spawn.randomLevelBoss(17902, -1689, ["blinkBoss", "shooterBoss", "launcherBoss", "pulsarBoss", "blockBoss", "bladeBoss", "revolutionBoss", "spawnerBossCulture", "spiderBoss", "sneakBoss", "snakeSpitBoss"]) // powerUps.spawnStartingPowerUps(1475, -1175); @@ -18373,19 +18382,6 @@ const level = { ctx.fill() ctx.fillRect(6100, -2000, 400, 50) - - - - - - - - - - - - - // -2000 -> 2500 // Math.random() * 5000 -2500 ctx.fillStyle = "rgba(0,0,0,0.6)" diff --git a/js/mob.js b/js/mob.js index e38c6a2..9b0b0ee 100644 --- a/js/mob.js +++ b/js/mob.js @@ -201,7 +201,7 @@ const mobs = { } } }, - endEffect() {}, + endEffect() { }, dmg: tickDamage, type: "dot", endCycle: simulation.cycle + cycles, @@ -506,7 +506,7 @@ const mobs = { } }, laser() { - const vertexCollision = function(v1, v1End, domain) { + const vertexCollision = function (v1, v1End, domain) { for (let i = 0; i < domain.length; ++i) { let vertices = domain[i].vertices; const len = vertices.length - 1; @@ -658,7 +658,7 @@ const mobs = { ctx.fillStyle = "rgba(0,0,0,0.07)"; ctx.fill(); //spring to random place on map - const vertexCollision = function(v1, v1End, domain) { + const vertexCollision = function (v1, v1End, domain) { for (let i = 0; i < domain.length; ++i) { let vertices = domain[i].vertices; const len = vertices.length - 1; @@ -756,7 +756,7 @@ const mobs = { }, curl(range = 1000, mag = -10) { //cause all mobs, and bodies to rotate in a circle - applyCurl = function(center, array, isAntiGravity = true) { + applyCurl = function (center, array, isAntiGravity = true) { for (let i = 0; i < array.length; ++i) { if (!array[i].isNotHoldable) { const sub = Vector.sub(center, array[i].position) @@ -924,7 +924,7 @@ const mobs = { //be sure to declare searchTarget in mob spawn //accelerate towards the searchTarget if (!this.seePlayer.recall) { - const newTarget = function(that) { + const newTarget = function (that) { if (Math.random() < 0.0007) { that.searchTarget = player.position; //chance to target player } else { @@ -1297,7 +1297,7 @@ const mobs = { } if (tech.cloakDuplication && !this.isBoss) { tech.cloakDuplication -= 0.02 - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance } } else if (tech.isShieldAmmo && this.shield && !this.isExtraShield) { let type = tech.isEnergyNoAmmo ? "heal" : "ammo" @@ -1350,7 +1350,7 @@ const mobs = { for (let i = 0, len = consBB.length; i < len; ++i) { if (consBB[i].bodyA === this) { if (consBB[i].bodyB.shield) { //&& !this.shield - consBB[i].bodyB.do = function() { this.death() } + consBB[i].bodyB.do = function () { this.death() } } consBB[i].bodyA = consBB[i].bodyB; consBB.splice(i, 1); @@ -1358,7 +1358,7 @@ const mobs = { break; } else if (consBB[i].bodyB === this) { if (consBB[i].bodyA.shield) { - consBB[i].bodyA.do = function() { this.death() } + consBB[i].bodyA.do = function () { this.death() } } consBB[i].bodyB = consBB[i].bodyA; consBB.splice(i, 1); @@ -1415,7 +1415,7 @@ const mobs = { //large mobs shrink so they don't block paths if (body[len].mass + body[len2].mass > 16) { const massLimit = 8 + 6 * Math.random() - const shrink = function(that1, that2) { + const shrink = function (that1, that2) { if (that1.mass + that2.mass > massLimit) { const scale = 0.95; Matter.Body.scale(that1, scale, scale); @@ -1438,7 +1438,7 @@ const mobs = { //large mobs shrink so they don't block paths if (body[len].mass > 9) { const massLimit = 7 + 4 * Math.random() - const shrink = function(that) { + const shrink = function (that) { if (that.mass > massLimit) { const scale = 0.95; Matter.Body.scale(that, scale, scale); diff --git a/js/player.js b/js/player.js index 83071a3..972ea9e 100644 --- a/js/player.js +++ b/js/player.js @@ -916,6 +916,48 @@ const m = { none() { m.isAltSkin = true }, + favicon() { //used to render the favicon, not actually in game + m.yOffWhen.jump = 70 + m.yOffWhen.stand = 49 + m.yOffWhen.crouch = 22 + m.isAltSkin = false + m.color = { + hue: 0, + sat: 0, + light: 100, + } + + m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)` + m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 10}%)` + let grd = ctx.createLinearGradient(-30, 0, 30, 0); + grd.addColorStop(0, m.fillColorDark); + grd.addColorStop(1, m.fillColor); + m.bodyGradient = grd + + m.draw = function () { + ctx.fillStyle = m.fillColor; + m.walk_cycle += m.flipLegs * m.Vx; + ctx.save(); + ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20) + ctx.translate(m.pos.x, m.pos.y); + // m.calcLeg(Math.PI, -3); + // m.drawLeg("#4a4a4a"); + // m.calcLeg(0, 0); + // m.drawLeg("#333"); + // ctx.rotate(m.angle); + ctx.beginPath(); + ctx.arc(0, 0, 30, 0, 2 * Math.PI); + ctx.fillStyle = m.bodyGradient + ctx.fill(); + ctx.arc(12, 0, 4.5, 0, 2 * Math.PI); + ctx.strokeStyle = "#333"; + ctx.lineWidth = 4.5; + ctx.stroke(); + ctx.restore(); + m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal + powerUps.boost.draw() + } + }, mech() { m.isAltSkin = true m.yOffWhen.stand = 52 @@ -1801,11 +1843,11 @@ const m = { m.fieldThreshold = Math.cos((m.fieldArc) * Math.PI) }, setHoldDefaults() { - if (tech.isFreeWormHole && m.fieldUpgrades[m.fieldMode].name !== "wormhole") { + if (tech.isFreeWormHole && m.fieldMode !== 9) { //not wormhole const removed = tech.removeTech("charmed baryon") //neutronum can get player stuck so it has to be removed if player has wrong field if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); } - if (tech.isNeutronium && m.fieldUpgrades[m.fieldMode].name !== "negative mass") { + if (tech.isNeutronium && m.fieldMode !== 3) { //not negative mass field const removed = tech.removeTech("neutronium") //neutronum can get player stuck so it has to be removed if player has wrong field if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); } @@ -1854,7 +1896,7 @@ const m = { }, setMaxEnergy() { // (m.fieldMode === 0 || m.fieldMode === 1) * 0.4 * m.coupling + - m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + 0.66 * (m.fieldMode === 1) + m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + 1.5 * (m.fieldMode === 1) // if (tech.isEnergyHealth) m.maxEnergy *= Math.sqrt(m.defense()) simulation.makeTextLog(`m.maxEnergy = ${(m.maxEnergy.toFixed(2))}`) }, @@ -2211,7 +2253,7 @@ const m = { if ( //use power up if it is close enough dist2 < 5000 && !simulation.isChoosing && - (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal) + (powerUp[i].name !== "heal" || m.maxHealth - m.health > 0.01 || tech.isOverHeal) ) { powerUps.onPickUp(powerUp[i]); Matter.Body.setVelocity(player, { //player knock back, after grabbing power up @@ -2471,7 +2513,7 @@ const m = { // m.setMaxHealth(); m.setFieldRegen() mobs.setMobSpawnHealth(); - powerUps.setDupChance(); + powerUps.setPowerUpMode(); if ((m.fieldMode === 0 || m.fieldMode === 9) && !build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.4); // m.collisionImmuneCycles = 30 + m.coupling * 120 //2 seconds @@ -2551,7 +2593,7 @@ const m = { name: "standing wave", //deflecting protects you in every direction description: `3 oscillating shields are permanently active -
+66 max energy +
+150 max energy
generate 6 energy per second`, drainCD: 0, effect: () => { @@ -2565,7 +2607,7 @@ const m = { const fieldRange1 = (0.75 + 0.3 * Math.sin(m.cycle / 23)) * m.fieldRange * m.harmonicRadius const fieldRange2 = (0.68 + 0.37 * Math.sin(m.cycle / 37)) * m.fieldRange * m.harmonicRadius const fieldRange3 = (0.7 + 0.35 * Math.sin(m.cycle / 47)) * m.fieldRange * m.harmonicRadius - const netfieldRange = Math.max(fieldRange1, fieldRange2, fieldRange3) + const netFieldRange = Math.max(fieldRange1, fieldRange2, fieldRange3) ctx.fillStyle = "rgba(110,170,200," + Math.min(0.6, (0.04 + m.energy * (0.1 + 0.11 * Math.random()))) + ")"; ctx.beginPath(); ctx.arc(m.pos.x, m.pos.y, fieldRange1, 0, 2 * Math.PI); @@ -2578,7 +2620,7 @@ const m = { ctx.fill(); //360 block for (let i = 0, len = mob.length; i < len; ++i) { - if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) - mob[i].radius < netfieldRange && !mob[i].isUnblockable) { // && Matter.Query.ray(map, mob[i].position, m.pos).length === 0 + if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) - mob[i].radius < netFieldRange && !mob[i].isUnblockable) { // && Matter.Query.ray(map, mob[i].position, m.pos).length === 0 mob[i].locatePlayer(); if (this.drainCD > m.cycle) { m.pushMass(mob[i], 0); @@ -3052,17 +3094,17 @@ const m = { m.drawRegenEnergy("rgba(0,0,0,0.2)") - if (tech.isHealAttract) { - for (let i = 0; i < powerUp.length; i++) { - if (powerUp[i].name === "heal") { - //&& Vector.magnitudeSquared(Vector.sub(powerUp[i].position, m.pos)) < 500000 - let attract = Vector.mult(Vector.normalise(Vector.sub(m.pos, powerUp[i].position)), 0.01 * powerUp[i].mass) - powerUp[i].force.x += attract.x; - powerUp[i].force.y += attract.y - powerUp[i].mass * simulation.g; //negate gravity - Matter.Body.setVelocity(powerUp[i], Vector.mult(powerUp[i].velocity, 0.7)); - } - } - } + // if (tech.isHealAttract) { + // for (let i = 0; i < powerUp.length; i++) { + // if (powerUp[i].name === "heal") { + // //&& Vector.magnitudeSquared(Vector.sub(powerUp[i].position, m.pos)) < 500000 + // let attract = Vector.mult(Vector.normalise(Vector.sub(m.pos, powerUp[i].position)), 0.01 * powerUp[i].mass) + // powerUp[i].force.x += attract.x; + // powerUp[i].force.y += attract.y - powerUp[i].mass * simulation.g; //negate gravity + // Matter.Body.setVelocity(powerUp[i], Vector.mult(powerUp[i].velocity, 0.7)); + // } + // } + // } // powerUp[i].force.x += 0.05 * (dxP / Math.sqrt(dist2)) * powerUp[i].mass; @@ -3562,17 +3604,6 @@ const m = { } m.drawRegenEnergy("rgba(0, 0, 0, 0.2)") m.plasmaBall.do() - if (tech.isHealAttract) { - for (let i = 0; i < powerUp.length; i++) { - if (powerUp[i].name === "heal") { - //&& Vector.magnitudeSquared(Vector.sub(powerUp[i].position, m.pos)) < 500000 - let attract = Vector.mult(Vector.normalise(Vector.sub(m.pos, powerUp[i].position)), 0.01 * powerUp[i].mass) - powerUp[i].force.x += attract.x; - powerUp[i].force.y += attract.y - powerUp[i].mass * simulation.g; //negate gravity - Matter.Body.setVelocity(powerUp[i], Vector.mult(powerUp[i].velocity, 0.7)); - } - } - } } } else if (tech.isExtruder) { m.hold = function () { @@ -3615,17 +3646,6 @@ const m = { ctx.lineWidth = tech.extruderRange; ctx.strokeStyle = "rgba(255,0,110,0.06)" ctx.stroke(); - if (tech.isHealAttract) { - for (let i = 0; i < powerUp.length; i++) { - if (powerUp[i].name === "heal") { - //&& Vector.magnitudeSquared(Vector.sub(powerUp[i].position, m.pos)) < 500000 - let attract = Vector.mult(Vector.normalise(Vector.sub(m.pos, powerUp[i].position)), 0.01 * powerUp[i].mass) - powerUp[i].force.x += attract.x; - powerUp[i].force.y += attract.y - powerUp[i].mass * simulation.g; //negate gravity - Matter.Body.setVelocity(powerUp[i], Vector.mult(powerUp[i].velocity, 0.7)); - } - } - } } } else { m.hold = function () { @@ -3644,17 +3664,6 @@ const m = { m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) } m.drawRegenEnergy("rgba(0, 0, 0, 0.2)") - if (tech.isHealAttract) { - for (let i = 0; i < powerUp.length; i++) { - if (powerUp[i].name === "heal") { - //&& Vector.magnitudeSquared(Vector.sub(powerUp[i].position, m.pos)) < 500000 - let attract = Vector.mult(Vector.normalise(Vector.sub(m.pos, powerUp[i].position)), 0.01 * powerUp[i].mass) - powerUp[i].force.x += attract.x; - powerUp[i].force.y += attract.y - powerUp[i].mass * simulation.g; //negate gravity - Matter.Body.setVelocity(powerUp[i], Vector.mult(powerUp[i].velocity, 0.7)); - } - } - } } } }, @@ -4133,7 +4142,7 @@ const m = { //
blocks can't collide with intangible mobs //field radius decreases out of line of sight //unlock tech from other fields - description: "use energy to guide blocks
tech, fields, and guns have +1 choice
generate 10 energy per second", + description: "use energy to guide blocks
tech, fields, and guns have +2 choice
generate 10 energy per second", effect: () => { m.fieldMeterColor = "#333" m.eyeFillColor = m.fieldMeterColor @@ -4213,7 +4222,7 @@ const m = { if ( dist2 < 5000 && !simulation.isChoosing && - (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal) + (powerUp[i].name !== "heal" || m.maxHealth - m.health > 0.01 || tech.isOverHeal) // (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth) // (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity) ) { //use power up if it is close enough @@ -4340,7 +4349,7 @@ const m = { m.duplicateChance = 0.03 m.fieldRange = 0 - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance m.hold = function () { // m.hole = { //this is reset with each new field, but I'm leaving it here for reference diff --git a/js/powerup.js b/js/powerup.js index c9ee175..4fe8128 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -165,17 +165,17 @@ const powerUps = { }, totalPowerUps: 0, //used for tech that count power ups at the end of a level do() { }, - setDupChance() { + setPowerUpMode() { if (tech.duplicationChance() > 0 || tech.isAnthropicTech) { if (tech.isPowerUpsVanish) { powerUps.do = powerUps.doDuplicatesVanish - } else if (tech.isPowerUpsAttract) { + } else if (tech.isHealAttract) { powerUps.do = powerUps.doAttractDuplicates } else { powerUps.do = powerUps.doDuplicates } tech.maxDuplicationEvent() //check to see if hitting 100% duplication - } else if (tech.isPowerUpsAttract) { + } else if (tech.isHealAttract) { powerUps.do = powerUps.doAttract } else { powerUps.do = powerUps.doDefault @@ -194,16 +194,32 @@ const powerUps = { }, doAttract() { powerUps.doDefault(); - //pull in - for (let i = 0, len = powerUp.length; i < len; ++i) { - const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, powerUp[i].position)), 0.0015 * powerUp[i].mass) - powerUp[i].force.x += force.x - powerUp[i].force.y = force.y - simulation.g + for (let i = 0; i < powerUp.length; i++) { //attract heal power ups to player + if (powerUp[i].name === "heal") { + //&& Vector.magnitudeSquared(Vector.sub(powerUp[i].position, m.pos)) < 500000 + let attract = Vector.mult(Vector.normalise(Vector.sub(m.pos, powerUp[i].position)), 0.015 * powerUp[i].mass) + powerUp[i].force.x += attract.x; + powerUp[i].force.y += attract.y - powerUp[i].mass * simulation.g; //negate gravity + Matter.Body.setVelocity(powerUp[i], Vector.mult(powerUp[i].velocity, 0.7)); + } } + // for (let i = 0, len = powerUp.length; i < len; ++i) { + // const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, powerUp[i].position)), 0.0015 * powerUp[i].mass) + // powerUp[i].force.x += force.x + // powerUp[i].force.y = force.y - simulation.g + // } }, doAttractDuplicates() { powerUps.doDuplicates(); - //pull in + for (let i = 0; i < powerUp.length; i++) { //attract heal power ups to player + if (powerUp[i].name === "heal") { + //&& Vector.magnitudeSquared(Vector.sub(powerUp[i].position, m.pos)) < 500000 + let attract = Vector.mult(Vector.normalise(Vector.sub(m.pos, powerUp[i].position)), 0.015 * powerUp[i].mass) + powerUp[i].force.x += attract.x; + powerUp[i].force.y += attract.y - powerUp[i].mass * simulation.g; //negate gravity + Matter.Body.setVelocity(powerUp[i], Vector.mult(powerUp[i].velocity, 0.7)); + } + } }, doDuplicates() { //draw power ups but give duplicates some electricity ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6; @@ -448,20 +464,18 @@ const powerUps = { effect() { powerUps.research.changeRerolls(1) }, + isMakingBots: false, //to prevent bot fabrication from running 2 sessions at once changeRerolls(amount) { - if (amount !== 0) { - powerUps.research.count += amount - // if (powerUps.research.count < 0) powerUps.research.count = 0 - - // else { - // simulation.makeTextLog(`powerUps.research.count += ${amount}`) //
${powerUps.research.count} - // } - } - if (tech.isRerollBots) { - + if (amount !== 0) powerUps.research.count += amount + if (tech.isRerollBots && !this.isMakingBots) { let cycle = () => { const cost = 2 + Math.floor(0.2 * b.totalBots()) - if (m.alive && powerUps.research.count >= cost) requestAnimationFrame(cycle); + if (m.alive && powerUps.research.count >= cost) { + requestAnimationFrame(cycle); + this.isMakingBots = true + } else { + this.isMakingBots = false + } if (!simulation.paused && !simulation.isChoosing && !(simulation.cycle % 60)) { powerUps.research.count -= cost b.randomBot() @@ -476,24 +490,6 @@ const powerUps = { } } requestAnimationFrame(cycle); - - - // let delay = 0 - // for (let cost = 2 + Math.floor(0.2 * b.totalBots()); powerUps.research.count > cost - 1; powerUps.research.count -= cost) { // 1/5 = 0.2 - // cost = 2 + Math.floor(0.2 * b.totalBots()) - // delay += 500 - // setTimeout(() => { - // b.randomBot() - // if (tech.renormalization) { - // for (let i = 0; i < cost; i++) { - // if (Math.random() < 0.44) { - // m.fieldCDcycle = m.cycle + 20; - // powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "research"); - // } - // } - // } - // }, delay); - // } } if (tech.isDeathAvoid && document.getElementById("tech-anthropic")) { document.getElementById("tech-anthropic").innerHTML = `-${powerUps.research.count}` @@ -563,6 +559,11 @@ const powerUps = { }); tech.extraMaxHealth += scaledOverHeal * simulation.healScale //increase max health m.setMaxHealth(); + } else if (overHeal > 0.1) { + requestAnimationFrame(() => { + powerUps.directSpawn(this.position.x, this.position.y, "heal", true, null, overHeal * 40 * (simulation.healScale ** 0.25))// directSpawn(x, y, target, moving = true, mode = null, size = powerUps[target].size()) { + }); + } } } @@ -875,7 +876,7 @@ const powerUps = { for (let i = 0; i < b.guns.length; i++) { if (!b.guns[i].have) options.push(i); } - let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + (m.fieldMode === 8))) + let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + 2 * (m.fieldMode === 8))) if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay function removeOption(index) { for (let i = 0; i < options.length; i++) { @@ -939,7 +940,7 @@ const powerUps = { for (let i = 1; i < m.fieldUpgrades.length; i++) { //skip field emitter if (i !== m.fieldMode) options.push(i); } - let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + (m.fieldMode === 8))) + let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + 2 * (m.fieldMode === 8))) if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay function removeOption(index) { @@ -1022,7 +1023,7 @@ const powerUps = { } } //set total choices - let totalChoices = (tech.isDeterminism ? 1 : 3 + tech.extraChoices + (m.fieldMode === 8)) + let totalChoices = (tech.isDeterminism ? 1 : 3 + tech.extraChoices + 2 * (m.fieldMode === 8)) if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay if (optionLengthNoDuplicates < totalChoices + 1) { //if not enough options for all the choices totalChoices = optionLengthNoDuplicates diff --git a/js/simulation.js b/js/simulation.js index e20bdaf..86d400a 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -943,8 +943,7 @@ const simulation = { m.hole.isOn = false; simulation.drawList = []; - //send health power ups to the next level - if (tech.isHealAttract && m.alive && (m.fieldMode === 3 || m.fieldMode === 5)) { + if (tech.isHealAttract && m.alive) { //send health power ups to the next level let healCount = 0 for (let i = 0, len = powerUp.length; i < len; i++) { if (powerUp[i].name === "heal" && Vector.magnitudeSquared(Vector.sub(powerUp[i].position, m.pos)) < 1000000) healCount++ diff --git a/js/tech.js b/js/tech.js index 2bbcf1f..0fd43e6 100644 --- a/js/tech.js +++ b/js/tech.js @@ -246,7 +246,7 @@ const tech = { if (tech.isBotDamage) dmg *= 1 + 0.06 * b.totalBots() if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage if (tech.isLowEnergyDamage) dmg *= 1 + 0.7 * Math.max(0, 1 - m.energy) - if (tech.energyDamage) dmg *= 1 + m.energy * 0.1 * tech.energyDamage; + if (tech.energyDamage) dmg *= 1 + m.energy * 0.15 * tech.energyDamage; if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.007 if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2 if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.66, player.speed * 0.0165) @@ -1271,6 +1271,7 @@ const tech = { count: 0, frequency: 1, frequencyDefault: 1, + isHealTech: true, allowed() { return true }, @@ -2553,7 +2554,7 @@ const tech = { { name: "electronegativity", descriptionFunction() { - return `+0.1% damage per current stored energy
(+${(10 * m.energy).toFixed(0)}%)` + return `+0.15% damage per current stored energy
(+${(15 * m.energy).toFixed(0)}%)` }, // description: "+1% damage per 8 stored energy", maxCount: 9, @@ -3017,6 +3018,7 @@ const tech = { count: 0, frequency: 1, frequencyDefault: 1, + isHealTech: true, allowed() { return !tech.isHealAttract }, @@ -3028,6 +3030,29 @@ const tech = { tech.isOverHeal = false; } }, + { + name: "accretion", + description: `${powerUps.orb.heal(1)} follow you, even between levels
spawn ${powerUps.orb.heal(3)}`, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + isHealTech: true, + allowed() { + return m.fieldMode !== 9 && !tech.isOverHeal + }, + requires: "not wormhole, quenching", + effect() { + tech.isHealAttract = true + powerUps.setPowerUpMode(); + for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "heal"); + }, + remove() { + tech.isHealAttract = false + powerUps.setPowerUpMode(); + }, + }, + { name: "negative entropy", descriptionFunction() { @@ -3137,11 +3162,11 @@ const tech = { requires: "anthropic principle", effect() { tech.isAnthropicTech = true - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance }, remove() { tech.isAnthropicTech = false - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance } }, { @@ -3889,11 +3914,11 @@ const tech = { requires: "below 100% duplication chance, not superdeterminism", effect() { tech.isCancelDuplication = true //search for tech.cancelCount to balance - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance }, remove() { tech.isCancelDuplication = false - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance } }, { @@ -3909,14 +3934,14 @@ const tech = { requires: "below 100% duplication chance", effect() { tech.duplicateChance += 0.1 - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.11); this.refundAmount += tech.addJunkTechToPool(0.33) }, refundAmount: 0, remove() { tech.duplicateChance = 0 - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (this.count > 0 && this.refundAmount > 0) { tech.removeJunkTechFromPool(this.refundAmount) this.refundAmount = 0 @@ -3936,12 +3961,12 @@ const tech = { requires: "below 1% duplication chance", effect() { tech.isStimulatedEmission = true - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.15); }, remove() { tech.isStimulatedEmission = false - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance } }, { @@ -3957,12 +3982,12 @@ const tech = { requires: "below 100% duplication chance", effect() { tech.isPowerUpsVanish = true - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.11); }, remove() { tech.isPowerUpsVanish = false - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance } }, { @@ -7465,26 +7490,6 @@ const tech = { } } }, - { - name: "accretion", - description: `${powerUps.orb.heal(1)} follow you, even between levels
spawn ${powerUps.orb.heal(6)}`, - isFieldTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return (m.fieldMode === 3 || m.fieldMode === 5) && !tech.isOverHeal - }, - requires: "negative mass, plasma torch, not quenching", - effect() { - tech.isHealAttract = true - for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "heal"); - }, - remove() { - tech.isHealAttract = false - }, - }, { name: "aerostat", description: `+88% damage while off the ground
-22% damage while on the ground`, @@ -8042,9 +8047,9 @@ const tech = { frequency: 3, frequencyDefault: 3, allowed() { - return (m.fieldMode === 6) && (build.isExperimentSelection || powerUps.research.count > 2) + return (m.fieldMode === 6 || m.fieldMode === 8) && (build.isExperimentSelection || powerUps.research.count > 2) }, - requires: "time dilation", + requires: "time dilation or pilot wave", effect() { tech.isFastTime = true m.setMovement(); @@ -8096,12 +8101,12 @@ const tech = { requires: "cloaking, time dilation, not quantum eraser", effect() { tech.cloakDuplication = 0.45 - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.4); }, remove() { tech.cloakDuplication = 0 - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance } }, { @@ -8296,7 +8301,7 @@ const tech = { requires: "wormhole, time dilation, negative mass, pilot wave", effect() { tech.fieldDuplicate = 0.11 - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.11); for (let i = 0; i < 4; i++) { if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) @@ -8304,7 +8309,7 @@ const tech = { }, remove() { tech.fieldDuplicate = 0 - powerUps.setDupChance(); //needed after adjusting duplication chance + powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (this.count > 0) powerUps.research.changeRerolls(4) } }, diff --git a/todo.txt b/todo.txt index 111705b..6d4df0a 100644 --- a/todo.txt +++ b/todo.txt @@ -1,23 +1,32 @@ ******************************************************** NEXT PATCH ************************************************** -field tech: accretion - health power ups follow you around and they travel with you to the to next level - spawn 6 heal power ups - negative mass, plasma torch +new favicon +heal power up overheals don't consume the entire heal power up -foam gun tech cavitation - more knock back, and 25% to make a foam bullet extra large and fast +accretion works with all fields except wormhole + (only because wormhole eat up heals so it's bad) + spawns 6 -> 3 heals -foam-bots now discharge a few bullets in a stream with a long reload time -laser-bot +5% energy drain, -5% damage -nail-bot +10% fire rate +pilot wave 1 -> 2 extra power up choices +standing wave 66 -> 150 max energy +electronegativity 0.1% -> 0.15% energy per energy (10->15% damage at 100 energy) + +a few more images +bug fixes *********************************************************** TODO ***************************************************** +tech: thorns? extend accretion to all fields run the code in power ups tech: using research spawns a heal and ammo +Tech: relativity + Simulation speed scales with movement speed. When still, time moves at 0.4 speed, at full walking speed it’s 1. (So if you’re falling or something and you move faster the simulation will be faster than usual) + Also a damage and/or defense boost to make it worth using + Tech: Turbine - Energy generation is proportional to your speed up to +X% energy generation at 40 speed Tech: "Electric Reactive Armor": Defense increases by 2% for each 1 energy generation you have @@ -1214,7 +1223,7 @@ if pause is pressed while selecting power ups, display pause menu on top of sele nail gun - Screenprint shotgun - blueprint by Dan McPharlin - grenades, missiles, explosions - by Victo Ngai + grenades, missiles, explosions - vibrant fireball explosion sonic shockwave ring art by Victo Ngai --ar 3:2 --v 5 --s 750 spores - turquoise black spores on a white background full color scientific anatomy by Ernst Haeckel drones - tilt-shift photography super balls - By Akari Toriyama