testChamber2

meta-analysis - if you choose a junk tech you instead get a random tech and spawn 2 research
micro-extruder should have 50% less lag

new community level testChamber2! by Oranger on n-gon discord
(be sure to enable community levels in settings)
This commit is contained in:
landgreen
2021-03-11 18:35:11 -08:00
parent 1056a77572
commit 3d04e61a04
8 changed files with 539 additions and 258 deletions

View File

@@ -1207,18 +1207,18 @@ const b = {
m.energy = 0;
}
b.isExtruderOn = true
const SPEED = 8
const SPEED = 14
const me = bullet.length;
const where = Vector.add(m.pos, player.velocity)
bullet[me] = Bodies.polygon(where.x + 20 * Math.cos(m.angle), where.y + 20 * Math.sin(m.angle), 4, 0.01, {
cycle: -0.5,
isWave: true,
endCycle: simulation.cycle + 35 + 45 * tech.isPlasmaRange,
endCycle: simulation.cycle + 53, // + 30 * tech.isPlasmaRange,
inertia: Infinity,
frictionAir: 0,
isInHole: true, //this keeps the bullet from entering wormholes
minDmgSpeed: 0,
dmg: b.dmgScale * 1.2, //damage also changes when you divide by mob.mass on in .do()
dmg: b.dmgScale * 1.5, //damage also changes when you divide by mob.mass on in .do()
classType: "bullet",
isBranch: false,
restitution: 0,
@@ -1270,7 +1270,7 @@ const b = {
y: SPEED * Math.sin(m.angle)
});
const transverse = Vector.normalise(Vector.perp(bullet[me].velocity))
if (180 - Math.abs(Math.abs(b.lastAngle - m.angle) - 180) > 0.3) bullet[me].isBranch = true; //don't draw stroke for this bullet
if (180 - Math.abs(Math.abs(b.lastAngle - m.angle) - 180) > 0.13) bullet[me].isBranch = true; //don't draw stroke for this bullet
b.lastAngle = m.angle //track last angle for the above angle difference calculation
if (!b.wasExtruderOn) bullet[me].isBranch = true;
} else {
@@ -1825,119 +1825,122 @@ const b = {
},
spore(where, isFreeze = tech.isSporeFreeze) { //used with the tech upgrade in mob.death()
const bIndex = bullet.length;
const side = 4;
bullet[bIndex] = Bodies.polygon(where.x, where.y, 4, side, {
// density: 0.0015, //frictionAir: 0.01,
inertia: Infinity,
isFreeze: isFreeze,
restitution: 0.5,
angle: Math.random() * 2 * Math.PI,
friction: 0,
frictionAir: 0.025,
thrust: (tech.isFastSpores ? 0.001 : 0.0004) * (1 + 0.3 * (Math.random() - 0.5)),
dmg: tech.isMutualism ? 12 : 5, //bonus damage from tech.isMutualism
lookFrequency: 100 + Math.floor(117 * Math.random()),
classType: "bullet",
collisionFilter: {
category: cat.bullet,
mask: cat.map | cat.mob | cat.mobBullet | cat.mobShield //no collide with body
},
endCycle: simulation.cycle + Math.floor((600 + Math.floor(Math.random() * 420)) * tech.isBulletsLastLonger),
minDmgSpeed: 0,
playerOffPosition: { //used when moving towards player to keep spores separate
x: 100 * (Math.random() - 0.5),
y: 100 * (Math.random() - 0.5)
},
beforeDmg(who) {
this.endCycle = 0; //bullet ends cycle after doing damage
if (this.isFreeze) mobs.statusSlow(who, 90)
},
onEnd() {
if (tech.isMutualism && this.isMutualismActive && !tech.isEnergyHealth) {
m.health += 0.005
if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth();
}
},
do() {
if (this.lockedOn && this.lockedOn.alive) {
this.force = Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), this.mass * this.thrust)
} else {
if (!(simulation.cycle % this.lookFrequency)) { //find mob targets
this.closestTarget = null;
this.lockedOn = null;
let closeDist = Infinity;
for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].dropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
const targetVector = Vector.sub(this.position, mob[i].position)
const dist = Vector.magnitude(targetVector) * (Math.random() + 0.5);
if (dist < closeDist) {
this.closestTarget = mob[i].position;
closeDist = dist;
this.lockedOn = mob[i]
if (0.3 > Math.random()) break //doesn't always target the closest mob
if (bIndex < 500) { //can't make over 500 spores
bullet[bIndex] = Bodies.polygon(where.x, where.y, 4, 4, {
// density: 0.0015, //frictionAir: 0.01,
inertia: Infinity,
isFreeze: isFreeze,
restitution: 0.5,
angle: Math.random() * 2 * Math.PI,
friction: 0,
frictionAir: 0.025,
thrust: (tech.isFastSpores ? 0.001 : 0.0004) * (1 + 0.3 * (Math.random() - 0.5)),
dmg: tech.isMutualism ? 12 : 5, //bonus damage from tech.isMutualism
lookFrequency: 100 + Math.floor(117 * Math.random()),
classType: "bullet",
collisionFilter: {
category: cat.bullet,
mask: cat.map | cat.mob | cat.mobBullet | cat.mobShield //no collide with body
},
endCycle: simulation.cycle + Math.floor((600 + Math.floor(Math.random() * 420)) * tech.isBulletsLastLonger),
minDmgSpeed: 0,
playerOffPosition: { //used when moving towards player to keep spores separate
x: 100 * (Math.random() - 0.5),
y: 100 * (Math.random() - 0.5)
},
beforeDmg(who) {
this.endCycle = 0; //bullet ends cycle after doing damage
if (this.isFreeze) mobs.statusSlow(who, 90)
},
onEnd() {
if (tech.isMutualism && this.isMutualismActive && !tech.isEnergyHealth) {
m.health += 0.005
if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth();
}
},
do() {
if (this.lockedOn && this.lockedOn.alive) {
this.force = Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), this.mass * this.thrust)
} else {
if (!(simulation.cycle % this.lookFrequency)) { //find mob targets
this.closestTarget = null;
this.lockedOn = null;
let closeDist = Infinity;
for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].dropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
const targetVector = Vector.sub(this.position, mob[i].position)
const dist = Vector.magnitude(targetVector) * (Math.random() + 0.5);
if (dist < closeDist) {
this.closestTarget = mob[i].position;
closeDist = dist;
this.lockedOn = mob[i]
if (0.3 > Math.random()) break //doesn't always target the closest mob
}
}
}
}
}
if (tech.isSporeFollow && this.lockedOn === null) { //move towards player
//checking for null means that the spores don't go after the player until it has looked and not found a target
const dx = this.position.x - m.pos.x;
const dy = this.position.y - m.pos.y;
if (dx * dx + dy * dy > 10000) {
this.force = Vector.mult(Vector.normalise(Vector.sub(m.pos, Vector.add(this.playerOffPosition, this.position))), this.mass * this.thrust)
if (tech.isSporeFollow && this.lockedOn === null) { //move towards player
//checking for null means that the spores don't go after the player until it has looked and not found a target
const dx = this.position.x - m.pos.x;
const dy = this.position.y - m.pos.y;
if (dx * dx + dy * dy > 10000) {
this.force = Vector.mult(Vector.normalise(Vector.sub(m.pos, Vector.add(this.playerOffPosition, this.position))), this.mass * this.thrust)
}
} else {
this.force.y += this.mass * 0.0001; //gravity
}
} else {
this.force.y += this.mass * 0.0001; //gravity
}
}
// if (!this.lockedOn && !(simulation.cycle % this.lookFrequency)) { //find mob targets
// this.closestTarget = null;
// this.lockedOn = null;
// let closeDist = Infinity;
// for (let i = 0, len = mob.length; i < len; ++i) {
// if (mob[i].dropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
// // Matter.Query.ray(body, this.position, mob[i].position).length === 0
// const targetVector = Vector.sub(this.position, mob[i].position)
// const dist = Vector.magnitude(targetVector);
// if (dist < closeDist) {
// this.closestTarget = mob[i].position;
// closeDist = dist;
// this.lockedOn = mob[i] //Vector.normalise(targetVector);
// if (0.3 > Math.random()) break //doesn't always target the closest mob
// }
// }
// }
// }
// if (this.lockedOn && this.lockedOn.alive) { //accelerate towards mobs
// this.force = Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), this.mass * this.thrust)
// } else if (tech.isSporeFollow && this.lockedOn !== undefined) { //move towards player
// //checking for undefined means that the spores don't go after the player until it has looked and not found a target
// const dx = this.position.x - m.pos.x;
// const dy = this.position.y - m.pos.y;
// if (dx * dx + dy * dy > 10000) {
// this.force = Vector.mult(Vector.normalise(Vector.sub(m.pos, Vector.add(this.playerOffPosition, this.position))), this.mass * this.thrust)
// }
// // this.force = Vector.mult(Vector.normalise(Vector.sub(m.pos, this.position)), this.mass * this.thrust)
// } else {
// this.force.y += this.mass * 0.0001; //gravity
// }
// if (!this.lockedOn && !(simulation.cycle % this.lookFrequency)) { //find mob targets
// this.closestTarget = null;
// this.lockedOn = null;
// let closeDist = Infinity;
// for (let i = 0, len = mob.length; i < len; ++i) {
// if (mob[i].dropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
// // Matter.Query.ray(body, this.position, mob[i].position).length === 0
// const targetVector = Vector.sub(this.position, mob[i].position)
// const dist = Vector.magnitude(targetVector);
// if (dist < closeDist) {
// this.closestTarget = mob[i].position;
// closeDist = dist;
// this.lockedOn = mob[i] //Vector.normalise(targetVector);
// if (0.3 > Math.random()) break //doesn't always target the closest mob
// }
// }
// }
// }
// if (this.lockedOn && this.lockedOn.alive) { //accelerate towards mobs
// this.force = Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), this.mass * this.thrust)
// } else if (tech.isSporeFollow && this.lockedOn !== undefined) { //move towards player
// //checking for undefined means that the spores don't go after the player until it has looked and not found a target
// const dx = this.position.x - m.pos.x;
// const dy = this.position.y - m.pos.y;
// if (dx * dx + dy * dy > 10000) {
// this.force = Vector.mult(Vector.normalise(Vector.sub(m.pos, Vector.add(this.playerOffPosition, this.position))), this.mass * this.thrust)
// }
// // this.force = Vector.mult(Vector.normalise(Vector.sub(m.pos, this.position)), this.mass * this.thrust)
// } else {
// this.force.y += this.mass * 0.0001; //gravity
// }
},
});
const SPEED = 4 + 8 * Math.random();
const ANGLE = 2 * Math.PI * Math.random()
Matter.Body.setVelocity(bullet[bIndex], {
x: SPEED * Math.cos(ANGLE),
y: SPEED * Math.sin(ANGLE)
});
World.add(engine.world, bullet[bIndex]); //add bullet to world
},
});
if (tech.isMutualism && m.health > 0.02) {
m.health -= 0.005
m.displayHealth();
bullet[bIndex].isMutualismActive = true
const SPEED = 4 + 8 * Math.random();
const ANGLE = 2 * Math.PI * Math.random()
Matter.Body.setVelocity(bullet[bIndex], {
x: SPEED * Math.cos(ANGLE),
y: SPEED * Math.sin(ANGLE)
});
World.add(engine.world, bullet[bIndex]); //add bullet to world
if (tech.isMutualism && m.health > 0.02) {
m.health -= 0.005
m.displayHealth();
bullet[bIndex].isMutualismActive = true
}
}
},
iceIX(speed = 0, spread = 2 * Math.PI) {
@@ -3405,6 +3408,7 @@ const b = {
const me = bullet.length;
const dir = m.angle + 0.02 * (Math.random() - 0.5)
bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle), m.pos.y + 35 * Math.sin(m.angle), 45, 20, b.fireAttributes(dir));
Matter.Body.setDensity(bullet[me], 0.004);
World.add(engine.world, bullet[me]); //add bullet to world
const SPEED = (m.crouch ? 52 : 43) + Math.random() * 7

