beetlemania

mob: beetleBoss
mob: flutter

balance: all mobs at every level are about 2%-3% harder to kill
This commit is contained in:
landgreen
2022-07-31 07:09:57 -07:00
parent 3434869989
commit 746e86cc4a
6 changed files with 245 additions and 46 deletions

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(6 * 4) //30 is near max on hard //60 is near max on why
// level.difficultyIncrease(8 * 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,7 +24,7 @@ const level = {
// powerUps.research.changeRerolls(100)
// tech.tech[297].frequency = 100
// b.guns[0].ammo = 10000
// m.setField("molecular assembler") //molecular assembler time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass
// m.setField("time dilation") //molecular assembler time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass
// 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("infrared diode");
// tech.giveTech("active cooling");
@@ -37,8 +37,8 @@ const level = {
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "research");
// spawn.starter(1900, -500, 200)
// spawn.starter(1900, -500, 50)
// spawn.revolutionBoss(1900, -500)
// for (let i = 0; i < 10; ++i) spawn.starter(1900 + 300 * Math.random(), -500 + 300 * Math.random())
// spawn.beetleBoss(1900, -400)
// for (let i = 0; i < 10; ++i) spawn.flutter(1900 + 300 * Math.random(), -500 + 300 * Math.random())
// 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");
// for (let i = 0; i < 4; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech");
@@ -148,7 +148,7 @@ const level = {
difficultyIncrease(num = 1) {
for (let i = 0; i < num; i++) {
simulation.difficulty++
m.dmgScale *= 0.925; //damage done by player decreases each level
m.dmgScale *= 0.922; //damage done by player decreases each level
if (simulation.accelScale < 6) simulation.accelScale *= 1.025 //mob acceleration increases each level
if (simulation.CDScale > 0.15) simulation.CDScale *= 0.965 //mob CD time decreases each level
}
@@ -159,7 +159,7 @@ const level = {
difficultyDecrease(num = 1) { //used in easy mode for simulation.reset()
for (let i = 0; i < num; i++) {
simulation.difficulty--
m.dmgScale /= 0.925; //damage done by player decreases each level
m.dmgScale /= 0.922; //damage done by player decreases each level
if (simulation.accelScale > 1) simulation.accelScale /= 1.025 //mob acceleration increases each level
if (simulation.CDScale < 1) simulation.CDScale /= 0.965 //mob CD time decreases each level
}
@@ -254,8 +254,10 @@ const level = {
level.levels = shuffle(level.levels); //shuffles order of maps
}
// level.levels.splice(Math.floor(level.levels.length * (0.4 + 0.6 * Math.random())), 0, "reservoir"); //add level to the back half of the randomized levels list
level.levels.splice(Math.floor(Math.seededRandom((level.levels.length) * 0.6, level.levels.length)), 0, "reservoir"); //add level to the back half of the randomized levels list
level.levels.splice(Math.floor(Math.seededRandom((level.levels.length) * 0.6, level.levels.length)), 0, "reactor"); //add level to the back half of the randomized levels list
level.levels.splice(Math.floor(Math.seededRandom(level.levels.length * 0.6, level.levels.length)), 0, "reservoir"); //add level to the back half of the randomized levels list
level.levels.splice(Math.floor(Math.seededRandom(level.levels.length * 0.6, level.levels.length)), 0, "reactor"); //add level to the back half of the randomized levels list
// level.levels.splice(Math.floor(Math.seededRandom(level.levels.length * 0.2, level.levels.length * 0.5)), 0, "reactor"); //add level to the back half of the randomized levels list
// level.levels.splice(Math.floor(Math.seededRandom(level.levels.length * 0.7, level.levels.length)), 0, "reactor"); //add level to the back half of the randomized levels list
level.levels.splice(0, 2); //remove 2 levels from the start of the array
if (!build.isExperimentSelection || (build.hasExperimentalMode && !simulation.isCheating)) { //experimental mode is endless, unless you only have an experiment Tech
level.levels.unshift("intro"); //add level to the start of the randomized levels list
@@ -2733,7 +2735,7 @@ const level = {
spawn.mapRect(475, -25, 25, 50); //edge shelf
},
testing() {
const hazard = level.hazard(6000, -1000, 5, 1000, 0.4) //laser
// const hazard = level.hazard(6000, -1000, 5, 1000, 0.4) //laser
const button = level.button(1000, 0)
spawn.bodyRect(1000, -50, 50, 50);
@@ -2747,7 +2749,7 @@ const level = {
level.enter.draw();
};
level.customTopLayer = () => {
hazard.opticalQuery();
// hazard.opticalQuery();
button.query();
button.draw();
ctx.fillStyle = "rgba(0,0,0,0.1)"

View File

@@ -589,6 +589,22 @@ const mobs = {
ctx.setLineDash([]);
}
},
wing(a, radius = 250, ellipticity = 0.4) {
const minorRadius = radius * ellipticity
const perp = { x: Math.cos(a), y: Math.sin(a) } //
const where = Vector.add(this.position, Vector.mult(perp, radius + 0.8 * this.radius))
ctx.beginPath();
ctx.ellipse(where.x, where.y, radius, minorRadius, a, 0, 2 * Math.PI)
ctx.fill();
//check for wing -> player damage
const hitPlayer = Matter.Query.ray([player], this.position, Vector.add(this.position, Vector.mult(perp, radius * 2.05)), minorRadius)
if (hitPlayer.length && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
m.damage(0.00008 * radius * simulation.dmgScale);
}
},
searchSpring() {
//draw the two dots on the end of the springs
ctx.beginPath();

View File

@@ -2884,7 +2884,7 @@ const m = {
//show sneak attack status
// if (m.cycle > m.lastKillCycle + 240) {
// if (m.sneakAttackCharge > 0) {
if (m.sneakAttackCycle + Math.min(120, 0.5 * (m.cycle - m.enterCloakCycle)) > m.cycle) {
if (m.sneakAttackCycle + Math.min(120, 0.7 * (m.cycle - m.enterCloakCycle)) > m.cycle) {
ctx.strokeStyle = "rgba(0,0,0,0.5)" //m.fieldMeterColor; //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})`
ctx.beginPath();
ctx.arc(m.pos.x, m.pos.y, 28, 0, 2 * Math.PI);

View File

@@ -5,7 +5,8 @@ const spawn = {
randomBossList: [
"orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
"powerUpBoss", "powerUpBossBaby", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss",
"snakeBoss", "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss", "shieldingBoss", "timeSkipBoss"
"snakeBoss", "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss", "shieldingBoss", "timeSkipBoss",
"beetleBoss"
],
bossTypeSpawnOrder: [], //preset list of boss names calculated at the start of a run by the randomSeed
bossTypeSpawnIndex: 0, //increases as the boss type cycles
@@ -24,6 +25,7 @@ const spawn = {
"slasher", "slasher", "slasher",
"stabber", "stabber", "stabber",
"springer", "springer", "springer",
"flutter", "flutter",
"shooter", "shooter",
"grenadier", "grenadier",
"striker", "striker",
@@ -33,7 +35,7 @@ const spawn = {
],
mobTypeSpawnOrder: [], //preset list of mob names calculated at the start of a run by the randomSeed
mobTypeSpawnIndex: 0, //increases as the mob type cycles
allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "launcherOne", "stabber", "sniper", "pulsar", "grenadier", "slasher"],
allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "launcherOne", "stabber", "sniper", "pulsar", "grenadier", "slasher", "flutter"],
setSpawnList() { //this is run at the start of each new level to determine the possible mobs for the level
spawn.pickList.splice(0, 1);
const push = spawn.mobTypeSpawnOrder[spawn.mobTypeSpawnIndex++ % spawn.mobTypeSpawnOrder.length]
@@ -2068,8 +2070,9 @@ const spawn = {
let targets = [] //track who is in the node boss, for shields
mobs.spawn(x, y, 6, radius, "#b386e8");
let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.0032); //extra dense //normal is 0.001 //makes effective life much larger and damage on collision
Matter.Body.setDensity(me, 0.003); //extra dense //normal is 0.001 //makes effective life much larger and damage on collision
me.isBoss = true;
me.damageReduction = 0.13 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) //normal is 1, most bosses have 0.25
targets.push(me.id) //add to shield protection
me.friction = 0;
@@ -2110,7 +2113,6 @@ const spawn = {
Composite.add(engine.world, cons[cons.length - 1]);
cons[len2].length = 100 + 1.5 * radius;
me.cons2 = cons[len2];
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) //normal is 1, most bosses have 0.25
me.do = function() {
// this.armor();
this.gravity();
@@ -2134,7 +2136,7 @@ const spawn = {
for (let i = 0; i < nodes; ++i) {
spawn.stabber(x + sideLength * Math.sin(i * angle), y + sideLength * Math.cos(i * angle), radius, 12);
Matter.Body.setDensity(mob[mob.length - 1], 0.003); //extra dense //normal is 0.001 //makes effective life much larger
mob[mob.length - 1].damageReduction = 0.5
mob[mob.length - 1].damageReduction = 0.12
targets.push(mob[mob.length - 1].id) //track who is in the node boss, for shields
}
@@ -2690,6 +2692,190 @@ const spawn = {
}
}
},
flutter(x, y, radius = 20 + 6 * Math.random()) {
mobs.spawn(x, y, 7, radius, '#16576b');
let me = mob[mob.length - 1];
me.isBoss = true;
Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
// me.damageReduction = 0.04 / (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);
me.accelMag = 0.0006 + 0.0006 * Math.sqrt(simulation.accelScale);
me.frictionAir = 0.05;
// me.seePlayerFreq = 40 + Math.floor(13 * Math.random())
me.memory = 240;
me.restitution = 1;
me.frictionStatic = 0;
me.friction = 0;
me.lookTorque = 0.000001 * (Math.random() > 0.5 ? -1 : 1);
me.fireDir = { x: 0, y: 0 }
spawn.shield(me, x, y);
// me.onDeath = function() {};
me.flapRate = 0.3 + Math.floor(3 * Math.random()) / 10 + 100 * me.accelMag
me.flapRadius = 100 + 75 * Math.random() + radius * 2
me.do = function() {
this.seePlayerByHistory()
this.checkStatus();
if (this.seePlayer.recall) {
this.force.x += Math.cos(this.angle) * this.accelMag * this.mass
this.force.y += Math.sin(this.angle) * this.accelMag * this.mass
//set direction to turn to fire
if (!(simulation.cycle % this.seePlayerFreq)) {
this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position));
//dot product can't tell if mob is facing directly away or directly towards, so check if pointed directly away from player every few cycles
const mod = (a, n) => {
return a - Math.floor(a / n) * n
}
const sub = Vector.sub(m.pos, this.position) //check by comparing different between angles. Give this a nudge if angles are 180 degree different
const diff = mod(Math.atan2(sub.y, sub.x) - this.angle + Math.PI, 2 * Math.PI) - Math.PI
if (Math.abs(diff) > 2.8) this.torque += 0.0002 * this.inertia * Math.random();
}
//rotate towards fireDir
const angle = this.angle + Math.PI / 2;
c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
const threshold = 0.4;
const turn = 0.00003 * this.inertia
if (c > threshold) {
this.torque += turn;
} else if (c < -threshold) {
this.torque -= turn;
}
const flapArc = 0.7 //don't go past 1.57 for normal flaps
ctx.fillStyle = `hsla(${160+40*Math.random()}, 100%, ${25 + 25*Math.random()*Math.random()}%, 0.2)`; //"rgba(0,235,255,0.3)"; // ctx.fillStyle = `hsla(44, 79%, 31%,0.4)`; //"rgba(0,235,255,0.3)";
this.wing(this.angle + Math.PI / 2 + flapArc * Math.sin(simulation.cycle * this.flapRate), this.flapRadius)
this.wing(this.angle - Math.PI / 2 - flapArc * Math.sin(simulation.cycle * this.flapRate), this.flapRadius)
}
};
},
beetleBoss(x, y, radius = 60) {
mobs.spawn(x, y, 7, radius, '#16576b');
let me = mob[mob.length - 1];
me.isBoss = true;
Matter.Body.setDensity(me, 0.005); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.07 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.nextHealthThreshold = 0.75
me.invulnerableCount = 0
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);
me.accelMag = 0.0006 + 0.0006 * Math.sqrt(simulation.accelScale);
me.frictionAir = 0.05;
me.seePlayerFreq = 30
me.memory = 420;
me.restitution = 1;
me.frictionStatic = 0;
me.friction = 0;
me.lookTorque = 0.000001 * (Math.random() > 0.5 ? -1 : 1);
me.fireDir = { x: 0, y: 0 }
spawn.shield(me, x, y);
// for (let i = 0, len = 4 + 0.2 * simulation.difficulty; i < len; ++i) {
// const phase = i / len * 2 * Math.PI
// const where = Vector.add(me.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5))
// spawn.flutter(where.x, where.y)
// }
me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
len = 0.2 * simulation.difficulty
if (len > 3) {
for (let i = 0; i < len; ++i) {
const phase = i / len * 2 * Math.PI
const where = Vector.add(this.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5))
spawn.flutter(where.x, where.y)
}
}
};
me.onDamage = function() {
if (this.health < this.nextHealthThreshold) {
this.health = this.nextHealthThreshold - 0.01
this.nextHealthThreshold = Math.floor(this.health * 4) / 4
this.invulnerableCount = 180 + Math.floor(60 * Math.random())
this.isInvulnerable = true
this.damageReduction = 0
this.frictionAir = 0
}
};
me.do = function() {
this.seePlayerByHistory()
this.checkStatus();
if (this.isInvulnerable) {
this.invulnerableCount--
if (this.invulnerableCount < 0) {
this.isInvulnerable = false
this.damageReduction = this.startingDamageReduction
this.frictionAir = 0.05
}
// //draw wings as if they are protecting
// const wingShield = (a, size) => {
// ctx.beginPath();
// const perp = { x: Math.cos(a), y: Math.sin(a) } //
// const where = Vector.add(this.position, Vector.mult(perp, 0.2 * this.radius))
// ctx.ellipse(where.x, where.y, size, size * 0.8, a, 0, 2 * Math.PI)
// ctx.fillStyle = this.fill = `hsla(${160+40*Math.random()}, 100%, ${25 + 25*Math.random()*Math.random()}%, 0.9)`; //"rgba(0,235,255,0.3)"; // ctx.fillStyle = `hsla(44, 79%, 31%,0.4)`; //"rgba(0,235,255,0.3)";
// ctx.fill();
// }
// wingShield(this.angle + Math.PI / 2, radius * 1.3)
// wingShield(this.angle - Math.PI / 2, radius * 1.3)
//draw invulnerable
ctx.beginPath();
let vertices = this.vertices;
ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 13 + 5 * Math.random();
ctx.strokeStyle = `rgba(255,255,255,${0.5+0.2*Math.random()})`;
ctx.stroke();
} else if (this.seePlayer.recall) {
// const force = Vector.mult(Vector.normalise(Vector.sub(this.seePlayer.position, this.position)), this.accelMag * this.mass)
// const force = Vector.mult({ x: Math.cos(this.angle), y: Math.sin(this.angle) }, this.accelMag * this.mass)
// this.force.x += force.x;
// this.force.y += force.y;
this.force.x += Math.cos(this.angle) * this.accelMag * this.mass
this.force.y += Math.sin(this.angle) * this.accelMag * this.mass
//set direction to turn to fire
if (!(simulation.cycle % this.seePlayerFreq)) {
this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position));
//dot product can't tell if mob is facing directly away or directly towards, so check if pointed directly away from player every few cycles
//check by comparing different between angles. Give this a nudge if angles are 180 degree different
const mod = (a, n) => {
return a - Math.floor(a / n) * n
}
const sub = Vector.sub(m.pos, this.position)
const diff = mod(Math.atan2(sub.y, sub.x) - this.angle + Math.PI, 2 * Math.PI) - Math.PI
if (Math.abs(diff) > 2.8) this.torque += 0.0002 * this.inertia * Math.random();
}
//rotate towards fireDir
const angle = this.angle + Math.PI / 2;
c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
const threshold = 0.4;
const turn = 0.00003 * this.inertia
if (c > threshold) {
this.torque += turn;
} else if (c < -threshold) {
this.torque -= turn;
}
const flapRate = 0.5
const flapArc = 0.7 //don't go past 1.57 for normal flaps
ctx.fillStyle = this.fill = `hsla(${160+40*Math.random()}, 100%, ${25 + 25*Math.random()*Math.random()}%, 0.9)`; //"rgba(0,235,255,0.3)"; // ctx.fillStyle = `hsla(44, 79%, 31%,0.4)`; //"rgba(0,235,255,0.3)";
this.wing(this.angle + Math.PI / 2 + flapArc * Math.sin(simulation.cycle * flapRate), 250, 0.5)
this.wing(this.angle - Math.PI / 2 - flapArc * Math.sin(simulation.cycle * flapRate), 250, 0.5)
}
};
},
laserTargetingBoss(x, y, radius = 80) {
const color = "#07f"
mobs.spawn(x, y, 3, radius, color);
@@ -3846,6 +4032,10 @@ const spawn = {
me.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.nextHealthThreshold = 0.75
me.invulnerableCount = 0
me.cycle = 0
me.inertia = Infinity;
me.frictionAir = 0.01
me.restitution = 1
@@ -3889,9 +4079,6 @@ const spawn = {
if (mob[i].isMine && Vector.magnitude(Vector.sub(this.position, mob[i].position)) < this.explodeRange) mob[i].isExploding = true
}
};
me.cycle = 0
me.nextHealthThreshold = 0.75
me.invulnerableCount = 0
// console.log(me.mass) //100
me.do = function() {
me.seePlayer.recall = 1
@@ -4718,14 +4905,14 @@ const spawn = {
},
bodyB: me,
stiffness: 0.00004,
damping: 0.1
damping: 0.2
});
Composite.add(engine.world, me.constraint);
}, 2000); //add in a delay in case the level gets flipped left right
me.isBoss = true;
Matter.Body.setDensity(me, 0.008 + 0.0003 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
Matter.Body.setDensity(me, 0.01 + 0.0003 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.2 / (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
me.isVerticesChange = true
@@ -4738,9 +4925,7 @@ const spawn = {
me.lookTorque = 0.000006 * (Math.random() > 0.5 ? -1 : 1);
me.fireDir = { x: 0, y: 0 };
setTimeout(() => {
// spawn.spawnOrbitals(me, radius + 200 + 50 * Math.random(), 1);
for (let i = 0, len = 3 + 0.5 * Math.sqrt(simulation.difficulty); i < len; i++) spawn.spawnOrbitals(me, radius + 40 + 10 * i, 1);
}, 100); //have to wait a sec so the tether constraint doesn't attach to an orbital
me.onDeath = function() {
if (isSpawnBossPowerUp) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
@@ -5051,6 +5236,8 @@ const spawn = {
mobs.spawn(x, y, 6, radius, "rgb(150,150,255)");
let me = mob[mob.length - 1];
me.isBoss = true;
Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.accelMag = 0.0001 * simulation.accelScale;
me.fireFreq = Math.floor(330 * simulation.CDScale)
@@ -5062,13 +5249,11 @@ const spawn = {
spawn.shield(me, x, y, 1);
spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random())
Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.onDeath = function() {
if (isSpawnBossPowerUp) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //helps collisions functions work better after vertex have been changed
};
me.onDamage = function() {};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.do = function() {
// this.armor();
this.seePlayerCheck();

View File

@@ -317,9 +317,9 @@ const tech = {
// isExperimentHide: true,
isBadRandomOption: true,
allowed() {
return !tech.isSuperDeterminism
return true
},
requires: "not superdeterminism",
requires: "",
effect() {
powerUps.spawn(m.pos.x, m.pos.y, "gun");
// this.count--
@@ -3043,9 +3043,9 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isResearchReality //tech.isResearchBoss || tech.isMetaAnalysis || tech.isRerollBots || tech.isDeathAvoid || tech.isRerollDamage || build.isExperimentSelection
return !tech.isResearchReality && !tech.isSuperDeterminism //tech.isResearchBoss || tech.isMetaAnalysis || tech.isRerollBots || tech.isDeathAvoid || tech.isRerollDamage || build.isExperimentSelection
},
requires: "not Ψ(t) collapse", //"abiogenesis, meta-analysis, bot fabrication, anthropic principle, or Bayesian statistics, not Ψ(t) collapse",
requires: "not Ψ(t) collapse, superdeterminism", //"abiogenesis, meta-analysis, bot fabrication, anthropic principle, or Bayesian statistics, not Ψ(t) collapse",
effect() {
tech.isJunkResearch = true;
},
@@ -3061,9 +3061,9 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
return true
return !tech.isSuperDeterminism
},
requires: "",
requires: "not superdeterminism",
effect() {
tech.isBrainstorm = true
tech.isBrainstormActive = false

View File

@@ -1,23 +1,19 @@
******************************************************** NEXT PATCH **************************************************
tech: ricochet - nails bounce off mobs and hit other mobs with extra damage per ricochet
mob: beetleBoss
mob: flutter
tech: dye laser - 20% efficiency and 20% damage
laser diode renamed infrared diode
40 -> 50% efficiency but you can't see the laser beam
laser-bots acquire new targets much faster
iridescence 88 -> 100% damage, a tiny bit harder to hit center of mobs
stacks up to 3 -> 9
dynamic equilibrium scales damage with defense
goes up to 9x stacks
neutronium 25 -> 20% slower movement
revolutionBoss laser swords are much slower and shorter
but they do more damage
balance: all mobs at every level are about 2%-3% harder to kill
*********************************************************** TODO *****************************************************
wings
put in mob as a method?
add parameter for ellipticity
give snakeBoss wings?
mob mechanics
bullets hit player and stay attached for 4-5 seconds, slowing player
hopperBullets?