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