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

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

bug fix: quantum eraser now removes mobs in a more random order
  it used to have a too low chance to remove bosses
This commit is contained in:
landgreen
2022-07-26 08:26:05 -07:00
parent cf3ba7d5f2
commit 3e8f07ab04
9 changed files with 288 additions and 161 deletions

View File

@@ -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)
}

View File

@@ -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 = `<a target="_blank" href='https://en.wikipedia.org/w/index.php?search=${encodeURIComponent(tech.tech[i].name).replace(/'/g, '%27')}&title=Special:Search' class="link">${tech.tech[i].name}</a>`
}
//<br>effective <strong class='color-defense'>defense</strong>: ${(1-simulation.dmgScale*m.harmReduction()).toPrecision(3)}
//<br>effective <strong class='color-d'>damage</strong>: ${(tech.damageFromTech() * m.dmgScale).toPrecision(3)}
const build = {
pauseGrid() {
//left side

View File

@@ -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");

View File

@@ -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(`<span class='color-var'>m</span>.health <span class='color-symbol'>+=</span> ${(heal).toFixed(3)}`) // <br>${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) {

View File

@@ -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++
}

View File

@@ -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(`<span class='color-var'>tech</span>.quantumEraserCount <span class='color-symbol'>=</span> ${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

View File

@@ -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 <strong>10 seconds</strong> after receiving <strong class='color-defense'>defense</strong><br>increase <strong class='color-d'>damage</strong> by <strong>200%</strong>",
// maxCount: 1,
// count: 0,
// frequency: 1,
// frequencyDefault: 1,
// allowed() {
// return true
// },
// requires: "",
// effect() {
// tech.isHarmDamage = true;
// },
// remove() {
// tech.isHarmDamage = false;
// }
// },
{
name: "CPT symmetry",
// description: "<strong>charge</strong>, <strong>parity</strong>, and <strong>time</strong> invert to undo <strong class='color-defense'>defense</strong><br><strong class='color-rewind'>rewind</strong> <strong>(1.5—5)</strong> seconds for <strong>(66—220)</strong> <strong class='color-f'>energy</strong>",
@@ -2272,42 +2253,42 @@ const tech = {
}
}
},
{
name: "weak interaction",
description: "for each unused <strong>power up</strong> at the end of a <strong>level</strong><br><strong>+10</strong> maximum <strong class='color-f'>energy</strong>", // <em>(up to 51 health per level)</em>",
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 <strong>power ups</strong> at the end of a <strong>level</strong><br>are still activated <em>(selections are random)</em>",
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 <strong>power up</strong> at the end of a <strong>level</strong><br><strong>+10</strong> maximum <strong class='color-f'>energy</strong>", // <em>(up to 51 health per level)</em>",
// 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 <strong>power ups</strong> at the end of a <strong>level</strong><br>are still activated <em>(selections are random)</em>",
// 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: "<strong>+1%</strong> <strong class='color-d'>damage</strong> per <strong>8</strong> stored <strong class='color-f'>energy</strong>",
@@ -4107,7 +4088,7 @@ const tech = {
{
name: "spin-statistics",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Spin%E2%80%93statistics_theorem' class="link">spin-statistics</a>`,
description: "<strong>invulnerable</strong> while firing the <strong>shotgun</strong><br>shotgun has <strong>50%</strong> fewer shots",
description: "after firing the <strong>shotgun</strong> you are <strong>invulnerable</strong><br>shotgun has <strong>50%</strong> 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 <strong class='color-d'>damage</strong> by <strong>5%</strong><br>of your last ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"} loss` },
// description: `increase <strong class='color-d'>damage</strong> by <strong>500%</strong><br>of your last <strong class='color-h'>health</strong> 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: `<strong>move</strong> and <strong>jump</strong> <strong>25%</strong> <strong>slower</strong><br>if your <strong class='color-f'>field</strong> is active <strong>+90%</strong> <strong class='color-defense'>defense</strong>`,
@@ -7347,6 +7348,26 @@ const tech = {
}
}
},
{
name: "patch",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Patch_(computing)' class="link">patch</a>`,
description: "after <strong class='color-cloaked'>cloaking</strong> recover <strong>75%</strong> of your<br>last <strong class='color-h'>health</strong> loss using that much <strong class='color-f'>energy</strong>",
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: `<a target="_blank" href='https://en.wikipedia.org/wiki/Dazzler_(weapon)' class="link">dazzler</a>`,
@@ -10528,5 +10549,7 @@ const tech = {
isLaserLens: null,
laserCrit: null,
isSporeColony: null,
isExtraBotOption: null
isExtraBotOption: null,
isLastHitDamage: null,
isCloakHealLastHit: null
}

View File

@@ -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 */

View File

@@ -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(`
<svg class="SVG-title" width="160" height="120">
<g fill="transparent" stroke="#333" stroke-width="1" transform="translate(78,75)" stroke-linecap="round">
<path d="M-34 -34 l31 31 m6 6 l31 31 M34 -34 l-31 31 m-6 6 l-31 31"></path>
<ellipse cx="0" cy="35" rx="34.5" ry="7"/>
<ellipse cx="0" cy="-35" rx="34.5" ry="7"/>
<g stroke="none" fill="#333">
<circle cx="0" cy="0" r="1.5" />
</g>
</g>
</svg>
`);
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?