diff --git a/.DS_Store b/.DS_Store
index 949d80d..2ff3b21 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/js/bullet.js b/js/bullet.js
index fab7d0d..a5ac1fa 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -741,6 +741,7 @@ const b = {
bullet[me].endCycle = simulation.cycle + Math.floor(input.down ? 120 : 80);
bullet[me].restitution = 0.4;
bullet[me].do = function() {
+ // console.log(this.mass * 0.0025)
this.force.y += this.mass * 0.0025; //extra gravity for harder arcs
};
Composite.add(engine.world, bullet[me]); //add bullet to world
@@ -794,6 +795,7 @@ const b = {
this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion
};
speed = input.down ? 46 : 32
+
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + speed * Math.cos(angle),
y: m.Vy / 2 + speed * Math.sin(angle)
@@ -917,6 +919,8 @@ const b = {
}
};
speed = 35
+ // speed = input.down ? 43 : 32
+
bullet[me].endCycle = simulation.cycle + 70;
if (input.down) {
speed += 9
@@ -950,6 +954,8 @@ const b = {
Matter.Body.scale(bullet[me], SCALE, SCALE);
speed = input.down ? 25 : 15
+ // speed = input.down ? 43 : 32
+
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + speed * Math.cos(angle),
y: m.Vy / 2 + speed * Math.sin(angle)
@@ -1092,9 +1098,36 @@ const b = {
}
}
}
+ let gunIndex = null
+ for (let i = 0, len = b.guns.length; i < len; i++) {
+ if (b.guns[i].name === "grenades") {
+ gunIndex = i
+ }
+ }
+
+
if (tech.isNeutronBomb) {
b.grenade = grenadeNeutron
+ if (tech.isRPG) {
+ b.guns[gunIndex].do = function() {}
+ } else {
+ if (gunIndex) b.guns[gunIndex].do = function() {
+ const cycles = 80
+ const speed = input.down ? 35 : 20 //input.down ? 43 : 32
+ const g = input.down ? 0.137 : 0.135
+ const v = { x: m.Vx / 2 + speed * Math.cos(m.angle), y: m.Vy / 2 + speed * Math.sin(m.angle) }
+ ctx.strokeStyle = "rgba(68, 68, 68, 0.2)" //color.map
+ ctx.lineWidth = 2
+ ctx.beginPath()
+ for (let i = 1, len = 19; i < len + 1; i++) {
+ const time = cycles * i / len
+ ctx.lineTo(m.pos.x + time * v.x, m.pos.y + time * v.y + g * time * time)
+ }
+ ctx.stroke()
+ }
+ }
} else if (tech.isRPG) {
+ b.guns[gunIndex].do = function() {}
if (tech.isVacuumBomb) {
b.grenade = grenadeRPGVacuum
} else {
@@ -1102,8 +1135,34 @@ const b = {
}
} else if (tech.isVacuumBomb) {
b.grenade = grenadeVacuum
+ if (gunIndex) b.guns[gunIndex].do = function() {
+ const cycles = Math.floor(input.down ? 50 : 30) //30
+ const speed = input.down ? 44 : 35
+ const v = { x: m.Vx / 2 + speed * Math.cos(m.angle), y: m.Vy / 2 + speed * Math.sin(m.angle) }
+ ctx.strokeStyle = "rgba(68, 68, 68, 0.2)" //color.map
+ ctx.lineWidth = 2
+ ctx.beginPath()
+ for (let i = 1.6, len = 19; i < len + 1; i++) {
+ const time = cycles * i / len
+ ctx.lineTo(m.pos.x + time * v.x, m.pos.y + time * v.y + 0.34 * time * time)
+ }
+ ctx.stroke()
+ }
} else {
b.grenade = grenadeDefault
+ if (gunIndex) b.guns[gunIndex].do = function() {
+ const cycles = Math.floor(input.down ? 120 : 80) //30
+ const speed = input.down ? 43 : 32
+ const v = { x: m.Vx / 2 + speed * Math.cos(m.angle), y: m.Vy / 2 + speed * Math.sin(m.angle) }
+ ctx.strokeStyle = "rgba(68, 68, 68, 0.2)" //color.map
+ ctx.lineWidth = 2
+ ctx.beginPath()
+ for (let i = 0.5, len = 19; i < len + 1; i++) {
+ const time = cycles * i / len
+ ctx.lineTo(m.pos.x + time * v.x, m.pos.y + time * v.y + 0.34 * time * time)
+ }
+ ctx.stroke()
+ }
}
},
harpoon(where, target, angle = m.angle, harpoonLength = 1, isReturn = false, totalCycles = 15) {
@@ -2437,7 +2496,14 @@ const b = {
if (tech.isIncendiary && simulation.cycle + this.deathCycles < this.endCycle) {
const max = Math.max(Math.min(this.endCycle - simulation.cycle - this.deathCycles, 1500), 0)
b.explosion(this.position, max * 0.1 + this.isImproved * 110 + 60 * Math.random()); //makes bullet do explosive damage at end
- this.endCycle -= max
+ if (tech.isForeverDrones) {
+ this.endCycle = 0
+ b.drone({ x: m.pos.x + 30 * (Math.random() - 0.5), y: m.pos.y + 30 * (Math.random() - 0.5) }, 5)
+ bullet[bullet.length - 1].endCycle = Infinity
+ } else {
+
+ this.endCycle -= max
+ }
} else {
//move away from target after hitting
const unit = Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), -20)
diff --git a/js/index.js b/js/index.js
index c624667..caafb22 100644
--- a/js/index.js
+++ b/js/index.js
@@ -223,7 +223,7 @@ const build = {
damage increase: ${((tech.damageFromTech()-1)*100).toFixed(0)}%
harm reduction: ${harm.toFixed(harm > 90 ? 2 : 0)}%
fire delay decrease: ${((1-b.fireCDscale)*100).toFixed(b.fireCDscale < 0.1 ? 2 : 0)}%
-
duplication chance: ${(Math.min(1,tech.duplicationChance())*100).toFixed(0)}%
+
duplication chance: ${(tech.duplicationChance()*100).toFixed(0)}%
${botText}
tech: ${tech.totalCount} research: ${powerUps.research.count}
diff --git a/js/level.js b/js/level.js
index e1eefe7..c9247c9 100644
--- a/js/level.js
+++ b/js/level.js
@@ -16,9 +16,9 @@ const level = {
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true
// m.setField("time dilation")
- // b.giveGuns("harpoon")
- // tech.giveTech("retrocausality")
- // tech.giveTech("causality bots")
+ // b.giveGuns("grenades")
+ // tech.giveTech("neutron bomb")
+ // tech.giveTech("vacuum bomb")
// tech.giveTech("causality bombs")
// for (let i = 0; i < 2; i++) tech.giveTech("refractory metal")
// tech.giveTech("antiscience")
diff --git a/js/mob.js b/js/mob.js
index 6a9e31d..1b1c331 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -1167,7 +1167,7 @@ const mobs = {
}
}
if (tech.cloakDuplication && !this.isBoss) {
- tech.cloakDuplication -= 0.01
+ tech.cloakDuplication -= 0.02
powerUps.setDupChance(); //needed after adjusting duplication chance
}
} else if (tech.isShieldAmmo && this.shield && !this.isExtraShield) {
diff --git a/js/spawn.js b/js/spawn.js
index 3372f2e..d1c36f6 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -2379,10 +2379,10 @@ const spawn = {
this.checkStatus();
};
},
- pulsarBoss(x, y, radius = 90) {
+ pulsarBoss(x, y, radius = 90, isNonCollide = false) {
mobs.spawn(x, y, 3, radius, "#a0f");
let me = mob[mob.length - 1];
-
+ if (isNonCollide) me.collisionFilter.mask = cat.bullet | cat.player
setTimeout(() => { //fix mob in place, but allow rotation
me.constraint = Constraint.create({
pointA: {
diff --git a/js/tech.js b/js/tech.js
index 14ea775..81b36f7 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -234,18 +234,21 @@
return dmg * tech.slowFire * tech.aimDamage
},
duplicationChance() {
- return Math.max(0, (tech.isPowerUpsVanish ? 0.13 : 0) + (tech.isStimulatedEmission ? 0.17 : 0) + tech.cancelCount * 0.045 + tech.duplicateChance + m.duplicateChance + tech.wormDuplicate + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0))
+ return Math.max(0, (tech.isPowerUpsVanish ? 0.12 : 0) + (tech.isStimulatedEmission ? 0.15 : 0) + tech.cancelCount * 0.04 + tech.duplicateChance + m.duplicateChance + tech.wormDuplicate + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.45 : 0))
},
isScaleMobsWithDuplication: false,
maxDuplicationEvent() {
- if (tech.is100Duplicate && tech.duplicationChance() > 0.99) {
- tech.is100Duplicate = false
- const range = 500
+ if (tech.is111Duplicate && tech.duplicationChance() > 1.11) {
+ tech.is111Duplicate = false
+ const range = 1300
tech.isScaleMobsWithDuplication = true
- for (let i = 0, len = 8; i < len; i++) {
+ for (let i = 0, len = 9; i < len; i++) {
const angle = 2 * Math.PI * i / len
spawn.randomLevelBoss(m.pos.x + range * Math.cos(angle), m.pos.y + range * Math.sin(angle), spawn.nonCollideBossList);
}
+ spawn.historyBoss(0, 0)
+ spawn.pulsarBoss(level.exit.x, level.exit.y, 70, true)
+ spawn.blockBoss(level.enter.x, level.enter.y)
tech.isScaleMobsWithDuplication = false
}
},
@@ -2850,15 +2853,15 @@
},
{
name: "weak anthropic principle",
- description: "after anthropic principle prevents your death
add 50% duplication chance for that level",
+ description: "after anthropic principle prevents your death
add 45% duplication chance for that level",
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
- return tech.isDeathAvoid && tech.duplicationChance() < 0.66
+ return tech.isDeathAvoid
},
- requires: "anthropic principle, below 66% duplication chance",
+ requires: "anthropic principle",
effect() {
tech.isAnthropicTech = true
powerUps.setDupChance(); //needed after adjusting duplication chance
@@ -3154,7 +3157,7 @@
},
{
name: "replication",
- description: "10% chance to duplicate spawned power ups
+30% JUNK to the potential tech pool",
+ description: "10% chance to duplicate spawned power ups
+40% JUNK to the potential tech pool",
maxCount: 9,
count: 0,
frequency: 1,
@@ -3167,7 +3170,7 @@
tech.duplicateChance += 0.1
powerUps.setDupChance(); //needed after adjusting duplication chance
if (!build.isExperimentSelection) simulation.circleFlare(0.1);
- this.refundAmount += tech.addJunkTechToPool(0.3)
+ this.refundAmount += tech.addJunkTechToPool(0.4)
},
refundAmount: 0,
remove() {
@@ -3181,7 +3184,7 @@
},
{
name: "stimulated emission",
- description: "17% chance to duplicate spawned power ups
but, after a collision eject 1 tech",
+ description: "15% chance to duplicate spawned power ups
but, after a collision eject 1 tech",
maxCount: 1,
count: 0,
frequency: 1,
@@ -3192,8 +3195,8 @@
requires: "below 100% duplication chance",
effect: () => {
tech.isStimulatedEmission = true
- powerUps.setDupChance(0.17); //needed after adjusting duplication chance
- if (!build.isExperimentSelection) simulation.circleFlare(0.17);
+ powerUps.setDupChance(); //needed after adjusting duplication chance
+ if (!build.isExperimentSelection) simulation.circleFlare(0.15);
},
remove() {
tech.isStimulatedEmission = false
@@ -3202,7 +3205,7 @@
},
{
name: "metastability",
- description: "13% chance to duplicate spawned power ups
duplicates explode with a 3 second half-life ",
+ description: "12% chance to duplicate spawned power ups
duplicates explode with a 3 second half-life ",
maxCount: 1,
count: 0,
frequency: 1,
@@ -3214,7 +3217,7 @@
effect: () => {
tech.isPowerUpsVanish = true
powerUps.setDupChance(); //needed after adjusting duplication chance
- if (!build.isExperimentSelection) simulation.circleFlare(0.13);
+ if (!build.isExperimentSelection) simulation.circleFlare(0.12);
},
remove() {
tech.isPowerUpsVanish = false
@@ -3223,7 +3226,7 @@
},
{
name: "futures exchange",
- description: "clicking × to cancel a field, tech, or gun
adds 4.5% power up duplication chance",
+ description: "clicking × to cancel a field, tech, or gun
adds 4% power up duplication chance",
maxCount: 1,
count: 0,
frequency: 1,
@@ -3297,21 +3300,21 @@
},
{
name: "apomixis",
- description: `when you reach 100% duplication
spawn 8 bosses with 100% more health`,
+ description: `when you reach 111% duplication
spawn 11 bosses with 111% more health`,
maxCount: 1,
count: 0,
- frequency: 2,
- frequencyDefault: 2,
+ frequency: 10,
+ frequencyDefault: 10,
allowed() {
- return tech.duplicationChance() > 0.33
+ return tech.duplicationChance() > 0.99
},
requires: "duplication chance above 33%",
effect() {
- tech.is100Duplicate = true;
+ tech.is111Duplicate = true;
tech.maxDuplicationEvent()
},
remove() {
- tech.is100Duplicate = false;
+ tech.is111Duplicate = false;
}
},
{
@@ -3381,10 +3384,8 @@
effect: () => {
powerUps.research.changeRerolls(-2)
simulation.makeTextLog(`m.research -= 2
${powerUps.research.count}`)
- const chanceStore = tech.duplicateChance
- tech.duplicateChance = (tech.isStimulatedEmission ? 0.2 : 0) + tech.cancelCount * 0.045 + m.duplicateChance + tech.duplicateChance * 2 //increase duplication chance to simulate doubling all 3 sources of duplication chance
- powerUps.spawn(m.pos.x, m.pos.y, "tech");
- tech.duplicateChance = chanceStore
+ powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
+ if (Math.random() < tech.duplicationChance() * 2) powerUps.directSpawn(m.pos.x + 10, m.pos.y + 5, "tech");
},
remove() {}
},
@@ -5778,9 +5779,9 @@
frequency: 3,
frequencyDefault: 3,
allowed() {
- return (m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" || m.fieldUpgrades[m.fieldMode].name === "negative mass") && (build.isExperimentSelection || powerUps.research.count > 3)
+ return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" || m.fieldUpgrades[m.fieldMode].name === "negative mass") && (build.isExperimentSelection || powerUps.research.count > 3)
},
- requires: "perfect diamagnetism or negative mass",
+ requires: "perfect diamagnetism, negative mass, pilot wave",
effect() {
tech.isFieldHarmReduction = true
for (let i = 0; i < 2; i++) {
@@ -6266,7 +6267,7 @@
// },
{
name: "retrocausality",
- description: "time dilation uses energy to rewind your
health, velocity, and position up to 10 s",
+ description: "time dilation uses energy to rewind your
health, velocity, and position up to 10 s",
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -6316,9 +6317,9 @@
frequency: 3,
frequencyDefault: 3,
allowed() {
- return m.fieldUpgrades[m.fieldMode].name === "time dilation" && (build.isExperimentSelection || powerUps.research.count > 2)
+ return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "time dilation") && (build.isExperimentSelection || powerUps.research.count > 2)
},
- requires: "time dilation",
+ requires: "time dilation, pilot wave",
effect() {
tech.isFastTime = true
m.setMovement();
@@ -6357,7 +6358,7 @@
},
{
name: "no-cloning theorem",
- description: `38% chance to duplicate spawned power ups
after a mob dies, lose 1% duplication chance`,
+ description: `40% chance to duplicate spawned power ups
after a mob dies, lose 2% duplication chance`,
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -6368,9 +6369,9 @@
},
requires: "cloaking, wormhole or time dilation and below 100% duplication chance",
effect() {
- tech.cloakDuplication = 0.38
+ tech.cloakDuplication = 0.4
powerUps.setDupChance(); //needed after adjusting duplication chance
- if (!build.isExperimentSelection) simulation.circleFlare(0.38);
+ if (!build.isExperimentSelection) simulation.circleFlare(0.4);
},
remove() {
tech.cloakDuplication = 0
@@ -6607,20 +6608,20 @@
},
{
name: "virtual particles",
- description: `use ${powerUps.orb.research(4)}to exploit your wormhole for a
14% chance to duplicate spawned power ups`,
+ description: `use ${powerUps.orb.research(4)}to exploit your wormhole for a
13% chance to duplicate spawned power ups`,
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
- return m.fieldUpgrades[m.fieldMode].name === "wormhole" && (build.isExperimentSelection || powerUps.research.count > 3) && tech.duplicationChance() < 1
+ return m.fieldUpgrades[m.fieldMode].name === "wormhole" && (build.isExperimentSelection || powerUps.research.count > 3)
},
- requires: "wormhole, below 100% duplication chance",
+ requires: "wormhole",
effect() {
- tech.wormDuplicate = 0.14
+ tech.wormDuplicate = 0.13
powerUps.setDupChance(); //needed after adjusting duplication chance
- if (!build.isExperimentSelection) simulation.circleFlare(0.14);
+ if (!build.isExperimentSelection) simulation.circleFlare(0.13);
for (let i = 0; i < 4; i++) {
if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
}
@@ -8727,7 +8728,7 @@
isGunSwitchField: null,
isNeedleShieldPierce: null,
isDuplicateBoss: null,
- is100Duplicate: null,
+ is111Duplicate: null,
isDynamoBotUpgrade: null,
isBlockPowerUps: null,
isBlockHarm: null,
diff --git a/todo.txt b/todo.txt
index 9f0a443..1177c6b 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,11 +1,17 @@
******************************************************** NEXT PATCH **************************************************
-number of undefined tech needed to get lore is now lower at higher difficulty modes
+grenades display their trajectory, to help you aim
+ I'm might get rid of it, but for now we'll try it out
-bug fixes
+several duplication tech give slightly lower duplication chance
+strange attractor now properly includes all your tech in duplication chance (it wasn't updated for recent duplication tech)
******************************************************** TODO ********************************************************
+give all duplicated power ups a half life that scales with the duplication chance
+ metastability reduces the half life
+ how to communicate the half-life?
+
tech: after bullets hit a mob, the mob takes 1% more damage
this.damageReduction *= 1.01