diff --git a/js/bullet.js b/js/bullet.js
index 8417c98..ae94732 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -1450,7 +1450,7 @@ const b = {
}
if (tech.isFoamBall) {
const radius = 5 + 8 * Math.random()
- const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 }
+ const velocity = { x: Math.max(0.5, 2 - radius * 0.1), y: 0 }
for (let i = 0, len = 2 * this.mass; i < len; i++) {
b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius)
}
@@ -1732,7 +1732,7 @@ const b = {
if (tech.isFoamBall) {
const radius = 5 + 8 * Math.random()
- const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 }
+ const velocity = { x: Math.max(0.5, 2 - radius * 0.1), y: 0 }
for (let i = 0, len = 2 * this.mass; i < len; i++) {
b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius)
}
@@ -3707,6 +3707,10 @@ const b = {
}
}
this.targetVertex = bestVertex
+ Matter.Body.setVelocity(this, {
+ x: 0,
+ y: 0
+ });
}
},
onEnd() {},
@@ -3778,6 +3782,10 @@ const b = {
} else if (this.target !== null) { //look for a new target
this.collisionFilter.category = cat.bullet;
this.collisionFilter.mask = cat.mob //| cat.mobShield //cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
+ Matter.Body.setVelocity(this, {
+ x: this.target.velocity.x,
+ y: this.target.velocity.y
+ });
if (tech.isSpawnBulletsOnDeath && bullet.length < 180 && !this.target.isMobBullet) {
let targets = []
for (let i = 0, len = mob.length; i < len; i++) {
@@ -5645,7 +5653,8 @@ const b = {
}
if (tech.isFoamBall) {
const radius = 5 + 8 * Math.random()
- const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 }
+ // const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 }
+ const velocity = { x: Math.max(0.5, 2 - radius * 0.1), y: 0 }
for (let i = 0, len = 6 * this.mass; i < len; i++) {
b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius)
}
@@ -5693,7 +5702,7 @@ const b = {
}
if (tech.isFoamBall) {
const radius = 5 + 8 * Math.random()
- const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 }
+ const velocity = { x: Math.max(0.5, 2 - radius * 0.1), y: 0 }
for (let i = 0, len = 6 * this.mass; i < len; i++) {
b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius)
}
@@ -5745,7 +5754,7 @@ const b = {
}
if (tech.isFoamBall) {
const radius = 5 + 8 * Math.random()
- const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 }
+ const velocity = { x: Math.max(0.5, 2 - radius * 0.1), y: 0 }
for (let i = 0, len = 6 * this.mass; i < len; i++) {
b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius)
}
diff --git a/js/index.js b/js/index.js
index 6045d04..651329c 100644
--- a/js/index.js
+++ b/js/index.js
@@ -224,10 +224,6 @@ window.onresize = () => {
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (!tech.tech[i].link) tech.tech[i].link = `${tech.tech[i].name}`
}
-
-
-//
effective defense: ${(1-simulation.dmgScale*m.harmReduction()).toPrecision(3)}
-//
effective damage: ${(tech.damageFromTech() * m.dmgScale).toPrecision(3)}
const build = {
pauseGrid() {
//left side
diff --git a/js/level.js b/js/level.js
index 4a48aa7..432ff4b 100644
--- a/js/level.js
+++ b/js/level.js
@@ -16,7 +16,7 @@ const level = {
start() {
if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.enableConstructMode() //used to build maps in testing mode
- // level.difficultyIncrease(8 * 4) //30 is near max on hard //60 is near max on why
+ // level.difficultyIncrease(4 * 4) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true
// m.maxHealth = m.health = 100
// powerUps.research.changeRerolls(100000)
@@ -24,19 +24,19 @@ const level = {
// powerUps.research.changeRerolls(100)
// tech.tech[297].frequency = 100
// b.guns[0].ammo = 10000
- // m.setField("metamaterial cloaking") //molecular assembler time dilation perfect diamagnetism metamaterial cloaking wormhole
- // b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 matter wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
- // tech.giveTech("robotics")
- // tech.giveTech("CPT symmetry");
- // tech.giveTech("lens");
- // tech.giveTech("robotics")
+ // m.setField("metamaterial cloaking") //molecular assembler time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass
+ // b.giveGuns("nail gun") //0 nail gun 1 shotgun 2 super balls 3 matter wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
+ // tech.giveTech("dynamic equilibrium")
+ // tech.giveTech("quantum eraser");
+ // tech.giveTech("patch");
+ // tech.giveTech("polyurethane foam")
// for (let i = 0; i < 100; ++i) tech.giveTech("nail-bot")
// for (let i = 0; i < 1; ++i) tech.giveTech("electric generator")
// for (let i = 0; i < 9; i++) tech.giveTech("compound lens")
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "research");
- // spawn.starter(1900, -500)
- // spawn.laserTargetingBoss(1900, -500)
+ // spawn.starter(1900, -500, 100)
+ // spawn.snakeBoss(1900, -500)
// for (let i = 0; i < 10; ++i) spawn.grower(1900, -500)
// level.testing(); //not in rotation, used for testing
// for (let i = 0; i < 7; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research");
diff --git a/js/player.js b/js/player.js
index 262fe1a..d404f1b 100644
--- a/js/player.js
+++ b/js/player.js
@@ -363,11 +363,8 @@ const m = {
m.health = m.health * (1 + 0.5 * (Math.random() - 0.5))
if (m.health > 1) m.health = 1;
m.displayHealth();
-
//randomize field
m.setField(Math.ceil(Math.random() * (m.fieldUpgrades.length - 1)))
-
-
//removes guns and ammo
b.inventory = [];
b.activeGun = null;
@@ -726,7 +723,11 @@ const m = {
document.getElementById("dmg").style.opacity = 0.1 + Math.min(0.6, dmg * 4);
}
- if (dmg > 0.06 / m.holdingMassScale) m.drop(); //drop block if holding
+ if (dmg > 0.03) {
+ m.lastHit = dmg;
+ if (dmg > 0.06 / m.holdingMassScale) m.drop(); //drop block if holding // m.holdingMassScale = 0.5 for most fields
+ if (m.isCloak) m.fireCDcycle = m.cycle //forced exit cloak
+ }
const normalFPS = function() {
if (m.defaultFPSCycle < m.cycle) { //back to default values
simulation.fpsCap = simulation.fpsCapDefault
@@ -908,6 +909,7 @@ const m = {
fieldShieldingScale: 1,
// fieldDamage: 1,
isSneakAttack: false,
+ lastHit: 0, //stores value of last damage player took above a threshold, in m.damage
sneakAttackCycle: 0,
enterCloakCycle: 0,
duplicateChance: 0,
@@ -950,6 +952,7 @@ const m = {
m.fieldShieldingScale = 1;
m.fieldBlockCD = 10;
m.fieldHarmReduction = 1;
+ m.lastHit = 0
m.isSneakAttack = false
m.duplicateChance = 0
powerUps.setDupChance();
@@ -1015,7 +1018,7 @@ const m = {
m.regenEnergy();
const xOff = m.pos.x - m.radius * m.maxEnergy
const yOff = m.pos.y - 50
- ctx.fillStyle = "rgba(0, 0, 0, 0.3)" //
+ ctx.fillStyle = "rgba(0, 0, 0, 0.2)" //
ctx.fillRect(xOff, yOff, 60 * m.maxEnergy, 10);
ctx.fillStyle = "#fff" //m.cycle > m.lastKillCycle + 300 ? "#000" : "#fff" //"#fff";
ctx.fillRect(xOff, yOff, 60 * m.energy, 10);
@@ -2750,39 +2753,27 @@ const m = {
m.fieldFire = true;
m.fieldMeterColor = "#333";
m.eyeFillColor = m.fieldMeterColor
- // m.eyeFillColor = '#333'
m.fieldPhase = 0;
m.isCloak = false
- // m.fieldDamage = 2.46 // 1 + 146/100
m.fieldDrawRadius = 0
m.isSneakAttack = true;
- // m.sneakAttackCharge = 0;
m.sneakAttackCycle = 0;
m.enterCloakCycle = 0;
- const drawRadius = 800
m.drawCloak = function() {
m.fieldPhase += 0.007
const wiggle = 0.15 * Math.sin(m.fieldPhase * 0.5)
ctx.beginPath();
ctx.ellipse(m.pos.x, m.pos.y, m.fieldDrawRadius * (1 - wiggle), m.fieldDrawRadius * (1 + wiggle), m.fieldPhase, 0, 2 * Math.PI);
- // if (m.fireCDcycle > m.cycle && (input.field)) {}
ctx.fillStyle = "#fff"
ctx.lineWidth = 2;
ctx.strokeStyle = "#000"
ctx.stroke()
- // ctx.fillStyle = "#fff" //`rgba(0,0,0,${0.5+0.5*m.energy})`;
ctx.globalCompositeOperation = "destination-in";
ctx.fill();
ctx.globalCompositeOperation = "source-over";
ctx.clip();
}
m.hold = function() {
- // if (m.isCloak) {
- // if (m.sneakAttackCharge < 120) m.sneakAttackCharge += 0.5
- // } else {
- // if (m.sneakAttackCharge > 0) m.sneakAttackCharge--
- // }
-
if (m.isHolding) {
m.drawHold(m.holdingTarget);
m.holding();
@@ -2801,7 +2792,31 @@ const m = {
if (!m.isCloak) {
m.isCloak = true //enter cloak
m.enterCloakCycle = m.cycle
- // console.log(m.enterCloakCycle)
+ if (tech.isCloakHealLastHit && m.lastHit > 0) {
+ const heal = Math.min(0.75 * m.lastHit, m.energy)
+ m.energy -= heal
+ simulation.drawList.push({ //add dmg to draw queue
+ x: m.pos.x,
+ y: m.pos.y,
+ radius: Math.sqrt(heal) * 200,
+ color: "rgba(0,255,200,0.6)",
+ time: 16
+ });
+ m.addHealth(heal); //heal from last hit
+ // if (tech.isEnergyHealth) {
+ // simulation.drawList.push({ //add dmg to draw queue
+ // x: m.pos.x,
+ // y: m.pos.y,
+ // radius: Math.sqrt(heal) * 200,
+ // color: "#0ad", //simulation.mobDmgColor
+ // time: 16
+ // });
+ // m.energy += heal
+ // } else {
+ // }
+ m.lastHit = 0
+ // simulation.makeTextLog(`m.health += ${(heal).toFixed(3)}`) //
${m.health.toFixed(3)}
+ }
if (tech.isIntangible) {
for (let i = 0; i < bullet.length; i++) {
if (bullet[i].botType && bullet[i].botType !== "orbit") bullet[i].collisionFilter.mask = cat.map | cat.bullet | cat.mobBullet | cat.mobShield
@@ -2841,12 +2856,12 @@ const m = {
}
}
if (m.isCloak) {
- this.fieldRange = this.fieldRange * 0.9 + 0.1 * drawRadius
- m.fieldDrawRadius = this.fieldRange * 0.88 //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy));
+ m.fieldRange = m.fieldRange * 0.9 + 80
+ m.fieldDrawRadius = m.fieldRange * 0.88 //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy));
m.drawCloak()
- } else if (this.fieldRange < 4000) {
- this.fieldRange += 50
- m.fieldDrawRadius = this.fieldRange //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy));
+ } else if (m.fieldRange < 4000) {
+ m.fieldRange += 50
+ m.fieldDrawRadius = m.fieldRange //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy));
m.drawCloak()
}
if (tech.isIntangible) {
diff --git a/js/simulation.js b/js/simulation.js
index d2fc0af..7f483bf 100644
--- a/js/simulation.js
+++ b/js/simulation.js
@@ -980,7 +980,6 @@ const simulation = {
}
if (tech.isQuantumEraser) {
- // tech.quantumEraserCount = 0
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].isDropPowerUp && mob[i].alive) tech.quantumEraserCount++
}
diff --git a/js/spawn.js b/js/spawn.js
index bd19022..6c63036 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -48,7 +48,13 @@ const spawn = {
},
quantumEraserCheck() { //remove mobs from tech: quantum eraser
if (tech.isQuantumEraser && tech.quantumEraserCount > 0) {
- for (let i = 0, len = mob.length; i < len; i++) {
+
+ //start at a random location in array
+ const randomMiddle = Math.floor(mob.length * Math.random())
+ let i = randomMiddle
+ for (let j = 0; j < mob.length; j++) {
+ i++
+ if (i > mob.length - 1) i = 0
if (mob[i].isDropPowerUp && mob[i].alive) { //&& !mob[i].isBoss
if (mob[i].isFinalBoss) {
tech.quantumEraserCount = 0;
@@ -86,6 +92,47 @@ const spawn = {
if (tech.quantumEraserCount < 1) break
}
}
+
+
+
+ // for (let i = 0, len = mob.length; i < len; i++) {
+ // if (mob[i].isDropPowerUp && mob[i].alive) { //&& !mob[i].isBoss
+ // if (mob[i].isFinalBoss) {
+ // tech.quantumEraserCount = 0;
+ // return
+ // } else {
+ // tech.isQuantumEraserDuplication = true
+ // mob[i].death()
+ // tech.isQuantumEraserDuplication = false
+ // }
+ // //graphics
+ // const color = 'rgba(255,255,255, 0.8)'
+ // simulation.drawList.push({
+ // x: mob[i].position.x,
+ // y: mob[i].position.y,
+ // radius: mob[i].radius * 2,
+ // color: color, //"rgba(0,0,0,0.6)",
+ // time: 60
+ // });
+ // simulation.drawList.push({
+ // x: mob[i].position.x,
+ // y: mob[i].position.y,
+ // radius: mob[i].radius * 1,
+ // color: color, //"rgba(0,0,0,0.85)",
+ // time: 90
+ // });
+ // simulation.drawList.push({
+ // x: mob[i].position.x,
+ // y: mob[i].position.y,
+ // radius: mob[i].radius * 0.5,
+ // color: color, //"rgb(0,0,0)",
+ // time: 120
+ // });
+ // tech.quantumEraserCount--
+ // simulation.makeTextLog(`tech.quantumEraserCount = ${tech.quantumEraserCount}`)
+ // if (tech.quantumEraserCount < 1) break
+ // }
+ // }
}
},
randomMob(x, y, chance = 1) {
@@ -2786,6 +2833,7 @@ const spawn = {
mobs.spawn(x, y, 3, radius, "rgb(0,235,255)");
let me = mob[mob.length - 1];
me.isBoss = true;
+ me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
@@ -2808,11 +2856,29 @@ const spawn = {
me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
- me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.targetingCount = 0;
me.targetingTime = 60 - Math.min(58, 3 * simulation.difficulty)
me.do = function() {
- // this.armor();
+
+ // //wings
+ // const wing = (simulation.cycle % 9) > 4 ? this.vertices[0] : this.vertices[2] //Vector.add(this.position, { x: 100, y: 0 })
+ // const radius = 200
+ // //draw
+ // ctx.beginPath();
+ // ctx.arc(wing.x, wing.y, radius, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay
+ // ctx.fillStyle = "rgba(0,235,255,0.3)";
+ // ctx.fill();
+ // //check damage
+ // const hitPlayer = Matter.Query.ray([player], this.position, wing, radius)
+ // if (hitPlayer.length && m.immuneCycle < m.cycle) {
+ // m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
+ // m.damage(0.02 * simulation.dmgScale);
+ // }
+
+
+
+
+
this.seePlayerByLookingAt();
this.checkStatus();
this.attraction();
@@ -5566,7 +5632,7 @@ const spawn = {
mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, color1); //"rgb(55,170,170)"
let me = mob[mob.length - 1];
me.isBoss = true;
- me.accelMag = 0.0003 + 0.0002 * Math.sqrt(simulation.accelScale)
+ me.accelMag = 0.0004 + 0.0002 * Math.sqrt(simulation.accelScale)
me.memory = 250;
me.laserRange = 500;
Matter.Body.setDensity(me, 0.0022 + 0.00022 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
@@ -5576,13 +5642,12 @@ const spawn = {
me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
- for (let i = 0; i < mob.length; i++) { //wake up tail mobs
- if (mob[i].isSnakeTail && mob[i].alive) {
- mob[i].isSnakeTail = false;
- mob[i].do = mob[i].doActive
- // mob[i].removeConsBB();
+ me.onDeath = function() {
+ powerUps.spawnBossPowerUp(this.position.x, this.position.y)
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (this.id === mob[i].snakeHeadID && mob[i].alive) mob[i].death()
}
- }
+ };
};
me.canFire = false;
me.closestVertex1 = 0;
@@ -5660,7 +5725,7 @@ const spawn = {
spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), i === 0 ? 25 : 20);
// mag -= 5
// spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 20);
- if (i === 0) mob[mob.length - 1].snakeHeadID = me.id
+ if (i < 3) mob[mob.length - 1].snakeHeadID = me.id
mob[mob.length - 1].previousTailID = previousTailID
previousTailID = mob[mob.length - 1].id
}
@@ -5703,9 +5768,9 @@ const spawn = {
mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, color1); //"rgb(55,170,170)"
let me = mob[mob.length - 1];
me.isBoss = true;
- me.accelMag = 0.00045 + 0.0002 * Math.sqrt(simulation.accelScale)
+ me.accelMag = 0.0009 + 0.0002 * Math.sqrt(simulation.accelScale)
me.memory = 250;
- me.laserRange = 500;
+ me.laserRange = 400;
Matter.Body.setDensity(me, 0.00165 + 0.00011 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.startingDamageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0
@@ -5713,6 +5778,9 @@ const spawn = {
me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (this.id === mob[i].snakeHeadID && mob[i].alive) mob[i].death()
+ }
};
me.do = function() {
this.seePlayerByHistory()
@@ -5738,7 +5806,7 @@ const spawn = {
angle -= 0.15 + i * 0.008
mag -= (i < 2) ? -15 : 5
spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), i === 0 ? 25 : 20);
- if (i === 0) mob[mob.length - 1].snakeHeadID = me.id
+ if (i < 3) mob[mob.length - 1].snakeHeadID = me.id
mob[mob.length - 1].previousTailID = previousTailID
previousTailID = mob[mob.length - 1].id
}
@@ -5775,11 +5843,13 @@ const spawn = {
mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)");
let me = mob[mob.length - 1];
me.collisionFilter.mask = cat.bullet | cat.player | cat.mob //| cat.body
- me.accelMag = 0.0007 * simulation.accelScale;
+ me.damageReduction = 0.2
+ Matter.Body.setDensity(me, 0.005); //normal is 0.001
+
+ // me.accelMag = 0.0007 * simulation.accelScale;
me.leaveBody = Math.random() < 0.33 ? true : false;
me.showHealthBar = false;
me.isDropPowerUp = false;
- Matter.Body.setDensity(me, 0.005); //normal is 0.001
me.frictionAir = 0.015;
me.isSnakeTail = true;
me.stroke = "transparent"
@@ -5792,16 +5862,16 @@ const spawn = {
mob[i].damageReduction = mob[i].startingDamageReduction
}
}
- }, 150);
+ }, 500);
};
me.do = function() {
this.checkStatus();
};
- me.doActive = function() {
- this.checkStatus();
- this.alwaysSeePlayer();
- this.attraction();
- };
+ // me.doActive = function() {
+ // this.checkStatus();
+ // this.alwaysSeePlayer();
+ // this.attraction();
+ // };
},
tetherBoss(x, y, constraint, radius = 90) {
// constrained mob boss for the towers level
diff --git a/js/tech.js b/js/tech.js
index 14832fc..7e6583f 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -239,7 +239,6 @@ const tech = {
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
if (tech.isDamageForGuns) dmg *= 1 + 0.13 * b.inventory.length
if (tech.isLowHealthDmg) dmg *= 1 + Math.max(0, 1 - m.health) * 0.5
- if (tech.isHarmDamage && m.lastHarmCycle + 600 > m.cycle) dmg *= 3;
if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.25
if (tech.isAcidDmg && m.health > 1) dmg *= 1.35;
if (tech.isRerollDamage) dmg *= 1 + 0.038 * powerUps.research.count
@@ -251,10 +250,10 @@ const tech = {
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2
if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.66, player.speed * 0.0165)
if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 1.6
- // if (m.isSneakAttack && m.cycle > m.lastKillCycle + 240) dmg *= tech.sneakAttackDmg
if (m.isSneakAttack && m.sneakAttackCycle + Math.min(120, 0.5 * (m.cycle - m.enterCloakCycle)) > m.cycle) dmg *= tech.sneakAttackDmg
- // if (m.isSneakAttack && m.sneakAttackCharge > 0) dmg *= tech.sneakAttackDmg
if (tech.isAxion && tech.isHarmMACHO) dmg *= 2 - m.harmReduction()
+ if (tech.isHarmDamage && m.lastHarmCycle + 600 > m.cycle) dmg *= 3;
+ if (tech.isLastHitDamage && m.lastHit) dmg *= 1 + 5 * m.lastHit // if (!simulation.paused) m.lastHit = 0
return dmg * tech.slowFire * tech.aimDamage
},
duplicationChance() {
@@ -2115,24 +2114,6 @@ const tech = {
tech.isHarmArmor = false;
}
},
- // {
- // name: "radiative equilibrium",
- // description: "for 10 seconds after receiving defense
increase damage by 200%",
- // maxCount: 1,
- // count: 0,
- // frequency: 1,
- // frequencyDefault: 1,
- // allowed() {
- // return true
- // },
- // requires: "",
- // effect() {
- // tech.isHarmDamage = true;
- // },
- // remove() {
- // tech.isHarmDamage = false;
- // }
- // },
{
name: "CPT symmetry",
// description: "charge, parity, and time invert to undo defense
rewind (1.5—5) seconds for (66—220) energy",
@@ -2272,42 +2253,42 @@ const tech = {
}
}
},
- {
- name: "weak interaction",
- description: "for each unused power up at the end of a level
+10 maximum energy", // (up to 51 health per level)",
- maxCount: 1,
- count: 0,
- frequency: 1,
- frequencyDefault: 1,
- allowed() {
- return !tech.isDroneGrab
- },
- requires: "not delivery drone",
- effect() {
- tech.isExtraMaxEnergy = true; //tracked by tech.extraMaxHealth
- },
- remove() {
- tech.isExtraMaxEnergy = false;
- }
- },
- {
- name: "electroweak interaction",
- description: "unused power ups at the end of a level
are still activated (selections are random)",
- maxCount: 1,
- count: 0,
- frequency: 2,
- frequencyDefault: 2,
- allowed() {
- return tech.isExtraMaxEnergy
- },
- requires: "weak interaction",
- effect() {
- tech.isEndLevelPowerUp = true;
- },
- remove() {
- tech.isEndLevelPowerUp = false;
- }
- },
+ // {
+ // name: "weak interaction",
+ // description: "for each unused power up at the end of a level
+10 maximum energy", // (up to 51 health per level)",
+ // maxCount: 1,
+ // count: 0,
+ // frequency: 1,
+ // frequencyDefault: 1,
+ // allowed() {
+ // return !tech.isDroneGrab
+ // },
+ // requires: "not delivery drone",
+ // effect() {
+ // tech.isExtraMaxEnergy = true; //tracked by tech.extraMaxHealth
+ // },
+ // remove() {
+ // tech.isExtraMaxEnergy = false;
+ // }
+ // },
+ // {
+ // name: "electroweak interaction",
+ // description: "unused power ups at the end of a level
are still activated (selections are random)",
+ // maxCount: 1,
+ // count: 0,
+ // frequency: 2,
+ // frequencyDefault: 2,
+ // allowed() {
+ // return tech.isExtraMaxEnergy
+ // },
+ // requires: "weak interaction",
+ // effect() {
+ // tech.isEndLevelPowerUp = true;
+ // },
+ // remove() {
+ // tech.isEndLevelPowerUp = false;
+ // }
+ // },
{
name: "electronegativity",
description: "+1% damage per 8 stored energy",
@@ -4107,7 +4088,7 @@ const tech = {
{
name: "spin-statistics",
link: `spin-statistics`,
- description: "invulnerable while firing the shotgun
shotgun has 50% fewer shots",
+ description: "after firing the shotgun you are invulnerable
shotgun has 50% fewer shots",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -6665,8 +6646,8 @@ const tech = {
isFieldTech: true,
maxCount: 1,
count: 0,
- frequency: 1,
- frequencyDefault: 1,
+ frequency: 2,
+ frequencyDefault: 2,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "negative mass"
},
@@ -6678,6 +6659,26 @@ const tech = {
tech.isHarmDamage = false;
}
},
+ {
+ name: "dynamic equilibrium",
+ descriptionFunction() { return `increase damage by 5%
of your last ${tech.isEnergyHealth ? "energy" : "health"} loss` },
+ // description: `increase damage by 500%
of your last health loss`,
+ isFieldTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "negative mass" || m.fieldUpgrades[m.fieldMode].name === "standing wave") && !tech.isCloakHealLastHit
+ },
+ requires: "negative mass, pilot wave, not patch",
+ effect() {
+ tech.isLastHitDamage = true;
+ },
+ remove() {
+ tech.isLastHitDamage = false;
+ }
+ },
{
name: "neutronium",
description: `move and jump 25% slower
if your field is active +90% defense`,
@@ -7347,6 +7348,26 @@ const tech = {
}
}
},
+ {
+ name: "patch",
+ link: `patch`,
+ description: "after cloaking recover 75% of your
last health loss using that much energy",
+ isFieldTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return m.fieldUpgrades[m.fieldMode].name === "metamaterial cloaking" && !tech.isLastHitDamage && !tech.isEnergyHealth
+ },
+ requires: "metamaterial cloaking, not dynamic equilibrium, mass-energy",
+ effect() {
+ tech.isCloakHealLastHit = true;
+ },
+ remove() {
+ tech.isCloakHealLastHit = false;
+ }
+ },
{
name: "dazzler",
link: `dazzler`,
@@ -10528,5 +10549,7 @@ const tech = {
isLaserLens: null,
laserCrit: null,
isSporeColony: null,
- isExtraBotOption: null
+ isExtraBotOption: null,
+ isLastHitDamage: null,
+ isCloakHealLastHit: null
}
\ No newline at end of file
diff --git a/style.css b/style.css
index 0eae605..18a785a 100644
--- a/style.css
+++ b/style.css
@@ -532,6 +532,8 @@ summary {
transition: opacity 0.25s;
pointer-events: none;
user-select: none;
+ /* white-space: pre;
+ font-family: 'Menlo', 'Monaco', monospace; */
}
/* color for in game console output */
diff --git a/todo.txt b/todo.txt
index e82a0ca..536ca39 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,43 +1,62 @@
******************************************************** NEXT PATCH **************************************************
-tech: electric generator - deflecting mobs generates energy for molecular assembler
-tech: homeostasis - for each health below 100 +0.8% defense
-tech: compound lens - +77% laser lens damage, +10° lens arc
+field tech: patch - after cloaking recover 75% of last health lost using that much energy
+ taking damage now forces decloaking
+field tech: dynamic equilibrium - increase damage by 5% the value of your last health loss
-tech: robotics - 2 random bots, power up choices include a bot tech option
-tech: open-source - 3 random bots, 4x bot tech frequency
- renamed from previous robotics tech
-slightly buffed all bot upgrades
+foam has less velocity after a mob it's stuck to dies
+snakeBoss becomes vulnerable if you remove any of the first 3 body segments
+ body segments have more health
-+9% iceIX damage
-catabolism uses energy instead of health if you have mass-energy
-optical amplifier laser tech options include laser-bot
-rule 90 and rule 30 looks better on more browsers, I hope
+bug fix: quantum eraser now removes mobs in a more random order
+ it used to have a too low chance to remove bosses
*********************************************************** TODO *****************************************************
+labs room:
+ low gravity zone
+ a button that toggles it on/off
+
+boss mechanics
+ bullets hit player and stay attached for 4-5 seconds, slowing player
+ hopperBullets?
+ black hole sucker effect on tail
+ flickering wings
+ draw pair of circles at 2 different locations, like beetle wings flapping
+ draw as ellipse
+ damage player if caught in wings
+
+tech: ricochet after nails do damage, the nail fires at a different nearby mobs
+ can reuse some targeted nail code
+ don't target 'who' you just damaged
+
+tech: You can place an extra perfect diamagnatism field on the map
+
+standing wave no longer pushes mobs away, but it can do damage to mobs caught in area effect
+negative mass field does damage to mobs inside field
+ combine with standing wave effect? pilot wave?
+
store value of last hit health lost
- names: patch
-
- tech: after cloaking regen 1/2 of the last hit
- spawning a heal power up is annoying because you'd be cloaked, so direct healing?
- time limit for effect?
- while still under ambush damage?
-
tech: killing the mob that caused the last hit spawns a heal power up equal to 1/2 of last hit
- time limit for effect? 3-4 seconds?
-
- tech: doing damage can recover up to 1/2 of the last hit
- spawn a heal equal to 1/2 of last hit
- time limit for effect? 3-4 seconds?
-
- tech increase damage by how much health was lost in last hit
- +damage = 3x health lost?
- if you went from 100 -> 60 health = +40%*3 = 120% damage
- negative mass field tech?
- too similar to radiative equilibrium
- pick between them?
+ time limit for effect?
+ need to also store who hit player
+add small SVG pics to in-game console
+ when?
+ one for each field?
+ use stuff on physics notes:
+simulation.makeTextLog(`
+
+`);
path-finding
build a path-finding map on level load
@@ -49,12 +68,6 @@ path-finding
drones?
bots that can go far from player and return
-tech ______ effect that last until you get hit
- field or bots can check your health every cycle and see if it lower
- if it's high update the health check value
- effect:
- +damage until getting hit for cloaking field
-
make plasma ball power up and block pick up still work when you have no no energy
make a unique CD var for plasma ball?