View File

@@ -16,7 +16,7 @@ const level = {
// simulation.zoomScale = 1000;
// simulation.setZoom();
// m.setField("nano-scale manufacturing")
// b.giveGuns("laser")
// b.giveGuns("shotgun")
// tech.isExplodeRadio = true
// for (let i = 0; i < 1; i++) tech.giveTech("dynamo-bot")
// tech.giveTech("supercritical fission")
@@ -55,6 +55,8 @@ const level = {
// level.detours() //fan level
// level.basement(); //fan level
// level.stronghold() //fan level
// level.testChamber2() //fan level
// powerUps.directSpawn(simulation.mouseInGame.x, simulation.mouseInGame.y, "tech");
// tech.giveTech("undefined")
@@ -768,7 +770,7 @@ const level = {
mapB.portalPair = mapA
return [portalA, portalB, mapA, mapB]
},
hazard(x, y, width, height, damage = 0.003, color = "hsla(160, 100%, 35%,0.75)", isOptical = false) {
hazard(x, y, width, height, damage = 0.003, color = "hsla(160, 100%, 35%,0.75)") {
return {
min: {
x: x,
@@ -782,15 +784,30 @@ const level = {
height: height,
maxHeight: height,
isOn: true,
opticalQuery() {
if (this.isOn && this.height > 0 && Matter.Query.region([player], this).length && !(m.isCloak)) {
if (m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + tech.collisionImmuneCycles;
m.damage(damage)
simulation.drawList.push({ //add dmg to draw queue
x: player.position.x,
y: player.position.y,
radius: damage * 1500,
color: simulation.mobDmgColor,
time: 20
});
}
}
},
query() {
if (this.isOn && this.height > 0 && Matter.Query.region([player], this).length && !(m.isCloak && isOptical)) {
if (this.isOn && this.height > 0 && Matter.Query.region([player], this).length) {
const drain = 0.003 + m.fieldRegen
if (m.energy > drain) {
m.energy -= drain
} else {
if (damage < 0.02) {
m.damage(damage)
} else if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) {
} else if (m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + tech.collisionImmuneCycles;
m.damage(damage)
simulation.drawList.push({ //add dmg to draw queue
@@ -802,29 +819,24 @@ const level = {
});
}
}
//float
if (!isOptical) {
if (player.velocity.y > 3) player.force.y -= 0.96 * player.mass * simulation.g
const slowY = (player.velocity.y > 0) ? Math.max(0.3, 1 - 0.0015 * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - 0.001 * Math.abs(player.velocity.y)) //down : up
Matter.Body.setVelocity(player, {
x: Math.max(0.6, 1 - 0.07 * Math.abs(player.velocity.x)) * player.velocity.x,
y: slowY * player.velocity.y
});
}
if (player.velocity.y > 5) player.force.y -= 0.95 * player.mass * simulation.g
const slowY = (player.velocity.y > 0) ? Math.max(0.4, 1 - 0.001 * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - 0.001 * Math.abs(player.velocity.y)) //down : up
Matter.Body.setVelocity(player, {
x: Math.max(0.6, 1 - 0.07 * Math.abs(player.velocity.x)) * player.velocity.x,
y: slowY * player.velocity.y
});
}
//float power ups
if (!isOptical) {
powerUpCollide = Matter.Query.region(powerUp, this)
for (let i = 0, len = powerUpCollide.length; i < len; i++) {
const diameter = 2 * powerUpCollide[i].size
const buoyancy = 1 - 0.2 * Math.max(0, Math.min(diameter, this.min.y - powerUpCollide[i].position.y + powerUpCollide[i].size)) / diameter
powerUpCollide[i].force.y -= buoyancy * 1.1 * powerUpCollide[i].mass * simulation.g;
Matter.Body.setVelocity(powerUpCollide[i], {
x: powerUpCollide[i].velocity.x,
y: 0.95 * powerUpCollide[i].velocity.y
});
}
powerUpCollide = Matter.Query.region(powerUp, this)
for (let i = 0, len = powerUpCollide.length; i < len; i++) {
const diameter = 2 * powerUpCollide[i].size
const buoyancy = 1 - 0.2 * Math.max(0, Math.min(diameter, this.min.y - powerUpCollide[i].position.y + powerUpCollide[i].size)) / diameter
powerUpCollide[i].force.y -= buoyancy * 1.1 * powerUpCollide[i].mass * simulation.g;
Matter.Body.setVelocity(powerUpCollide[i], {
x: powerUpCollide[i].velocity.x,
y: 0.95 * powerUpCollide[i].velocity.y
});
}
},
draw() {
@@ -1117,9 +1129,9 @@ const level = {
};
level.customTopLayer = () => {};
level.setPosToSpawn(0, -50); //normal spawn
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.exit.x = 1500;
level.exit.y = -1875;
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.defaultZoom = 1800
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#dcdcde";
@@ -1482,8 +1494,8 @@ const level = {
spawn.mapRect(1225, -1955, 175, 30);
const removeIndex2 = map.length - 1 //so much work to catch blocks caught at the bottom of the vertical portals
const hazard = level.hazard(350, -2025, 700, 10, 0.4, "hsl(0, 100%, 50%)", true) //laser
const hazard2 = level.hazard(1775, -2550, 150, 10, 0.4, "hsl(0, 100%, 50%)", true) //laser
const hazard = level.hazard(350, -2025, 700, 10, 0.4, "hsl(0, 100%, 50%)") //laser
const hazard2 = level.hazard(1775, -2550, 150, 10, 0.4, "hsl(0, 100%, 50%)") //laser
const button = level.button(2100, -2600)
@@ -1533,8 +1545,8 @@ const level = {
portal2[3].query()
portal3[2].query()
portal3[3].query()
hazard.query();
hazard2.query();
hazard.opticalQuery();
hazard2.opticalQuery();
if (button.isUp) {
hazard.isOn = false;
hazard2.isOn = false;
@@ -2971,6 +2983,42 @@ const level = {
});
World.add(engine.world, cons[cons.length - 1]);
// spawn.bodyRect(-2775, 1300, 400, 100, 1); //hoist
// cons[cons.length] = Constraint.create({
// pointA: {
// x: -2375,
// y: 150
// },
// bodyB: body[body.length - 1],
// pointB: {
// x: 190,
// y: -50
// },
// stiffness: 0.0001,
// damping: 0.2,
// length: 1
// });
// cons[cons.length] = Constraint.create({
// pointA: {
// x: -2775,
// y: 150
// },
// bodyB: body[body.length - 1],
// pointB: {
// x: -190,
// y: -50
// },
// stiffness: 0.0001,
// damping: 0.2,
// length: 1
// });
// World.add(engine.world, [cons[cons.length - 1], cons[cons.length - 2]]);
//blocks
spawn.bodyRect(-165, -150, 30, 35, 1);
spawn.bodyRect(-165, -115, 30, 35, 1);
@@ -4019,7 +4067,7 @@ const level = {
// // tether ball
// spawn.tetherBoss(8000, 630, { x: 8550, y: 680 })
// let me = mob[mob.length - 1];
// me.onDeath = function() {
// me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs
// this.removeCons(); //remove constraint
// spawnCouloirEnHaut()
// doorSortieSalle.isOpen = false;
@@ -4033,7 +4081,7 @@ const level = {
if (mob[i].isBoss) me = mob[i]
}
if (me) {
me.onDeath = function() {
me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs
spawnCouloirEnHaut()
doorSortieSalle.isOpen = false;
};
@@ -4049,7 +4097,7 @@ const level = {
if (mob[i].isBoss) me = mob[i]
}
if (me) {
me.onDeath = function() {
me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs
spawnCouloirEnHaut()
doorSortieSalle.isOpen = false;
};
@@ -4624,5 +4672,247 @@ const level = {
spawn.randomLevelBoss(3100, -1850, ["shooterBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "snakeBoss", "laserBoss"]);
}
}
}
},
testChamber2() {
level.setPosToSpawn(-600, 400);
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.exit.x = 550;
level.exit.y = -2730;
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20);
const portal = level.portal({ //main portals
x: -1000,
y: 50
}, -Math.PI / 2, { //up
x: 1000,
y: 50
}, -Math.PI / 2) //up
const portal2 = level.portal({ //portals in upper right corner
x: 1400,
y: -2200
}, -Math.PI / 2, { //up
x: 1700,
y: -1700
}, -Math.PI / 2) //up
const rotor = level.rotor(-200, -1950, -0.001)
level.custom = () => {
level.playerExitCheck();
portal[2].query()
portal[3].query()
portal2[2].query()
portal2[3].query()
rotor.rotate();
};
level.customTopLayer = () => {
portal[0].draw();
portal[1].draw();
portal[2].draw();
portal[3].draw();
portal2[0].draw();
portal2[1].draw();
portal2[2].draw();
portal2[3].draw();
};
level.defaultZoom = 1700 // 4500 // 1400
simulation.zoomTransition(level.defaultZoom)
//section 1: before portals
spawn.mapRect(-925, 450, 1850, 250); //1-1 base
spawn.mapRect(-925, -300, 55, 755); //1 left wall
spawn.mapRect(-875, 50, 1100, 50); //1-1 ceiling
spawn.mapRect(620, -300, 305, 755); //1-1 and 1-2 right wall
spawn.bodyRect(200, 350, 230, 100);
spawn.bodyRect(300, 250, 150, 100);
spawn.mapRect(-875, -300, 580, 50); //1-2 ceiling on left
spawn.mapRect(0, -300, 625, 50); //1-2 ceiling on right
spawn.mapRect(0, -650, 150, 350); //1-3 right wall
spawn.mapRect(-925, -650, 975, 150); //1-3 ceiling
spawn.mapRect(-1280, 100, 205, 150); //1-4 floor
spawn.mapRect(-1280, 245, 360, 455); //bottom left corner
spawn.mapRect(-1600, -200, 200, 50); //1-4 platform 1
level.fill.push({
x: -875,
y: -250,
width: 1500,
height: 700,
color: "rgba(0,0,0,0.1)"
});
level.fill.push({
x: -925,
y: -505,
width: 930,
height: 255,
color: "rgba(0,0,0,0.1)"
});
//section 2: lower central room (gone through main portals 1 time)
spawn.mapRect(920, 245, 160, 455); //below right portal
spawn.mapRect(1075, -300, 500, 1000); //2-1 right floor
spawn.mapRect(1075, -2005, 550, 1055); //shute right wall
spawn.mapRect(875, -1000, 50, 300); //shute left 1
spawn.mapRect(860, -1030, 50, 300); //shute left 2
spawn.mapRect(850, -1100, 50, 300); //shute left 3
spawn.mapRect(830, -980, 50, 50); //shute left 4
spawn.mapRect(1075, -1000, 50, 300); //shute right 1
spawn.mapRect(1090, -1030, 50, 300); //shute right 2
spawn.mapRect(1100, -1100, 50, 300); //shute right 3
spawn.mapRect(1120, -980, 50, 50); //shute right 4
spawn.bodyRect(100, -1000, 50, 350);
spawn.bodyRect(100, -1015, 250, 15);
spawn.mapRect(-925, -1600, 100, 1000); //2-2 left wall
spawn.mapRect(725, -2150, 200, 750); //2-2 right wall
spawn.mapRect(725, -1200, 200, 200); //2-2 right wall 2
spawn.mapRect(300, -1000, 625, 50); //2 central ledge
level.fill.push({
x: 725,
y: -1400,
width: 200,
height: 200,
color: "rgba(0,0,0,0.1)"
});
level.fill.push({
x: 925,
y: -2150,
width: 150,
height: 2175,
color: "rgba(0,0,0,0.1)"
});
level.fill.push({
x: 925,
y: -3450,
width: 150,
height: 900,
color: "rgba(0,0,0,0.1)"
});
//section 3: upper left room and upper central room (gone through main portals 2 times)
spawn.mapRect(-1775, -1000, 700, 300); //3-1 floor
spawn.mapRect(-1900, -2300, 175, 1600); //3-1 left wall
spawn.mapRect(-1375, -1300, 300, 50); //3-1 platform 1
spawn.mapRect(-1600, -1650, 300, 50); //3-1 platform 2
spawn.mapRect(-1775, -2300, 700, 300); //3-1 ceiling
spawn.mapRect(-830, -1600, 300, 50); //2 upper left ledge
spawn.mapRect(250, -2150, 675, 50); //2 upper right ledge
spawn.mapRect(-925, -2300, 100, 400); //3-2 left wall
spawn.mapRect(-600, -2700, 1525, 150); //3-2 ceiling
spawn.mapRect(1075, -2150, 250, 150); //next to upper portal
level.fill.push({
x: -1730,
y: -2300,
width: 870,
height: 1600,
color: "rgba(0,0,0,0.1)"
});
//section 4: upper right portals
spawn.mapRect(1475, -2700, 150, 700); //4-1 left wall
spawn.mapRect(1775, -1650, 250, 150); //4-1 floor-ish
spawn.mapRect(1575, -1505, 450, 555); //below upper right portal
spawn.mapRect(1800, -2250, 400, 50); //4-1 platform 2
spawn.bodyRect(2200, -2250, 25, 300);
spawn.mapRect(2200, -1950, 400, 50); //4-1 platform 1
//spawn.bodyRect(2575, -2600, 25, 650);
spawn.mapRect(2600, -1650, 400, 50); //4-1 platform 0
spawn.mapRect(2200, -1350, 400, 50); //4-1 platform -1
spawn.bodyRect(2200, -1900, 25, 550);
spawn.bodyRect(2575, -1650, 25, 300);
spawn.mapRect(1780, -4200, 820, 1600); //top right corner
spawn.mapRect(800, -4200, 1800, -500); //4-2 ceiling
spawn.mapRect(1075, -3450, 250, 900); //4-2 center block
spawn.mapRect(800, -3450, 125, 900); //4-2 left wall
spawn.mapRect(1550, -4200, 310, 600); //4-2 upper right wall
level.fill.push({
x: 1800,
y: -2200,
width: 225,
height: 550,
color: "rgba(0,0,0,0.1)"
});
level.fill.push({
x: 1800,
y: -2600,
width: 400,
height: 400,
color: "rgba(0,0,0,0.1)"
});
level.fill.push({
x: 2200,
y: -2600,
width: 400,
height: 1250,
color: "rgba(0,0,0,0.1)"
});
//section 5: after portals (gone through main portals 3 times)
spawn.mapRect(-700, -2700, 100, 450); //5-1 right wall
spawn.mapRect(-1450, -2700, 900, 50); //5-1 ceiling
spawn.mapRect(-925, -2300, 325, 50); //5-1 right floor
level.fill.push({
x: -1450,
y: -2655,
width: 755,
height: 355,
color: "rgba(0,0,0,0.1)"
});
//top left corner stuff
if (true) {
spawn.mapRect(-1900, -2450, 250, 450); //
} else {
spawn.boost(-1650, -2310, 400);
spawn.mapRect(-2200, -2700, 450, 50); //
spawn.mapRect(-1850, -3000, 500, 50); //
}
//exit room
spawn.mapRect(350, -3000, 50, 100); //exit room left wall
spawn.mapRect(350, -3000, 450, -1700); //exit room ceiling
spawn.bodyRect(350, -2900, 50, 50); //door
spawn.bodyRect(350, -2850, 50, 50); //door
spawn.bodyRect(350, -2800, 50, 50); //door
spawn.bodyRect(350, -2750, 50, 50); //door
level.fillBG.push({
x: 375,
y: -3000,
width: 450,
height: 300,
color: "#d4f4f4"
});
spawn.debris(-800, -50, 400, 6); //16 debris per level
spawn.debris(-1650, -2300, 250, 4); //16 debris per level
spawn.debris(-750, -650, 750, 6); //16 debris per level
//mobs
spawn.randomMob(-650, -100, 0.7); //1-2 left
spawn.randomMob(100, -150, 0.3); //1-2 right
spawn.randomMob(-100, -400, 0); //1-3 right
//spawn.randomMob(-1500, -300, 0.3); //1-4 platform
spawn.randomMob(1450, -450, 0); //2-1 right
spawn.randomMob(1700, -800, 1); //2-1 off the edge. chance is 1 because some enemies just fall
spawn.randomGroup(-550, -1000, -0.3); //2-2
spawn.randomMob(-1550, -1800, 0.7); //3-1 upper platform
//spawn.randomMob(-1225, -1400, 0.3); //3-1 lower platform
spawn.randomMob(450, -2350, 0.3); //3-2 right ledge
//spawn.randomMob(1150, -2250, 0); //3-2 far right
spawn.randomGroup(2400, -2300, -0.3); //4-1 floating
spawn.randomMob(2400, -1450, 0); //4-1 platform -1
spawn.randomMob(2800, -1800, 0.5); //4-1 platform 0
spawn.randomMob(-1100, -2800, 0.5); //5-2 left
spawn.randomMob(-550, -2800, 0.5); //5-2 middle
if (simulation.difficulty > 3) {
if (Math.random() < 0.5) {
spawn.randomLevelBoss(450, -1350, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "shieldingBoss", "pulsarBoss", "laserBoss"]);
} else {
spawn.randomLevelBoss(-300, -3200, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "shieldingBoss", "pulsarBoss", "laserBoss"]);
}
}
powerUps.addRerollToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(7725, 2275);
},
};

View File

@@ -647,7 +647,6 @@ const m = {
m.energy -= dmg;
if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage
if (tech.isDeathAvoid && powerUps.research.count && !tech.isDeathAvoidedThisLevel) {
tech.isDeathAvoidedThisLevel = true
powerUps.research.changeRerolls(-1)
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span><br>${powerUps.research.count}`)

View File

@@ -112,11 +112,6 @@ const powerUps = {
document.getElementById("tech-anthropic").innerHTML = `-${powerUps.research.count}`
}
if (tech.renormalization && Math.random() < 0.37 && amount < 0) powerUps.spawn(m.pos.x, m.pos.y, "research");
if (tech.isResearchReality && amount < 0) {
m.switchWorlds()
simulation.trails()
simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`);
}
if (tech.isRerollHaste) {
if (powerUps.research.count === 0) {
tech.researchHaste = 0.66;
@@ -141,6 +136,11 @@ const powerUps = {
// simulation.makeTextLog(`${Math.max(0,powerUps.tech.lastTotalChoices - powerUps.tech.banishLog.length)} estimated <strong class='color-m'>tech</strong> choices remaining`)
simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - powerUps.tech.banishLog.length)}`)
}
if (tech.isResearchReality) {
m.switchWorlds()
simulation.trails()
simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`);
}
powerUps[type].effect();
},
},

View File

@@ -525,7 +525,9 @@ const simulation = {
level.levels.push("basement");
level.levels.push("detours");
level.levels.push("house");
level.levels.splice(0, 4); //remove 4 random levels to make up for adding the 4 community levels
level.levels.push("testChamber2");
// level.levels.push("vats");
level.levels.splice(0, 5); //remove some random levels to make up for adding the community levels
}
level.levels = shuffle(level.levels); //shuffles order of maps
level.levels.unshift("intro"); //add level to the start of the randomized levels list
@@ -699,6 +701,7 @@ const simulation = {
let holdTarget; //if player is holding something this remembers it before it gets deleted
if (m.holdingTarget) holdTarget = m.holdingTarget;
simulation.fallHeight = 3000;
m.fireCDcycle = 0
m.drop();
m.hole.isOn = false;
@@ -993,6 +996,7 @@ const simulation = {
for (let i = 0, len = cons.length; i < len; ++i) {
ctx.moveTo(cons[i].pointA.x, cons[i].pointA.y);
ctx.lineTo(cons[i].bodyB.position.x, cons[i].bodyB.position.y);
// ctx.lineTo(cons[i].bodyB.position.x + cons[i].pointB.x, cons[i].bodyB.position.y + cons[i].pointB.y);
}
for (let i = 0, len = consBB.length; i < len; ++i) {
ctx.moveTo(consBB[i].bodyA.position.x, consBB[i].bodyA.position.y);

View File

@@ -1579,7 +1579,7 @@ const spawn = {
}
};
},
pulsar(x, y, radius = 30) {
pulsar(x, y, radius = 40) {
mobs.spawn(x, y, 3, radius, "#f08");
let me = mob[mob.length - 1];
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
@@ -1587,10 +1587,11 @@ const spawn = {
me.radius *= 2
me.vertices[1].x = me.position.x + Math.cos(me.angle) * me.radius; //make one end of the triangle longer
me.vertices[1].y = me.position.y + Math.sin(me.angle) * me.radius;
me.fireCycle = 0
Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
me.fireCycle = Infinity
me.fireTarget = { x: 0, y: 0 }
me.pulseRadius = Math.min(400, 150 + simulation.difficulty * 3)
me.fireDelay = Math.max(70, 180 - simulation.difficulty)
me.pulseRadius = Math.min(400, 165 + simulation.difficulty * 3)
me.fireDelay = Math.max(75, 150 - simulation.difficulty * 0.5)
me.isFiring = false
me.onHit = function() {};
me.canSeeTarget = function() {
@@ -1681,7 +1682,7 @@ const spawn = {
this.torque += 0.000001 * this.inertia;
} else if (dot < -threshold) {
this.torque -= 0.000001 * this.inertia;
} else if (this.fireCycle > 90) { // aim
} else if (this.fireCycle > 60) { // aim
unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
this.fireTarget = Vector.add(this.vertices[1], unit)
if (!this.canSeeTarget()) return

View File

@@ -67,7 +67,7 @@
if (index === 'random') {
let options = [];
for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed()) options.push(i);
if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk && !tech.tech[i].isLore) options.push(i);
}
// give a random tech from the tech I don't have
if (options.length > 0) {
@@ -86,6 +86,12 @@
}
if (!found) return //if name not found don't give any tech
}
if (tech.isMetaAnalysis && tech.tech[index].isJunk) {
tech.giveTech('random', true)
for (let i = 0; i < 2; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "research");
return
}
if (tech.tech[index].isLost) tech.tech[index].isLost = false; //give specific tech
tech.tech[index].effect(); //give specific tech
tech.tech[index].count++
@@ -1176,8 +1182,8 @@
tech.isBotDamage = false
}
}, {
name: "bot replication",
description: "<strong class='color-dup'>duplicate</strong> your permanent <strong class='color-bot'>bots</strong><br>remove <strong>all</strong> of your <strong class='color-g'>guns</strong>",
name: "ersatz bots",
description: "<strong>double</strong> your permanent <strong class='color-bot'>bots</strong><br>remove <strong>all</strong> of your <strong class='color-g'>guns</strong>",
maxCount: 1,
count: 0,
frequency: 1,
@@ -2000,7 +2006,7 @@
frequency: 1,
isHealTech: true,
allowed() {
return m.maxHealth > 1 || tech.isArmorFromPowerUps
return m.health > 0.1 && (m.maxHealth > 1 || tech.isArmorFromPowerUps)
},
requires: "increased max health",
effect() {
@@ -2134,9 +2140,9 @@
count: 0,
frequency: 1,
allowed() {
return !tech.isImmortal && !tech.isResearchReality
return !tech.isImmortal && !tech.isResearchReality && level.onLevel < 6
},
requires: "not quantum immortality, perturbation theory",
requires: "before level 6, not quantum immortality, perturbation theory",
effect() {
tech.isSwitchReality = true;
},
@@ -2150,9 +2156,9 @@
count: 0,
frequency: 1,
allowed() {
return !tech.isImmortal && !tech.isSwitchReality
return !tech.isImmortal && !tech.isSwitchReality && (powerUps.research.count > 2 || build.isExperimentSelection)
},
requires: "not quantum immortality, many-worlds",
requires: "at least 2 research, not quantum immortality, many-worlds",
effect() {
tech.isResearchReality = true;
for (let i = 0; i < 11; i++) powerUps.spawn(m.pos.x + Math.random() * 10, m.pos.y + Math.random() * 10, "research", false);
@@ -2167,9 +2173,9 @@
count: 0,
frequency: 1,
allowed() {
return (powerUps.research.count > 1 || build.isExperimentSelection) && !tech.isSuperDeterminism && !tech.isRerollHaste
return (powerUps.research.count > 2 || build.isExperimentSelection) && !tech.isSuperDeterminism && !tech.isRerollHaste
},
requires: "not superdeterminism or Ψ(t) collapse<br>at least 2 research",
requires: "not superdeterminism or Ψ(t) collapse<br>at least 3 research",
effect() {
tech.renormalization = true;
},
@@ -2313,26 +2319,25 @@
remove() {
tech.isShieldAmmo = false;
}
}, {
name: "stimulated emission",
description: "<strong>20%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>but, after a <strong>collision</strong> eject <strong>1</strong> <strong class='color-m'>tech</strong>",
},
{
name: "meta-analysis",
description: "if you choose a <strong>junk</strong> <strong class='color-m'>tech</strong> you instead get a <br>random non-junk <strong class='color-m'>tech</strong> and spawn <strong>2</strong> <strong class='color-r'>research</strong>",
maxCount: 1,
count: 0,
frequency: 1,
frequency: 2,
allowed() {
return tech.duplicationChance() < 1
return tech.duplicateChance
},
requires: "below 100% duplication chance",
effect: () => {
tech.isBayesian = true
simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw
tech.maxDuplicationEvent()
requires: "replication",
effect() {
tech.isMetaAnalysis = true
},
remove() {
tech.isBayesian = false
if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal
tech.isMetaAnalysis = false
}
}, {
},
{
name: "replication",
description: "<strong>7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>add <strong>12</strong> junk <strong class='color-m'>tech</strong> to the potential pool",
maxCount: 9,
@@ -2354,7 +2359,28 @@
if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal
if (this.count > 1) tech.removeJunkTechFromPool(12)
}
}, {
},
{
name: "stimulated emission",
description: "<strong>20%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>but, after a <strong>collision</strong> eject <strong>1</strong> <strong class='color-m'>tech</strong>",
maxCount: 1,
count: 0,
frequency: 1,
allowed() {
return tech.duplicationChance() < 1
},
requires: "below 100% duplication chance",
effect: () => {
tech.isBayesian = true
simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw
tech.maxDuplicationEvent()
},
remove() {
tech.isBayesian = false
if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal
}
},
{
name: "futures exchange",
description: "clicking <strong style = 'font-size:150%;'>×</strong> to cancel a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>adds <strong>4.5%</strong> power up <strong class='color-dup'>duplication</strong> chance",
maxCount: 1,
@@ -2682,27 +2708,6 @@
tech.isSuperDeterminism = false;
}
},
// {
// name: "ammo technology",
// description: "</strong>double</strong> the <strong class='flicker'>frequency</strong> of finding <strong class='color-g'>gun</strong> <strong class='color-m'>tech</strong><br>spawn <strong>6</strong> <strong class='color-g'>ammo</strong>",
// maxCount: 1,
// count: 0,
// frequency: 1,
// isNonRefundable: true,
// // isExperimentHide: true,
// // isBadRandomOption: true,
// allowed() {
// return !tech.isEnergyNoAmmo
// },
// requires: "not exciton lattice",
// effect() {
// for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "ammo");
// for (let i = 0, len = tech.tech.length; i < len; i++) {
// if (tech.tech[i].isGunTech) tech.tech[i].frequency *= 2
// }
// },
// remove() {}
// },
//**************************************************
//************************************************** gun
//************************************************** tech
@@ -4352,23 +4357,6 @@
// }
// },
{
name: "plasma jet",
description: "increase <strong class='color-plasma'>plasma</strong> <strong>torch's</strong> range by <strong>27%</strong>",
isFieldTech: true,
maxCount: 9,
count: 0,
frequency: 1,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "plasma torch"
},
requires: "plasma torch",
effect() {
tech.isPlasmaRange += 0.27;
},
remove() {
tech.isPlasmaRange = 1;
}
}, {
name: "plasma-bot",
description: "a <strong class='color-bot'>bot</strong> uses <strong class='color-f'>energy</strong> to emit <strong class='color-plasma'>plasma</strong><br>that <strong class='color-d'>damages</strong> and <strong>pushes</strong> mobs",
isFieldTech: true,
@@ -4388,7 +4376,26 @@
remove() {
tech.plasmaBotCount = 0;
}
}, {
},
{
name: "plasma jet",
description: "increase <strong class='color-plasma'>plasma</strong> <strong>torch's</strong> range by <strong>30%</strong>",
isFieldTech: true,
maxCount: 9,
count: 0,
frequency: 1,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "plasma torch" && !tech.isExtruder
},
requires: "plasma torch, not micro-extruder",
effect() {
tech.isPlasmaRange += 0.3;
},
remove() {
tech.isPlasmaRange = 1;
}
},
{
name: "micro-extruder",
description: "<strong class='color-plasma'>plasma</strong> <strong>torch</strong> extrudes a thin <strong class='color-plasma'>hot</strong> wire<br>increases <strong class='color-d'>damage</strong>, and <strong class='color-f'>energy</strong> drain",
isFieldTech: true,
@@ -4396,9 +4403,9 @@
count: 0,
frequency: 1,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "plasma torch"
return m.fieldUpgrades[m.fieldMode].name === "plasma torch" && tech.isPlasmaRange === 1
},
requires: "plasma torch",
requires: "plasma torch, not plasma jet",
effect() {
tech.isExtruder = true;
},
@@ -5790,5 +5797,6 @@
isFlipFlopOn: null,
isFlipFlopLevelReset: null,
isFlipFlopDamage: null,
isFlipFlopEnergy: null
isFlipFlopEnergy: null,
isMetaAnalysis: null
}