newLevel - towers
  please give feedback
boost level elements can now be pointed at any angle

paradigm shift costs 1 health, but cost increases after each use
  ejecting with paradigm shift tech sets their frequency to zero, so they don't show up again
polyurethane foam - makes more foam from super balls
bubble fusion - now works with any shield, but only once per mob
  so it triggers from the shieldingBoss
collider - has a higher chance to form tech vs. other power ups

removed all ON/OFF tech
  I just don't think they are fun

JUNK tech - wall jump

fixed some bugs

player damage reduction adjustment: 0.9x -> 0.89x per level per difficulty mode (1,2,4,5)
  on easy that's 0.28 -> 0.245 by level 12 (a 12% player damage nerf)
  on why a 50% player damage nerf by level 12
This commit is contained in:
landgreen
2024-04-28 09:55:12 -07:00
parent 3ce6becec9
commit 773ee5c1ae
12 changed files with 1012 additions and 621 deletions

View File

@@ -3790,7 +3790,7 @@ const b = {
this.force.y += this.mass * 0.001;
if (Matter.Query.collides(this, [player]).length) {
this.endCycle = 0
m.energy -= 0.05
m.energy -= 0.04
if (m.energy < 0) m.energy = 0
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
@@ -3828,8 +3828,8 @@ const b = {
if (!who.isInvulnerable) {
if (tech.oneSuperBall) mobs.statusStun(who, 120) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds)
if (tech.isFoamBall) {
for (let i = 0, len = 5 * this.mass; i < len; i++) {
const radius = 5 + 8 * Math.random()
for (let i = 0, len = 6 * this.mass; i < len; i++) {
const radius = 6 + 9 * Math.random()
const velocity = { x: Math.max(0.5, 2 - radius * 0.1), y: 0 }
b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius)
}

View File

@@ -113,32 +113,7 @@ function collisionChecks(event) {
m.damage(dmg);
return
}
if (tech.isFlipFlop) {
if (tech.isFlipFlopOn) {
tech.isFlipFlopOn = false
if (document.getElementById("tech-flip-flop")) document.getElementById("tech-flip-flop").innerHTML = ` = <strong>OFF</strong>`
m.eyeFillColor = 'transparent'
m.damage(dmg);
} else {
tech.isFlipFlopOn = true //immune to damage this hit, lose immunity for next hit
if (document.getElementById("tech-flip-flop")) document.getElementById("tech-flip-flop").innerHTML = ` = <strong>ON</strong>`
m.eyeFillColor = m.fieldMeterColor //'#0cf'
if (!tech.isFlipFlopHarm) m.damage(dmg);
}
if (tech.isFlipFlopHealth) {
m.setMaxHealth();
for (let i = 0; i < powerUp.length; i++) {
if (powerUp[i].name === "heal") {
const oldSize = powerUp[i].size
powerUp[i].size = powerUps.heal.size() //update current heals
const scale = powerUp[i].size / oldSize
Matter.Body.scale(powerUp[i], scale, scale); //grow
}
}
}
} else {
m.damage(dmg); //normal damage
}
m.damage(dmg); //normal damage
if (tech.isCollisionRealitySwitch && m.alive) {
m.switchWorlds()

View File

@@ -1430,7 +1430,7 @@ window.addEventListener("keydown", function (event) {
simulation.loop = simulation.normalLoop
if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'none'
simulation.makeTextLog("", 0);
} else { //if (keys[191])
} else {
simulation.testing = true;
simulation.loop = simulation.testingLoop
if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'inline'

View File

@@ -4,13 +4,12 @@ let cons = []; //all constraints between a point and a body
let consBB = []; //all constraints between two bodies
let composite = [] //rotors and other map elements that don't fit
const level = {
isEndlessFall: false,
fallMode: "",
defaultZoom: 1400,
onLevel: -1,
levelsCleared: 0,
// playableLevels: ["pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion"],
//see level.populateLevels: (initial, ... , reservoir or factory, reactor, ... , subway, final) added later
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock"],
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock", "towers"],
communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass", "cantilever", "tlinat", "ruins", "ace", "crimsonTowers", "LaunchSite", "shipwreck", "unchartedCave", "dojo", "arena", "soft"],
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"],
levels: [],
@@ -42,9 +41,9 @@ const level = {
// requestAnimationFrame(() => { tech.giveTech("optical amplifier") });
// for (let i = 0; i < 1; ++i) tech.giveTech("combinatorial optimization")
// tech.giveTech("Pareto efficiency")
// for (let i = 0; i < 1; ++i) tech.giveTech("Higgs mechanism")
// for (let i = 0; i < 1; ++i) tech.giveTech("active cooling")
// for (let i = 0; i < 1; ++i) tech.giveTech("heuristics")
for (let i = 0; i < 1; ++i) tech.giveTech("collider")
// for (let i = 0; i < 1; ++i) tech.giveTech("anthropic principle")
// for (let i = 0; i < 1; ++i) tech.giveTech("bubble fusion")
// requestAnimationFrame(() => { for (let i = 0; i < 10; i++) b.orbitBot(m.pos, false) });
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("ersatz bots") });
// for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide")
@@ -55,13 +54,13 @@ const level = {
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research");
// for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling");
// spawn.mapRect(575, -700, 25, 425); //block mob line of site on testing
// level.testing();
// level.towers();
// for (let i = 0; i < 1; ++i) spawn.laserLayer(1400, -500)
// Matter.Body.setPosition(player, { x: -200, y: -3330 });
// for (let i = 0; i < 4; ++i) spawn.laserLayer(1300, -500 + 100 * Math.random())
// for (let i = 0; i < 1; ++i) spawn.stinger(1900, -500)
// for (let i = 0; i < 1; ++i) spawn.dragonFlyBoss(1900, -500)
// for (let i = 0; i < 1; ++i) spawn.powerUpBossBaby(1900, -500)
// spawn.beetleBoss(1900, -500, 25)
// spawn.zombie(-3000, -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color)
// for (let i = 0; i < 5; ++i) spawn.starter(1000 + 1000 * Math.random(), -500 + 300 * Math.random())
@@ -78,7 +77,9 @@ const level = {
// simulation.isAutoZoom = false; //look in close
// simulation.zoomScale *= 0.5;
// simulation.setZoom();
// for (let i = 0; i < 3; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech");
// tech.addJunkTechToPool(0.7)
// for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech");
// for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 450, m.pos.y + 50 * Math.random(), "boost");
// for (let i = 0; i < 100; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "ammo");
// for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "field", false);
@@ -137,15 +138,7 @@ const level = {
mob[mob.length - 1].isDecoupling = true //so you can find it to remove
for (let j = 0, len = 4; j < len; j++) powerUps.spawn(level.exit.x + 100 * (Math.random() - 0.5), level.exit.y - 100 + 100 * (Math.random() - 0.5), "research", false)
}
// if (tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) {
if ((tech.isRelay || tech.isFlipFlop) && !tech.isFlipFlopOn) {
tech.isFlipFlopOn = true
if (tech.isFlipFlopHealth) m.setMaxHealth()
if (tech.isRelayEnergy) m.setMaxEnergy()
m.eyeFillColor = m.fieldMeterColor
simulation.makeTextLog(`tech.isFlipFlopOn <span class='color-symbol'>=</span> true`);
}
// if (m.plasmaBall) m.plasmaBall.reset()
if (m.plasmaBall) m.plasmaBall.fire()
if (localSettings.entanglement && localSettings.entanglement.levelName === level.levels[level.onLevel]) {
const flip = localSettings.entanglement.isHorizontalFlipped === simulation.isHorizontalFlipped ? 1 : -1
@@ -180,23 +173,22 @@ const level = {
if (b.activeGun !== null && b.activeGun !== undefined && b.guns[b.activeGun].name !== "laser") {
const ammoPerOrb = b.guns[b.activeGun].ammoPack
const a = Math.ceil(rate * b.guns[b.activeGun].ammo / ammoPerOrb)
powerUps.spawnDelay("ammo", a);
powerUps.spawnDelay("ammo", a, 4);
simulation.makeTextLog(`${(rate * 100).toFixed(0)}<span class='color-symbol'>%</span> <span class='color-m'>interest</span> on <span class='color-g'>ammo</span> <span class='color-symbol'>=</span> ${a > 20 ? a + powerUps.orb.ammo(1) : powerUps.orb.ammo(a)}`)
}
if (powerUps.research.count > 0) {
const r = Math.ceil(rate * powerUps.research.count)
simulation.makeTextLog(`${(rate * 100).toFixed(0)}<span class='color-symbol'>%</span> <span class='color-m'>interest</span> on <span class='color-r'>research</span> <span class='color-symbol'>=</span> ${r > 20 ? r + powerUps.orb.research(1) : powerUps.orb.research(r)}`)
powerUps.spawnDelay("research", r);
powerUps.spawnDelay("research", r, 4);
}
if (m.coupling > 0) {
const c = Math.ceil(rate * m.coupling)
powerUps.spawnDelay("coupling", c);
powerUps.spawnDelay("coupling", c, 4);
simulation.makeTextLog(`${(rate * 100).toFixed(0)}<span class='color-symbol'>%</span> <span class='color-m'>interest</span> on <span class='color-coupling'>coupling</span> <span class='color-symbol'>=</span> ${c > 20 ? c + powerUps.orb.coupling(1) : powerUps.orb.coupling(c)}`)
}
const healPerOrb = (powerUps.heal.size() / 40 / (simulation.healScale ** 0.25)) ** 2
const h = Math.ceil(rate * m.health / healPerOrb)
powerUps.spawnDelay("heal", h);
powerUps.spawnDelay("heal", h, 4);
simulation.makeTextLog(`${(rate * 100).toFixed(0)}<span class='color-symbol'>%</span> <span class='color-m'>interest</span> on <span class='color-h'>health</span> <span class='color-symbol'>=</span> ${h > 20 ? h + powerUps.orb.heal(1) : powerUps.orb.heal(h)}`)
// trying to spawn smaller heals
@@ -230,7 +222,7 @@ const level = {
difficultyIncrease(num = 1) {
for (let i = 0; i < num; i++) {
simulation.difficulty++
m.dmgScale *= 0.9; //damage done by player decreases each level
m.dmgScale *= 0.89; //damage done by player decreases each level
if (simulation.accelScale < 6) simulation.accelScale *= 1.024 //mob acceleration increases each level
if (simulation.CDScale > 0.15) simulation.CDScale *= 0.964 //mob CD time decreases each level
}
@@ -241,7 +233,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.9; //damage done by player decreases each level
m.dmgScale /= 0.89; //damage done by player decreases each level
if (simulation.accelScale > 1) simulation.accelScale /= 1.024 //mob acceleration increases each level
if (simulation.CDScale < 1) simulation.CDScale /= 0.964 //mob CD time decreases each level
}
@@ -801,65 +793,147 @@ const level = {
return who
},
boost(x, y, height = 1000) { //height is how high the player will be flung above y
who = map[map.length] = Matter.Bodies.fromVertices(x + 50, y + 35, Vertices.fromPath("120 40 -120 40 -50 -40 50 -40"), {
collisionFilter: {
category: cat.body,
mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
},
boostBounds: {
min: {
x: x,
y: y - 20
boost(x, y, height = 1000, angle = Math.PI / 2) { //height is how high the player will be flung above y
if (angle !== Math.PI / 2) { //angle !== 3 * Math.PI / 2
angle *= -1
who = map[map.length] = Matter.Bodies.fromVertices(x + 50, y + 35, Vertices.fromPath("80 40 -80 40 -50 -40 50 -40"), {
collisionFilter: {
category: cat.body,
mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
},
max: {
x: x + 100,
y: y
}
},
yVelocity: -1.21 * Math.sqrt(Math.abs(height)),
query() {
// check for collisions
query = (who) => {
if (Matter.Query.region(who, this.boostBounds).length > 0) {
list = Matter.Query.region(who, this.boostBounds)
Matter.Body.setVelocity(list[0], {
x: list[0].velocity.x + (Math.random() - 0.5) * 2.5, //add a bit of horizontal drift to reduce endless bounces
y: this.yVelocity //give a upwards velocity
});
yVelocity: 1.21 * Math.sqrt(Math.abs(height)),
query() {
// check for collisions
const rayVector = Vector.add(this.position, Vector.rotate({ x: 100, y: 0 }, angle))
query = (who) => {
const list = Matter.Query.ray(who, this.position, rayVector, 100)
if (list.length > 0) {
Matter.Body.setVelocity(list[0].bodyA, Vector.rotate({ x: this.yVelocity, y: 0 }, angle));
}
}
}
query(body)
query(mob)
query(bullet)
query(powerUp)
//player collision
if (Matter.Query.region([player], this.boostBounds).length > 0 && !input.down) {
m.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts
m.hardLandCD = 0 // disable hard landing
if (player.velocity.y > 26) {
Matter.Body.setVelocity(player, {
x: player.velocity.x,
y: -15 //gentle bounce if coming down super fast
});
} else {
Matter.Body.setVelocity(player, {
x: player.velocity.x + (Math.random() - 0.5) * 2.5,
y: this.yVelocity //give a upwards velocity that will put the player that the height desired
});
query(body)
query(mob)
query(bullet)
query(powerUp)
//player collision
const list = Matter.Query.ray([player], this.position, rayVector, 100)
if (list.length > 0) {
Matter.Body.setVelocity(player, Vector.rotate({ x: this.yVelocity, y: 0 }, angle));
m.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts
m.hardLandCD = 0 // disable hard landing
}
}
//draw
ctx.fillStyle = "rgba(200,0,255,0.15)";
ctx.fillRect(this.boostBounds.min.x, this.boostBounds.min.y - 10, 100, 30);
ctx.fillStyle = "rgba(200,0,255,0.05)";
ctx.fillRect(this.boostBounds.min.x, this.boostBounds.min.y - 50, 100, 70);
// ctx.fillStyle = "rgba(200,0,255,0.02)";
// ctx.fillRect(x, y - 120, 100, 120);
},
});
return who
// if (Matter.Query.region([player], this.boostBounds).length > 0 && !input.down) {
// m.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts
// m.hardLandCD = 0 // disable hard landing
// if (player.velocity.y > 26) {
// Matter.Body.setVelocity(player, {
// x: player.velocity.x,
// y: -15 //gentle bounce if coming down super fast
// });
// } else {
// Matter.Body.setVelocity(player, {
// x: player.velocity.x + (Math.random() - 0.5) * 2.5,
// y: this.yVelocity //give a upwards velocity that will put the player that the height desired
// });
// }
// }
//draw
const v1 = this.vertices[0]
const v2 = this.vertices[1]
let unit = Vector.rotate({ x: 60, y: 0 }, angle)
let v3 = Vector.add(v2, unit)
let v4 = Vector.add(v1, unit)
// ctx.beginPath();
// ctx.strokeStyle = "#000";
// ctx.stroke()
ctx.beginPath();
ctx.moveTo(v1.x, v1.y)
ctx.lineTo(v2.x, v2.y)
ctx.lineTo(v3.x, v3.y)
ctx.lineTo(v4.x, v4.y)
ctx.fillStyle = "rgba(200,0,255,0.05)";
ctx.fill()
// ctx.strokeStyle = "#000";
// ctx.stroke()
unit = Vector.rotate({ x: 20, y: 0 }, angle)
v3 = Vector.add(v2, unit)
v4 = Vector.add(v1, unit)
ctx.beginPath();
ctx.moveTo(v1.x, v1.y)
ctx.lineTo(v2.x, v2.y)
ctx.lineTo(v3.x, v3.y)
ctx.lineTo(v4.x, v4.y)
ctx.fillStyle = "rgba(200,0,255,0.15)";
ctx.fill()
},
});
Matter.Body.rotate(who, angle + Math.PI / 2);
return who
} else {
who = map[map.length] = Matter.Bodies.fromVertices(x + 50, y + 35, Vertices.fromPath("120 40 -120 40 -50 -40 50 -40"), {
collisionFilter: {
category: cat.body,
mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
},
boostBounds: {
min: {
x: x,
y: y - 20
},
max: {
x: x + 100,
y: y
}
},
yVelocity: -1.21 * Math.sqrt(Math.abs(height)),
query() {
// check for collisions
query = (who) => {
if (Matter.Query.region(who, this.boostBounds).length > 0) {
list = Matter.Query.region(who, this.boostBounds)
Matter.Body.setVelocity(list[0], {
x: list[0].velocity.x + (Math.random() - 0.5) * 2.5, //add a bit of horizontal drift to reduce endless bounces
y: this.yVelocity //give a upwards velocity
});
}
}
query(body)
query(mob)
query(bullet)
query(powerUp)
//player collision
if (Matter.Query.region([player], this.boostBounds).length > 0 && !input.down) {
m.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts
m.hardLandCD = 0 // disable hard landing
if (player.velocity.y > 26) {
Matter.Body.setVelocity(player, {
x: player.velocity.x,
y: -15 //gentle bounce if coming down super fast
});
} else {
Matter.Body.setVelocity(player, {
x: player.velocity.x + (Math.random() - 0.5) * 2.5,
y: this.yVelocity //give a upwards velocity that will put the player that the height desired
});
}
}
//draw
ctx.fillStyle = "rgba(200,0,255,0.15)";
ctx.fillRect(this.boostBounds.min.x, this.boostBounds.min.y - 10, 100, 30);
ctx.fillStyle = "rgba(200,0,255,0.05)";
ctx.fillRect(this.boostBounds.min.x, this.boostBounds.min.y - 50, 100, 70);
// ctx.fillStyle = "rgba(200,0,255,0.02)";
// ctx.fillRect(x, y - 120, 100, 120);
},
});
return who
}
},
elevator(x, y, width, height, maxHeight, force = 0.003, friction = {
up: 0.01,
@@ -2570,27 +2644,6 @@ const level = {
ctx.fillStyle = "#ccc"
ctx.fill()
//power up dispenser
// ctx.beginPath()
// for (let i = 2; i < 10; i++) {
// ctx.moveTo(2000, -100 * i)
// ctx.lineTo(2080, -100 * i)
// }
// ctx.strokeStyle = "#ddd"
// ctx.lineWidth = 5;
// ctx.stroke();
// ctx.beginPath()
// for (let i = 2; i < 10; i++) {
// ctx.arc(2040, -100 * i, 30, 0, 2 * Math.PI);
// ctx.moveTo(2040, -100 * i)
// }
// ctx.fillStyle = "rgba(0,0,0,0.3)"
// ctx.fill()
// ctx.fillStyle = "rgba(240,255,255,0.5)"
// ctx.fillRect(2000, -1000, 80, 700)
//exit room
ctx.fillStyle = "#f2f2f2"
ctx.fillRect(2600, -600, 400, 300)
@@ -4198,6 +4251,250 @@ const level = {
// if (simulation.difficulty > 1) spawn.randomLevelBoss(2200, -1300);
powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
towers() {
// simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
level.difficultyIncrease(10 * 4) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true
const isFlipped = (simulation.isHorizontalFlipped && Math.random() < 0.33) ? true : false
level.announceMobTypes()
if (isFlipped) {
level.setPosToSpawn(9150 + 50, -2230 - 25);
level.exit.x = -100 - 50;
level.exit.y = -50 + 25;
leftRoomColor = "#cff"
rightRoomColor = "rgba(0,0,0,0.13)"
} else {
level.setPosToSpawn(-100, -50);
level.exit.x = 9150;
level.exit.y = -2230;
}
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance
level.fallMode = "position"; //must set level.fallModeBounds in this mode to prevent player getting stuck left or right
level.fallModeBounds = { left: level.enter.x, right: level.exit.x } //used with level.fallMode = "position";
simulation.fallHeight = 5000 //level.enter.y - 4000
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit
level.defaultZoom = 2500
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#cdd9df";
powerUps.spawnStartingPowerUps(6300, 1025)
const boost1 = level.boost(7560, 1480, 1700, 1.75)
const boost2 = level.boost(7098, 0, 1250, Math.PI / 3) //x,y,push,angle radians
const boost3 = level.boost(9700, -730, 1050, 1.95)
const boost4 = level.boost(4300, -720, 1500, 1.25)
const boost5 = level.boost(3000, -1215, 3000, 1.25)
const train1 = level.transport(3650, 100, 415, 500, 8); //x,y,width.height,VxGoal,force
const train2 = level.transport(1250, 100, 415, 500, -8); //x,y,width.height,VxGoal,force
const train3 = level.transport(4050, 100, 415, 500, 8); //x,y,width.height,VxGoal,force
let portal1, portal2
portal1 = level.portal({
x: 3675,
y: -2225 + 1025
}, -Math.PI / 2, { //up
x: 3675,
y: -375
}, Math.PI / 2) //down
portal2 = level.portal({
x: 6300,
y: -1225
}, -Math.PI / 2, { //up
x: 6300,
y: -375
}, Math.PI / 2) //down
level.custom = () => {
boost1.query();
boost2.query();
boost3.query();
boost4.query();
boost5.query();
//trains oscillate back and forth and act like they are bouncing off each other
if (train1.position.x < 2850) {
train1.changeDirection(true) //go right
} else if (train1.position.x > 3850) {
train1.changeDirection(false) //go left
}
if (train2.position.x < 1450) {
train2.changeDirection(true) //go right
} else if (train2.position.x > 2450) {
train2.changeDirection(false) //go left
}
if (train3.position.x < 4250) {
train3.changeDirection(true) //go right
} else if (train3.position.x > 5250) {
train3.changeDirection(false) //go left
}
train1.move();
train2.move();
train3.move();
ctx.fillStyle = "rgba(0,0,0,0.25)"
ctx.fillRect(1250, 121, 4200, 6)
ctx.fillStyle = "rgba(50,70,100,0.04)"
ctx.fillRect(2500, -10000, 1800, 30000);
ctx.fillRect(8300, -10000, 1800, 30000);
ctx.fillRect(-500, -10000, 1800, 30000);
ctx.fillRect(5400, -10000, 1800, 30000);
portal1[2].query()
portal1[3].query()
portal2[2].query()
portal2[3].query()
ctx.fillStyle = "#cff"
if (isFlipped) {
ctx.fillRect(-350, -300, 525, 325); //entrance typically
} else {
ctx.fillRect(8925, -2575, 525, 400) //exit typically
}
level.exit.drawAndCheck();
level.enter.draw();
};
level.customTopLayer = () => {
ctx.fillStyle = "rgba(0,0,0,0.13)"
ctx.fillRect(8300, -1950, 1550, 1275);
ctx.fillRect(5400, 875, 1800, 650);
ctx.fillRect(2950, -2200, 875, 1050);
if (isFlipped) {
ctx.fillRect(8925, -2575, 575, 400) //exit typically
} else {
ctx.fillRect(-350, -300, 525, 325); //entrance typically
}
ctx.fillStyle = "rgba(0,0,0,0.5)"
ctx.fillRect(7175, -1515, 125, 180);
portal1[0].draw();
portal1[1].draw();
portal1[2].draw();
portal1[3].draw();
portal2[0].draw();
portal2[1].draw();
portal2[2].draw();
portal2[3].draw();
};
// four large rounded squares
let a = 900 //side length
let c = 100 //corner offset
// spawn.mapVertex(3400, -1300, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${a - c} ${a - c} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off
// spawn.mapVertex(9200, -1300, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${a - c} ${a - c} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off
// spawn.mapVertex(6300, 900, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${a - c} ${a - c} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off
spawn.mapVertex(400, 900, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${a - c} ${a - c} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off
//lower 1st zone entrance /exit
spawn.mapRect(-400, -350, 575, 75);
spawn.mapRect(-400, -300, 75, 375);
spawn.mapRect(100, -325, 75, 175);
spawn.mapRect(100, -10, 75, 50);
//2nd zone upper hollow square
spawn.mapVertex(5650 - 2900, 900 - 2200, `${-a} ${-a + c} ${-a + c} ${-a} ${-400} ${-a} ${-400} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //1/2 square with edges cut off
spawn.mapVertex(6950 - 2900, 900 - 2200, `${400} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${a - c} ${a - c} ${a} ${400} ${a}`); //1/2 square with edges cut off
// spawn.mapRect(5600 - 2900, 1400 - 2200, 1350, 400);
spawn.mapRect(2950, -1175, 650, 775);
spawn.mapRect(3750, -1175, 100, 775);
spawn.mapRect(3575, -1025, 200, 475);
//4th zone far right hollow square near exit
spawn.mapVertex(9200, -2050, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${-600} ${-a} ${-600}`); //square with edges cut off --- hollow top
spawn.mapVertex(9200, -550, `${-a} ${600} ${a} ${600} ${a} ${a - c} ${a - c} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off --- hollow bottom
spawn.mapRect(9800, -2100, 300, 1600); //hollow left wall
spawn.mapVertex(8175, -1425, "-1400 -90 350 -90 400 -40 400 40 350 90 -1400 90");
spawn.mapVertex(6856, -1425, "300 -90 -350 -90 -400 -40 -400 40 -350 90 300 90");
//exit housing
spawn.mapRect(8925, -2575, 575, 75);
if (isFlipped) {
spawn.mapRect(8925, -2550, 75, 400);
spawn.mapRect(9425, -2550, 75, 125);
spawn.mapRect(9425, -2215, 75, 50);
spawn.bodyRect(9425, -2425, 75, 210);
} else {
spawn.mapRect(9425, -2550, 75, 400);
spawn.mapRect(8925, -2550, 75, 125);
spawn.mapRect(8925, -2215, 75, 50);
}
//lower 3rd zone
spawn.mapVertex(6300, 450, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${0} ${-a} ${0}`); //square with edges cut off --- hollow top
spawn.mapVertex(6550, 1650, `${-a} ${600} ${a + 500} ${600} ${a + 500} ${a - c} ${a - c + 500} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off --- hollow bottom
spawn.mapVertex(6300, 1200, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40");
//upper 3rd zone
a = 400 //side length
c = 50 //corner offset
spawn.mapVertex(6300, -800, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${a - c} ${a - c} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off
spawn.mapVertex(5800, -1425, "-300 -40 -250 -90 250 -90 300 -40 300 40 250 90 -250 90 -300 40");
spawn.mapVertex(5485, -1850, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40");
spawn.mapVertex(7365, -1850, "-650 -40 -600 -90 600 -90 650 -40 650 40 600 90 -600 90 -650 40"); //long
spawn.mapVertex(6300, -2175, "-300 -40 -250 -90 250 -90 300 -40 300 40 250 90 -250 90 -300 40"); //highest
spawn.mapVertex(4450, -1850, "-200 -40 -150 -90 150 -90 200 -40 200 40 150 90 -150 90 -200 40");
spawn.mapVertex(5500, -300, "-200 -60 -170 -90 170 -90 200 -60 200 60 170 90 -170 90 -200 60");
spawn.mapVertex(4600, -590, "-500 -90 170 -90 200 -60 200 60 170 90 -500 90");
//no debris on this level, so spawn some heals and ammo
powerUps.chooseRandomPowerUp(6275, 1425);
powerUps.chooseRandomPowerUp(3350, -1250);
powerUps.chooseRandomPowerUp(9550, -750);
//random blocks
spawn.bodyRect(7725, -2200, 150, 250, 0.2);
spawn.bodyRect(4625, -825, 75, 125, 0.2);
spawn.bodyRect(3250, -1200, 25, 25, 0.2);
spawn.bodyRect(3375, -1275, 25, 75, 0.2);
spawn.bodyRect(3450, -1200, 50, 25, 0.2);
spawn.bodyRect(2825, -2225, 25, 25, 0.2);
spawn.bodyRect(4075, -2225, 50, 25, 0.2);
spawn.bodyRect(8850, -800, 75, 100, 0.2);
spawn.bodyRect(6900, -100, 75, 100, 0.2);
spawn.bodyRect(8975, -1575, 50, 50, 0.2);
spawn.bodyRect(5725, -1700, 125, 175, 0.2);
spawn.bodyRect(6850, -1725, 150, 200, 0.2);
//mobs
spawn.randomMob(5700, -75, 0);
spawn.randomMob(6200, -100, 0);
spawn.randomMob(6900, -100, 0.1);
spawn.randomMob(5550, -500, 0.1);
spawn.randomMob(4675, -850, 0.1);
spawn.randomMob(4450, -2050, 0.1);
spawn.randomMob(4050, -2325, 0.1);
spawn.randomMob(2850, -2325, 0.1);
spawn.randomMob(3350, -1325, 0.2);
spawn.randomMob(5300, -2050, 0.2);
spawn.randomMob(5675, -2050, 0.2);
spawn.randomMob(5850, -1625, 0.3);
spawn.randomMob(6775, -1600, 0.3);
spawn.randomMob(7700, -1625, 0.4);
spawn.randomMob(7850, -2000, 0.4);
spawn.randomMob(7225, -2000, 0.4);
spawn.randomMob(6350, -2400, 0.5);
spawn.randomMob(8850, -1650, 0.5);
spawn.randomMob(9500, -1300, 0.5);
spawn.randomMob(9250, -900, 0.5);
spawn.randomMob(8600, -875, 0.6);
spawn.randomMob(5575, 1350, 0.6);
spawn.randomMob(6075, 1025, 0.6);
spawn.randomMob(6300, 1025, 0.7);
spawn.randomMob(6525, 1425, 0.8);
spawn.randomMob(7125, 1450, 0.9);
// spawn.randomMob(8600, -2325, 0.7);
// spawn.randomMob(8650, -2825, 0.8);
// spawn.randomMob(9225, -2850, 0.9);
// spawn.randomMob(8525, -2375, 0.9);
spawn.randomGroup(4925, -2850, 1);
if (simulation.difficulty > 1) {
spawn.randomLevelBoss(7275, -2475);
spawn.secondaryBossChance(8400, -1025)
}
powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
factory() {
level.announceMobTypes()
// simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -4211,7 +4508,7 @@ const level = {
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit
level.defaultZoom = 1500
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#d0d2d4s";
document.body.style.backgroundColor = "#d0d2d4";
// color.map = "#262a2f"
let isPowerLeft = true
const movers = []
@@ -5596,7 +5893,7 @@ const level = {
},
pavilion() {
level.announceMobTypes()
level.isEndlessFall = true;
level.fallMode = "start";
const vanish = []
level.exit.x = -850;
level.exit.y = -1485;
@@ -6449,7 +6746,7 @@ const level = {
},
satellite() {
level.announceMobTypes()
level.isEndlessFall = true;
level.fallMode = "start";
const boost1 = level.boost(5825, 235, 1400)
const elevator = level.elevator(4210, -1265, 380, 50, -3450) //, 0.003, { up: 0.01, down: 0.2 }
level.custom = () => {
@@ -6626,7 +6923,7 @@ const level = {
},
rooftops() {
level.announceMobTypes()
level.isEndlessFall = true;
level.fallMode = "start";
// level.fallPosition = { x: 5000, y:-4000}
const elevator = level.elevator(1450, -990, 235, 45, -2000)
const boost1 = level.boost(4950, 0, 1100)
@@ -6635,7 +6932,6 @@ const level = {
boost1.query();
elevator.move();
elevator.drawTrack();
ctx.fillStyle = "#d4f4f4"
if (isBackwards) {
ctx.fillRect(-650, -2300, 440, 300)
@@ -6643,7 +6939,6 @@ const level = {
ctx.fillRect(3460, -700, 1090, 800)
}
level.exit.drawAndCheck();
level.enter.draw();
};
@@ -6815,7 +7110,7 @@ const level = {
},
aerie() {
level.announceMobTypes()
level.isEndlessFall = true;
level.fallMode = "start";
const boost1 = level.boost(-425, 100, 1400)
const boost2 = level.boost(5350, 275, 2850);
@@ -7045,7 +7340,7 @@ const level = {
},
skyscrapers() {
level.announceMobTypes()
level.isEndlessFall = true;
level.fallMode = "start";
const boost1 = level.boost(475, 0, 1300)
const boost2 = level.boost(4450, 0, 1300);
level.custom = () => {
@@ -7184,11 +7479,8 @@ const level = {
},
highrise() {
level.announceMobTypes()
level.isEndlessFall = true;
const elevator1 = level.elevator(-790, -190, 180, 25, -1150, 0.0025, {
up: 0.01,
down: 0.2
}, true) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) {
level.fallMode = "start";
const elevator1 = level.elevator(-790, -190, 180, 25, -1150, 0.0025, { up: 0.01, down: 0.2 }, true) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) {
elevator1.addConstraint();
// const button1 = level.button(-500, -200)
const toggle1 = level.toggle(-300, -200) //(x,y,isOn,isLockOn = true/false)
@@ -7470,7 +7762,7 @@ const level = {
},
warehouse() {
level.announceMobTypes()
level.isEndlessFall = true;
level.fallMode = "start";
level.custom = () => {
ctx.fillStyle = "#444" //light fixtures
ctx.fillRect(-920, -505, 40, 10)
@@ -27198,7 +27490,7 @@ const level = {
}
};
},
shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance(), isExtraShield = false) {
shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance()) {
if (this.allowShields && Math.random() < chance) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(255,255,255,0.9)");
let me = mob[mob.length - 1];
@@ -27207,7 +27499,6 @@ const level = {
me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isUnblockable = true
me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet;
consBB[consBB.length] = Constraint.create({
@@ -27229,6 +27520,12 @@ const level = {
me.shieldTargetID = target.id
target.isShielded = true;
if (target.shieldCount > 0) {
target.shieldCount++
} else {
target.shieldCount = 1
}
me.shieldCount = target.shieldCount //used with "bubble fusion"
target.shieldID = me.id
me.onDeath = function () {
//clear isShielded status from target
@@ -28466,7 +28763,7 @@ const level = {
}
};
},
shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance(), isExtraShield = false) {
shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance()) {
if (this.allowShields && Math.random() < chance) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(255,255,255,0.9)");
let me = mob[mob.length - 1];
@@ -28475,7 +28772,6 @@ const level = {
me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isUnblockable = true
me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet;
consBB[consBB.length] = Constraint.create({
@@ -28497,6 +28793,12 @@ const level = {
me.shieldTargetID = target.id
target.isShielded = true;
if (target.shieldCount > 0) {
target.shieldCount++
} else {
target.shieldCount = 1
}
me.shieldCount = target.shieldCount //used with "bubble fusion"
target.shieldID = me.id
me.onDeath = function () {
//clear isShielded status from target

View File

@@ -1161,6 +1161,7 @@ const mobs = {
this.onDeath(this); //custom death effects
this.removeConsBB();
this.alive = false; //triggers mob removal in mob[i].replace(i)
console.log(this.shieldCount)
if (this.isDropPowerUp) {
// if (true) {
@@ -1306,7 +1307,7 @@ const mobs = {
tech.cloakDuplication -= 0.01
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
}
} else if (tech.isShieldAmmo && this.shield && !this.isExtraShield && this.isDropPowerUp) {
} else if (tech.isShieldAmmo && this.shield && this.shieldCount === 1) {
let type = tech.isEnergyNoAmmo ? "heal" : "ammo"
if (Math.random() < 0.4) {
type = "heal"

View File

@@ -8,7 +8,7 @@ const m = {
// let vector = Vertices.fromPath("0 40 50 40 50 115 0 115 30 130 20 130"); //player as a series of vertices
let vertices = Vertices.fromPath("0,40, 50,40, 50,115, 30,130, 20,130, 0,115, 0,40"); //player as a series of vertices
playerBody = Bodies.fromVertices(0, 0, vertices);
jumpSensor = Bodies.rectangle(0, 46, 36, 6, {
jumpSensor = Bodies.rectangle(0, 46, 36, 6, { //(0, 46, 50, 6, { //for wall jumping
//this sensor check if the player is on the ground to enable jumping
sleepThreshold: 99999999999,
isSensor: true
@@ -545,7 +545,7 @@ const m = {
},
baseHealth: 1,
setMaxHealth(isMessage) {
m.maxHealth = m.baseHealth + tech.extraMaxHealth + 3 * tech.isFallingDamage + 4 * tech.isFlipFlop * tech.isFlipFlopOn * tech.isFlipFlopHealth
m.maxHealth = m.baseHealth + tech.extraMaxHealth + 3 * tech.isFallingDamage
document.getElementById("health-bg").style.width = `${Math.floor(300 * m.maxHealth)}px`
if (isMessage) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-h'>maxHealth</span> <span class='color-symbol'>=</span> ${m.maxHealth.toFixed(2)}`)
if (m.health > m.maxHealth) m.health = m.maxHealth;
@@ -2178,7 +2178,7 @@ const m = {
}
},
setMaxEnergy(isMessage = true) {
m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2.66 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + 1.5 * (m.fieldMode === 1) + (m.fieldMode === 0 || m.fieldMode === 1) * 0.05 * m.coupling + 0.77 * tech.isStandingWaveExpand
m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2.66 * tech.isGroundState + 1.5 * (m.fieldMode === 1) + (m.fieldMode === 0 || m.fieldMode === 1) * 0.05 * m.coupling + 0.77 * tech.isStandingWaveExpand
if (isMessage) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-f'>maxEnergy</span> <span class='color-symbol'>=</span> ${(m.maxEnergy.toFixed(2))}`)
},
fieldMeterColor: "#0cf",

View File

@@ -247,12 +247,14 @@ const powerUps = {
if (powerUp[i].isDuplicated) {
if (Math.random() < 0.003 && !m.isBodiesAsleep) { // (1-0.003)^240 = chance to be removed after 4 seconds, 240 = 4 seconds * 60 cycles per second
b.explosion(powerUp[i].position, 175 + (11 + 3 * Math.random()) * powerUp[i].size);
Matter.Composite.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1);
if (powerUp[i]) {
Matter.Composite.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1);
}
break
}
if (Math.random() < 0.3) { //draw electricity
const mag = 4 + powerUp[i].size / 5
const mag = Math.max(1, 4 + powerUp[i].size / 5)
let unit = Vector.rotate({ x: mag, y: mag }, 2 * Math.PI * Math.random())
let path = { x: powerUp[i].position.x + unit.x, y: powerUp[i].position.y + unit.y }
ctx.beginPath();
@@ -328,7 +330,7 @@ const powerUps = {
simulation.circleFlare(value);
}
if (tech.isCancelRerolls) {
for (let i = 0, len = 10 + 4 * Math.random(); i < len; i++) {
for (let i = 0, len = 8 + 4 * Math.random(); i < len; i++) {
let spawnType
if (Math.random() < 0.4 && !tech.isEnergyNoAmmo) {
spawnType = "ammo"
@@ -340,7 +342,7 @@ const powerUps = {
powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), spawnType, false);
}
}
if (tech.isCancelCouple) powerUps.spawnDelay("coupling", 8)
if (tech.isCancelCouple) powerUps.spawnDelay("coupling", 7)
if (tech.isCancelTech && tech.cancelTechCount === 0 && type !== "entanglement") {
tech.cancelTechCount++
// powerUps.research.use('tech')
@@ -524,7 +526,7 @@ const powerUps = {
name: "heal",
color: "#0eb",
size() {
return Math.sqrt(0.1 + 0.25) * 40 * (simulation.healScale ** 0.25) * Math.sqrt(tech.largerHeals * (tech.isHalfHeals ? 0.5 : 1)) * (tech.isFlipFlopOn && tech.isFlipFlopHealth ? Math.sqrt(2) : 1); //(simulation.healScale ** 0.25) gives a smaller radius as heal scale goes down
return Math.sqrt(0.1 + 0.25) * 40 * (simulation.healScale ** 0.25) * Math.sqrt(tech.largerHeals * (tech.isHalfHeals ? 0.5 : 1)); //(simulation.healScale ** 0.25) gives a smaller radius as heal scale goes down
},
effect() {
if (!tech.isEnergyHealth && m.alive) {
@@ -819,30 +821,92 @@ const powerUps = {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
},
// junkTechText(choose, click) { //old code with yahoo images
// const techCountText = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count + 1}x)` : "";
// const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-size: contain;background-repeat: no-repeat;background-image: url('img/junk.webp');"`
// if (!localSettings.isHideImages) {
// setTimeout(() => { //delay so that the html element exists
// if (tech.tech[choose].url === undefined) { //if on url has been set yet
// const url = "https://images.search.yahoo.com/search/images?p=" + tech.tech[choose].name;
// fetch(url, { signal: AbortSignal.timeout(1000) }) //give up if it takes over 1 second
// .then((response) => response.text())
// .then((html) => {
// const parser = new DOMParser();
// const doc = parser.parseFromString(html, "text/html");
// const elements = doc.getElementsByClassName("ld");
// // console.log(i, elements[i].getAttribute("data"), JSON.parse(elements[i].getAttribute("data")).iurl)
// const index = Math.floor(Math.random() * 4) //randomly choose from the first 4 images
// if (parseInt(JSON.parse(elements[index].getAttribute("data")).s.slice(0, -2)) < 500) { //make sure it isn't too big
// tech.tech[choose].url = JSON.parse(elements[index].getAttribute("data")).iurl //store the url
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')` //make the url the background image
// } else if (parseInt(JSON.parse(elements[index + 1].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
// tech.tech[choose].url = JSON.parse(elements[index + 1].getAttribute("data")).iurl
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
// } else if (parseInt(JSON.parse(elements[index + 2].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
// tech.tech[choose].url = JSON.parse(elements[index + 2].getAttribute("data")).iurl
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
// }
// });
// } else {
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
// }
// }, 1);
// }
// return `<div id = "junk-${choose}" class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}"${style}>
// <div class="card-text">
// <div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
// ${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
// },
// junkTechText(choose, click) {
// const techCountText = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count + 1}x)` : "";
// const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-size: contain;background-repeat: no-repeat;background-image: url('img/junk.webp');"`
// if (!localSettings.isHideImages) {
// setTimeout(() => { //delay so that the html element exists
// if (tech.tech[choose].url === undefined) { //if on url has been set yet
// const url = "https://images.search.yahoo.com/search/images?p=" + tech.tech[choose].name;
// fetch(url, { signal: AbortSignal.timeout(1000) }) //give up if it takes over 1 second
// .then((response) => response.text())
// .then((html) => {
// const parser = new DOMParser();
// const doc = parser.parseFromString(html, "text/html");
// const elements = doc.getElementsByClassName("ld");
// // console.log(i, elements[i].getAttribute("data"), JSON.parse(elements[i].getAttribute("data")).iurl)
// const index = Math.floor(Math.random() * 4) //randomly choose from the first 4 images
// if (parseInt(JSON.parse(elements[index].getAttribute("data")).s.slice(0, -2)) < 500) { //make sure it isn't too big
// tech.tech[choose].url = JSON.parse(elements[index].getAttribute("data")).iurl //store the url
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')` //make the url the background image
// } else if (parseInt(JSON.parse(elements[index + 1].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
// tech.tech[choose].url = JSON.parse(elements[index + 1].getAttribute("data")).iurl
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
// } else if (parseInt(JSON.parse(elements[index + 2].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
// tech.tech[choose].url = JSON.parse(elements[index + 2].getAttribute("data")).iurl
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
// }
// });
// } else {
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
// }
// }, 1);
// }
// return `<div id = "junk-${choose}" class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}"${style}>
// <div class="card-text">
// <div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
// ${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
// },
junkTechText(choose, click) {
const techCountText = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count + 1}x)` : "";
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-size: contain;background-repeat: no-repeat;background-image: url('img/junk.webp');"`
if (!localSettings.isHideImages) {
setTimeout(() => { //delay so that the html element exists
if (tech.tech[choose].url === undefined) { //if on url has been set yet
const url = "https://images.search.yahoo.com/search/images?p=" + tech.tech[choose].name;
const url = `https://api.openverse.engineering/v1/images/?q=${tech.tech[choose].name}`;
fetch(url, { signal: AbortSignal.timeout(1000) }) //give up if it takes over 1 second
.then((response) => response.text())
.then((html) => {
const parser = new DOMParser();
const doc = parser.parseFromString(html, "text/html");
const elements = doc.getElementsByClassName("ld");
// console.log(i, elements[i].getAttribute("data"), JSON.parse(elements[i].getAttribute("data")).iurl)
const index = Math.floor(Math.random() * 4) //randomly choose from the first 4 images
if (parseInt(JSON.parse(elements[index].getAttribute("data")).s.slice(0, -2)) < 500) { //make sure it isn't too big
tech.tech[choose].url = JSON.parse(elements[index].getAttribute("data")).iurl //store the url
.then((response) => response.json())
.then((responseJson) => {
if (responseJson.results.length > 0) {
const index = Math.floor(Math.random() * responseJson.results.length) //randomly choose from the images
tech.tech[choose].url = responseJson.results[index].url //store the url
document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')` //make the url the background image
} else if (parseInt(JSON.parse(elements[index + 1].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
tech.tech[choose].url = JSON.parse(elements[index + 1].getAttribute("data")).iurl
document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
} else if (parseInt(JSON.parse(elements[index + 2].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
tech.tech[choose].url = JSON.parse(elements[index + 2].getAttribute("data")).iurl
document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
}
});
} else {
@@ -878,7 +942,6 @@ const powerUps = {
// console.log(options.length)
if (options.length > 0 || !tech.isSuperDeterminism) {
let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + 2 * (m.fieldMode === 8)))
if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay
function removeOption(index) {
for (let i = 0; i < options.length; i++) {
if (options[i] === index) {
@@ -940,8 +1003,6 @@ const powerUps = {
if (i !== m.fieldMode) options.push(i);
}
let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + 2 * (m.fieldMode === 8)))
if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay
function removeOption(index) {
for (let i = 0; i < options.length; i++) {
if (options[i] === index) {
@@ -1016,7 +1077,6 @@ const powerUps = {
}
//set total choices
let totalChoices = (tech.isDeterminism ? 1 : 3 + tech.extraChoices + 2 * (m.fieldMode === 8))
if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay
if (optionLengthNoDuplicates < totalChoices + 1) { //if not enough options for all the choices
totalChoices = optionLengthNoDuplicates
if (tech.isBanish) { //when you run out of options eject banish
@@ -1214,7 +1274,7 @@ const powerUps = {
} else if (tech.tech[choose].isSkin) {
text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isInstant) {
text += powerUps.instantTechTextTechText(choose, `powerUps.choose('tech',${choose})`)
text += powerUps.instantTechText(choose, `powerUps.choose('tech',${choose})`)
} else { //normal tech
text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`)
}
@@ -1229,14 +1289,14 @@ const powerUps = {
}
},
},
spawnDelay(type, count) {
count *= 2
spawnDelay(type, count, delay = 2) {
count *= delay
let cycle = () => {
if (count > 0) {
if (m.alive) requestAnimationFrame(cycle);
if (!simulation.paused && !simulation.isChoosing) { //&& !(simulation.cycle % 2)
count--
if (!(count % 2)) {
if (!(count % delay)) {
const where = { x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) }
powerUps.spawn(where.x, where.y, type);
}
@@ -1256,18 +1316,6 @@ const powerUps = {
b.mine(who.position, { x: 0, y: 0 }, 0)
}
}
if (tech.isRelay) {
if (tech.isFlipFlopOn) {
tech.isFlipFlopOn = false
if (document.getElementById("tech-switch")) document.getElementById("tech-switch").innerHTML = ` = <strong>OFF</strong>`
m.eyeFillColor = 'transparent'
} else {
tech.isFlipFlopOn = true //immune to damage this hit, lose immunity for next hit
if (document.getElementById("tech-switch")) document.getElementById("tech-switch").innerHTML = ` = <strong>ON</strong>`
m.eyeFillColor = m.fieldMeterColor //'#0cf'
}
if (tech.isRelayEnergy) m.setMaxEnergy();
}
},
spawnRandomPowerUp(x, y) { //mostly used after mob dies, doesn't always return a power up
if (!tech.isEnergyHealth && (Math.random() * Math.random() - 0.3 > Math.sqrt(m.health)) || Math.random() < 0.04) { //spawn heal chance is higher at low health
@@ -1449,8 +1497,10 @@ const powerUps = {
// tech.removeTech(index)
// } else {
// }
tech.tech[index].frequency = 0 //banish tech
powerUps.ejectTech(index)
m.damage(0.04)
m.damage(tech.pauseEjectTech * 0.01)
tech.pauseEjectTech *= 1.2
document.getElementById(`${index}-pause-tech`).style.textDecoration = "line-through"
document.getElementById(`${index}-pause-tech`).style.animation = ""
document.getElementById(`${index}-pause-tech`).onclick = null
@@ -1478,15 +1528,9 @@ const powerUps = {
smallIndexes.push(i)
}
}
if (bigIndexes.length > 0) {
// console.log("at least 1 big will always spilt")
const index = bigIndexes[Math.floor(Math.random() * bigIndexes.length)]
for (let i = 0; i < 3; i++) powerUps.directSpawn(where.x, where.y, options[Math.floor(Math.random() * options.length)], false)
Matter.Composite.remove(engine.world, powerUp[index]);
powerUp.splice(index, 1);
} else if (smallIndexes.length > 2 && Math.random() < 0.33) {
// console.log("no big, at least 3 small can combine")
if (smallIndexes.length > 2 && Math.random() < 0.66) { // console.log("no big, at least 3 small can combine")
for (let j = 0; j < 3; j++) {
for (let i = 0; i < powerUp.length; i++) {
if (powerUp[i].name === "heal" || powerUp[i].name === "research" || powerUp[i].name === "ammo" || powerUp[i].name === "coupling" || powerUp[i].name === "boost") {
@@ -1499,8 +1543,13 @@ const powerUps = {
options = ["tech", "gun", "field"]
powerUps.directSpawn(where.x, where.y, options[Math.floor(Math.random() * options.length)], false)
} else if (smallIndexes.length > 0) {
// console.log("no big, at least 1 small will swap flavors")
} else if (bigIndexes.length > 0 && Math.random() < 0.5) { // console.log("at least 1 big can spilt")
const index = bigIndexes[Math.floor(Math.random() * bigIndexes.length)]
for (let i = 0; i < 3; i++) powerUps.directSpawn(where.x, where.y, options[Math.floor(Math.random() * options.length)], false)
Matter.Composite.remove(engine.world, powerUp[index]);
powerUp.splice(index, 1);
} else if (smallIndexes.length > 0) { // console.log("no big, at least 1 small will swap flavors")
const index = Math.floor(Math.random() * powerUp.length)
options = options.filter(e => e !== powerUp[index].name); //don't repeat the current power up type
powerUps.directSpawn(where.x, where.y, options[Math.floor(Math.random() * options.length)], false)

View File

@@ -184,7 +184,7 @@ const simulation = {
fpsCapDefault: 72, //use to change fpsCap back to normal after a hit from a mob
isCommunityMaps: false,
cyclePaused: 0,
fallHeight: 6000, //below this y position the player dies
fallHeight: 6000, //below this y position the player will teleport to start, take damage, or teleport to the sky based on the value of level.fallMode
lastTimeStamp: 0, //tracks time stamps for measuring delta
delta: 1000 / 60, //speed of game engine //looks like it has to be 16.6666 to match player input
buttonCD: 0,
@@ -435,10 +435,10 @@ const simulation = {
} else if (tech.tech[i].count > 0 && !tech.tech[i].isInstant) {
if (text) text += "<br>" //add a new line, but not on the first line
text += tech.tech[i].name
if (tech.tech[i].nameInfo) {
text += tech.tech[i].nameInfo
tech.tech[i].addNameInfo();
}
// if (tech.tech[i].nameInfo) {
// text += tech.tech[i].nameInfo
// tech.tech[i].addNameInfo();
// }
if (tech.tech[i].count > 1) text += ` (${tech.tech[i].count}x)`
}
}
@@ -933,22 +933,8 @@ const simulation = {
m.energy = m.maxEnergy + (m.energy - m.maxEnergy) * tech.overfillDrain //every second energy above max energy loses 25%
if (m.energy > 1000000) m.energy = 1000000
}
if (tech.isFlipFlopEnergy && m.immuneCycle < m.cycle) {
if (tech.isFlipFlopOn) {
if (m.immuneCycle < m.cycle) m.energy += 0.2;
} else {
m.energy -= 0.01;
if (m.energy < 0) m.energy = 0
}
}
if (tech.relayIce && tech.isFlipFlopOn) {
for (let j = 0; j < tech.relayIce; j++) {
for (let i = 0, len = 3 + Math.ceil(9 * Math.random()); i < len; i++) b.iceIX(2)
}
}
if (m.pos.y > simulation.fallHeight) { // if 4000px deep
if (level.isEndlessFall) {
if (level.fallMode === "start") {
//infinite falling. teleport to sky after falling
simulation.ephemera.push({
@@ -957,7 +943,6 @@ const simulation = {
do() {
this.count--
if (this.count < 0 || m.onGround) simulation.removeEphemera(this.name)
// console.log(player.velocity.y)
if (player.velocity.y > 70) Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.99 });
if (player.velocity.y > 90) Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.99 });
},
@@ -976,13 +961,36 @@ const simulation = {
m.angle = Math.atan2(simulation.mouseInGame.y - m.pos.y, simulation.mouseInGame.x - m.pos.x);
// move bots
for (let i = 0; i < bullet.length; i++) {
if (bullet[i].botType) {
Matter.Body.setPosition(bullet[i], Vector.sub(bullet[i].position, change));
// Matter.Body.setPosition(bullet[i], Vector.add(player.position, { x: 250 * (Math.random() - 0.5), y: 250 * (Math.random() - 0.5) }));
// Matter.Body.setVelocity(bullet[i], { x: 0, y: 0 });
}
if (bullet[i].botType) Matter.Body.setPosition(bullet[i], Vector.sub(bullet[i].position, change));
}
} else {
} else if (level.fallMode === "position") { //fall and stay in the same horizontal position
simulation.ephemera.push({
name: "slow player",
count: 180, //cycles before it self removes
do() {
this.count--
if (this.count < 0 || m.onGround) simulation.removeEphemera(this.name)
if (player.velocity.y > 70) Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.99 });
if (player.velocity.y > 90) Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.99 });
},
})
const before = { x: player.position.x, y: player.position.y, }
let posXClamped = Math.min(Math.max(level.fallModeBounds.left, player.position.x), level.fallModeBounds.right)
Matter.Body.setPosition(player, { x: posXClamped, y: level.enter.y - 4000 });
// translate camera smoothly to preserve illusion to endless fall
const change = { x: before.x - posXClamped, y: before.y - player.position.y }
m.transX += change.x
m.transY += change.y
simulation.mouseInGame.x = (simulation.mouse.x - canvas.width2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.width2 - m.transX;
simulation.mouseInGame.y = (simulation.mouse.y - canvas.height2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.height2 - m.transY;
m.angle = Math.atan2(simulation.mouseInGame.y - m.pos.y, simulation.mouseInGame.x - m.pos.x);
// move bots
for (let i = 0; i < bullet.length; i++) {
if (bullet[i].botType) Matter.Body.setPosition(bullet[i], Vector.sub(bullet[i].position, change));
}
} else { //get hurt and go to start
Matter.Body.setVelocity(player, { x: 0, y: 0 });
Matter.Body.setPosition(player, { x: level.enter.x + 50, y: level.enter.y - 20 });
// m.damage(0.02 * simulation.difficultyMode);
@@ -1049,7 +1057,7 @@ const simulation = {
do() {
if (Matter.Query.point(map, m.pos).length > 0 || Matter.Query.point(map, player.position).length > 0) {
this.count--
// console.log('halp, stuck in map!', Matter.Query.point(map, m.pos))
if (this.count < 0) {
simulation.removeEphemera(this.name)
Matter.Body.setVelocity(player, { x: 0, y: 0 });
@@ -1116,7 +1124,7 @@ const simulation = {
clearNow: false,
clearMap() {
level.isProcedural = false;
level.isEndlessFall = false;
level.fallMode = "";
ctx.setTransform(1, 0, 0, 1, 0, 0);
if (m.alive) {
if (tech.isLongitudinal) b.guns[3].waves = []; //empty array of wave bullets
@@ -1370,7 +1378,6 @@ const simulation = {
// window.getSelection().addRange(range);
// document.execCommand("copy");
// window.getSelection().removeAllRanges();
// console.log(`spawn.mapRect(${simulation.getCoords.pos1.x}, ${simulation.getCoords.pos1.y}, ${simulation.getCoords.pos2.x - simulation.getCoords.pos1.x}, ${simulation.getCoords.pos2.y - simulation.getCoords.pos1.y}); //`);
// }
// }
// },
@@ -1544,15 +1551,9 @@ const simulation = {
const circleCollisions = [];
for (const line of outerCollisions) {
for (const vertex of line) {
// console.log('hi')
const distance = Math.sqrt((vertex.x - pos.x) ** 2 + (vertex.y - pos.y) ** 2)
const angle = Math.atan2(vertex.y - pos.y, vertex.x - pos.x);
// const queryPoint = {
// x: Math.cos(angle) * (distance - 1) + pos.x,
// y: Math.sin(angle) * (distance - 1) + pos.y
// }
const queryPoint = { x: Math.cos(angle + Math.PI) + vertex.x, y: Math.sin(angle + Math.PI) + vertex.y }
if (Math.abs(distance - radius) < 1 && Matter.Query.ray(map, pos, queryPoint).length == 0) circleCollisions.push(vertex)
}
}
@@ -1917,7 +1918,6 @@ const simulation = {
const y = round(simulation.constructMouseDownPosition.y)
const dx = Math.max(25, round(simulation.mouseInGame.x) - x)
const dy = Math.max(25, round(simulation.mouseInGame.y) - y)
// console.log(e.button)
if (e.button === 1) {
if (level.isProcedural) {
simulation.outputMapString(`spawn.randomMob(x+${x}, ${y}, 0);\n`);
@@ -1965,8 +1965,8 @@ const simulation = {
});
//undo last element added after you press z
document.body.addEventListener("keydown", (e) => { // e.keyCode z=90 m=77 b=66 shift = 16 c = 67
if (simulation.testing && e.keyCode === 90 && simulation.constructMapString.length) {
document.body.addEventListener("keydown", (event) => { // e.keyCode z=90 m=77 b=66 shift = 16 c = 67
if (simulation.testing && event.code === "KeyZ" && simulation.constructMapString.length) {
if (simulation.constructMapString[simulation.constructMapString.length - 1][6] === 'm') { //remove map from current level
const index = map.length - 1
Matter.Composite.remove(engine.world, map[index]);

View File

@@ -1691,6 +1691,7 @@ const spawn = {
powerUps.spawnBossPowerUp(me.position.x, me.position.y)
powerUps.spawn(me.position.x, me.position.y, "heal");
powerUps.spawn(me.position.x, me.position.y, "ammo");
powerUps.spawn(me.position.x, me.position.y, "ammo");
} else if (!m.isCloak) {
me.foundPlayer();
}
@@ -1698,7 +1699,7 @@ const spawn = {
me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction
me.damageReduction = 0
me.invulnerabilityCountDown = 25 + simulation.difficulty
me.invulnerabilityCountDown = 30 + simulation.difficulty
me.onHit = function () { //run this function on hitting player
if (powerUps.ejectTech()) {
powerUps.ejectGraphic("150, 138, 255");
@@ -1713,10 +1714,7 @@ const spawn = {
if (vertices > 3) {
this.isDropPowerUp = false;
spawn.powerUpBossBaby(this.position.x, this.position.y, vertices - 1)
Matter.Body.setVelocity(mob[mob.length - 1], {
x: this.velocity.x,
y: this.velocity.y
})
Matter.Body.setVelocity(mob[mob.length - 1], { x: this.velocity.x, y: this.velocity.y })
}
for (let i = 0; i < powerUp.length; i++) powerUp[i].collisionFilter.mask = cat.map | cat.powerUp
};
@@ -1770,15 +1768,16 @@ const spawn = {
powerUps.spawnBossPowerUp(me.position.x, me.position.y)
powerUps.spawn(me.position.x, me.position.y, "heal");
powerUps.spawn(me.position.x, me.position.y, "ammo");
powerUps.spawn(me.position.x, me.position.y, "ammo");
} else if (!m.isCloak) {
me.foundPlayer();
}
me.damageReduction = 0.15 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
// me.isInvulnerable = true
// me.startingDamageReduction = me.damageReduction
// me.damageReduction = 0
// me.invulnerabilityCountDown = 60 + simulation.difficulty * 2
me.damageReduction = 0.22 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction
me.damageReduction = 0
me.invulnerabilityCountDown = 30 + simulation.difficulty
me.onHit = function () { //run this function on hitting player
if (powerUps.ejectTech()) {
@@ -1794,10 +1793,7 @@ const spawn = {
if (vertices > 3) {
this.isDropPowerUp = false;
spawn.powerUpBoss(this.position.x, this.position.y, vertices - 1)
Matter.Body.setVelocity(mob[mob.length - 1], {
x: this.velocity.x,
y: this.velocity.y
})
Matter.Body.setVelocity(mob[mob.length - 1], { x: this.velocity.x, y: this.velocity.y })
}
for (let i = 0; i < powerUp.length; i++) powerUp[i].collisionFilter.mask = cat.map | cat.powerUp
};
@@ -1843,22 +1839,22 @@ const spawn = {
// me.constrainPowerUps()
me.do = function () {
this.stroke = `hsl(0,0%,${80 + 25 * Math.sin(simulation.cycle * 0.01)}%)`
// if (this.isInvulnerable) {
// if (this.invulnerabilityCountDown > 0) {
// this.invulnerabilityCountDown--
// 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 = 20;
// ctx.strokeStyle = "rgba(255,255,255,0.7)";
// ctx.stroke();
// } else {
// this.isInvulnerable = false
// this.damageReduction = this.startingDamageReduction
// }
// }
if (this.isInvulnerable) {
if (this.invulnerabilityCountDown > 0) {
this.invulnerabilityCountDown--
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 {
this.isInvulnerable = false
this.damageReduction = this.startingDamageReduction
}
}
//steal all power ups
// for (let i = 0; i < Math.min(powerUp.length, this.vertices.length); i++) {
// powerUp[i].collisionFilter.mask = 0
@@ -6898,9 +6894,7 @@ const spawn = {
ctx.moveTo(this.vertices[this.vertices.length - 1].x, this.vertices[this.vertices.length - 1].y)
const phase = (this.vertices.length + 1) * this.cycle / this.maxCycles
if (phase > 1) ctx.lineTo(this.vertices[0].x, this.vertices[0].y)
for (let i = 1; i < phase - 1; i++) {
ctx.lineTo(this.vertices[i].x, this.vertices[i].y)
}
for (let i = 1; i < phase - 1; i++) ctx.lineTo(this.vertices[i].x, this.vertices[i].y)
ctx.lineWidth = 5
ctx.strokeStyle = "rgb(255,255,255)"
ctx.stroke();
@@ -7584,7 +7578,7 @@ const spawn = {
}
};
},
shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance(), isExtraShield = false) {
shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance()) {
if (this.allowShields && Math.random() < chance) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)");
let me = mob[mob.length - 1];
@@ -7593,7 +7587,6 @@ const spawn = {
me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isUnblockable = true
me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet;
consBB[consBB.length] = Constraint.create({
@@ -7615,7 +7608,14 @@ const spawn = {
me.shieldTargetID = target.id
target.isShielded = true;
if (target.shieldCount > 0) {
target.shieldCount++
} else {
target.shieldCount = 1
}
me.shieldCount = target.shieldCount //used with "bubble fusion"
target.shieldID = me.id
me.onDeath = function () {
//clear isShielded status from target
for (let i = 0, len = mob.length; i < len; i++) {
@@ -8210,12 +8210,6 @@ const spawn = {
}
}
},
// bodyRect(x, y, width, height, chance = 1, properties = { friction: 0.05, frictionAir: 0.001 }) {
// if (Math.random() < chance) body[body.length] = Bodies.rectangle(x + width / 2, y + height / 2, width, height, properties);
// },
// bodyVertex(x, y, vector, properties) { //adds shape to body array
// body[body.length] = Matter.Bodies.fromVertices(x, y, Vertices.fromPath(vector), properties);
// },
bodyRect(x, y, width, height, chance = 1, properties = { friction: 0.05, frictionAir: 0.001 }) { //this is the command that adds blocks to the world in the middle of a level
if (Math.random() < chance) {
body[body.length] = Bodies.rectangle(x + width / 2, y + height / 2, width, height, properties);

View File

@@ -19,6 +19,7 @@ const tech = {
//remove lore if it's your first time playing since it's confusing
//also remove lore if cheating
tech.removeCount = 0;
tech.pauseEjectTech = 1; //used in paradigm shift
lore.techCount = 0;
if (simulation.isCheating || localSettings.runCount < 1) { //simulation.isCommunityMaps ||
for (let i = 0, len = tech.tech.length; i < len; i++) {
@@ -231,7 +232,6 @@ const tech = {
if (m.isSneakAttack && m.sneakAttackCycle + Math.min(100, 0.66 * (m.cycle - m.enterCloakCycle)) > m.cycle) dmg *= 4.5 * (1 + 0.033 * m.coupling)
if (tech.deathSkipTime) dmg *= 1 + 0.6 * tech.deathSkipTime
if (tech.isTechDebt) dmg *= tech.totalCount > 20 ? Math.pow(0.85, tech.totalCount - 20) : 4 - 0.15 * tech.totalCount
if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555
if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.71828
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
if (tech.isDamageForGuns) dmg *= 1 + 0.22 * Math.max(0, b.inventory.length - 1)
@@ -545,7 +545,7 @@ const tech = {
}
},
{
name: "hyperpolarization",
name: "repolarization",
descriptionFunction() {
return `the <strong class= 'color-d'> damage</strong> from <strong> depolarization</strong> <br>resets <strong>1.25 seconds</strong> sooner after a mob <strong>dies</strong>`
},
@@ -826,7 +826,7 @@ const tech = {
}
if (gunTechPool.length) {
const index = Math.floor(Math.random() * gunTechPool.length)
console.log(gunTechPool, index, gunTechPool[index], tech.tech[gunTechPool[index]].name)
// console.log(gunTechPool, index, gunTechPool[index], tech.tech[gunTechPool[index]].name)
simulation.makeTextLog(`<span class='color-var'>tech</span>.giveTech("<span class='color-text'>${tech.tech[gunTechPool[index]].name}</span>")`, 360)
// tech.tech[gunTechPool[index]].isInstant = true //makes it not remove properly under paradigm shift
tech.giveTech(gunTechPool[index]) // choose from the gun pool
@@ -1390,7 +1390,7 @@ const tech = {
},
{
name: "thermal runaway",
description: "after mobs <strong>die</strong><br>they <strong class='color-e'>explode</strong>",
description: "after mobs <strong>die</strong> they <strong class='color-e'>explode</strong>",
maxCount: 1,
count: 0,
frequency: 1,
@@ -1472,7 +1472,7 @@ const tech = {
{
name: "bubble fusion",
descriptionFunction() {
return `after destroying a mob's natural <strong>shield</strong><br>spawn <strong>1-2</strong> ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`
return `after destroying a mob's <strong>shield</strong><br>spawn <strong>1-2</strong> ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)} <em>(once per mob)</em>`
},
maxCount: 1,
count: 0,
@@ -2295,7 +2295,7 @@ const tech = {
},
{
name: "decorrelation",
description: "if your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> are unused for <strong>2</strong> seconds<br><strong>0.3x</strong> <strong class='color-defense'>damage taken</strong>",
description: "if your <strong class='color-g'>gun</strong> and <strong class='color-f'>field</strong> are unused for <strong>2</strong> seconds<br><strong>0.3x</strong> <strong class='color-defense'>damage taken</strong>",
maxCount: 1,
count: 0,
frequency: 1,
@@ -2313,7 +2313,7 @@ const tech = {
},
{
name: "anticorrelation",
description: "if your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> are unused for <strong>2</strong> seconds<br><strong>2x</strong> <strong class='color-d'>damage</strong>",
description: "if your <strong class='color-g'>gun</strong> and <strong class='color-f'>field</strong> are unused for <strong>2</strong> seconds<br><strong>2x</strong> <strong class='color-d'>damage</strong>",
maxCount: 1,
count: 0,
frequency: 1,
@@ -2422,285 +2422,285 @@ const tech = {
tech.isBlockPowerUps = false
}
},
{
name: "NOR gate",
description: "if <strong>flip-flop</strong> is <strong class='color-flop'>OFF</strong><br>become <strong>invulnerable</strong> to your next collision",
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isFlipFlop
},
requires: "flip-flop",
effect() {
tech.isFlipFlopHarm = true //do you have this tech
},
remove() {
tech.isFlipFlopHarm = false
}
},
{
name: "shape-memory alloy",
descriptionFunction() {
return `if <strong>flip-flop</strong> is <strong class='color-flop'>ON</strong><br><strong>+400</strong> maximum <strong class='color-h'>health</strong> and <strong>2x</strong> ${powerUps.orb.heal()} effect`
},
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isFlipFlop
},
requires: "flip-flop",
effect() {
tech.isFlipFlopHealth = true;
m.setMaxHealth();
for (let i = 0; i < powerUp.length; i++) {
if (powerUp[i].name === "heal") {
const oldSize = powerUp[i].size
powerUp[i].size = powerUps.heal.size() //update current heals
const scale = powerUp[i].size / oldSize
Matter.Body.scale(powerUp[i], scale, scale); //grow
}
}
},
remove() {
tech.isFlipFlopHealth = false;
m.setMaxHealth();
for (let i = 0; i < powerUp.length; i++) {
if (powerUp[i].name === "heal") {
const oldSize = powerUp[i].size
powerUp[i].size = powerUps.heal.size() //update current heals
const scale = powerUp[i].size / oldSize
Matter.Body.scale(powerUp[i], scale, scale); //grow
}
}
}
},
{
name: "flip-flop",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Flip-flop_(electronics)' class="link">flip-flop</a>`,
description: `toggle <strong class="color-flop">ON</strong> and <strong class="color-flop">OFF</strong> after a <strong>collision</strong><br>unlock advanced <strong class='color-m'>tech</strong> that runs if <strong class="color-flop">ON</strong>`,
nameInfo: "<span id = 'tech-flip-flop'></span>",
addNameInfo() {
setTimeout(function () {
if (document.getElementById("tech-flip-flop")) {
if (tech.isFlipFlopOn) {
document.getElementById("tech-flip-flop").innerHTML = ` = <strong>ON</strong>`
m.eyeFillColor = m.fieldMeterColor //'#5af'
} else {
document.getElementById("tech-flip-flop").innerHTML = ` = <strong>OFF</strong>`
m.eyeFillColor = "transparent"
}
}
}, 100);
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isRelay
},
requires: "not relay switch",
effect() {
tech.isFlipFlop = true //do you have this tech?
if (!tech.isFlipFlopOn) {
tech.isFlipFlopOn = true //what is the state of flip-Flop?
}
// if (!m.isShipMode) {
// m.skin.flipFlop()
// }
},
remove() {
tech.isFlipFlop = false
if (tech.isFlipFlopOn) {
tech.isFlipFlopOn = false //what is the state of flip-Flop?
}
m.eyeFillColor = 'transparent'
// m.resetSkin();
}
},
{
name: "NAND gate",
description: "if <strong class='color-flop'>ON</strong><br><strong>1.555x</strong> <strong class='color-d'>damage</strong>",
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isFlipFlop || tech.isRelay
},
requires: "ON/OFF tech",
effect() {
tech.isFlipFlopDamage = true;
},
remove() {
tech.isFlipFlopDamage = false;
}
},
{
name: "integrated circuit",
description: "if <strong class='color-flop'>ON</strong> <strong>+7</strong> power up <strong>choices</strong><br>if <strong class='color-flop'>OFF</strong> <strong>-1</strong> power up <strong>choices</strong>",
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return (tech.isFlipFlop || tech.isRelay) && !tech.isDeterminism
},
requires: "ON/OFF tech, not determinism",
effect() {
tech.isFlipFlopChoices = true //do you have this tech
},
remove() {
tech.isFlipFlopChoices = false
}
},
{
name: "transistor",
description: "if <strong class='color-flop'>ON</strong> generate <strong>+20</strong> <strong class='color-f'>energy</strong> per second<br>if <strong class='color-flop'>OFF</strong> drain <strong>-1</strong> <strong class='color-f'>energy</strong> per second",
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isFlipFlop || tech.isRelay
},
requires: "ON/OFF tech",
effect() {
tech.isFlipFlopEnergy = true;
},
remove() {
tech.isFlipFlopEnergy = false;
}
},
// {
// name: "decoupling",
// link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Decoupling_(cosmology)' class="link">decoupling</a>`,
// name: "NOR gate",
// description: "if <strong>flip-flop</strong> is <strong class='color-flop'>OFF</strong><br>become <strong>invulnerable</strong> to your next collision",
// maxCount: 1,
// count: 0,
// frequency: 3,
// frequencyDefault: 3,
// allowed() {
// return tech.isFlipFlop
// },
// requires: "flip-flop",
// effect() {
// tech.isFlipFlopHarm = true //do you have this tech
// },
// remove() {
// tech.isFlipFlopHarm = false
// }
// },
// {
// name: "shape-memory alloy",
// descriptionFunction() {
// //<span style = 'font-size:80%;'>(${ m.couplingDescription(this.bonus)})</span>
// return `if <strong class='color-flop'>ON</strong> <strong>+5</strong> <strong class='color-coupling'>coupling</strong><br>if <strong class='color-flop'>OFF</strong> a dangerous particle slowly <strong>chases</strong> you`
// return `if <strong>flip-flop</strong> is <strong class='color-flop'>ON</strong><br><strong>+400</strong> maximum <strong class='color-h'>health</strong> and <strong>2x</strong> ${powerUps.orb.heal()} effect`
// },
// maxCount: 1,
// count: 0,
// frequency: 3,
// frequencyDefault: 3,
// bonus: 5, //coupling given
// allowed() {
// return tech.isFlipFlop
// },
// requires: "flip-flop",
// effect() {
// tech.isFlipFlopHealth = true;
// m.setMaxHealth();
// for (let i = 0; i < powerUp.length; i++) {
// if (powerUp[i].name === "heal") {
// const oldSize = powerUp[i].size
// powerUp[i].size = powerUps.heal.size() //update current heals
// const scale = powerUp[i].size / oldSize
// Matter.Body.scale(powerUp[i], scale, scale); //grow
// }
// }
// },
// remove() {
// tech.isFlipFlopHealth = false;
// m.setMaxHealth();
// for (let i = 0; i < powerUp.length; i++) {
// if (powerUp[i].name === "heal") {
// const oldSize = powerUp[i].size
// powerUp[i].size = powerUps.heal.size() //update current heals
// const scale = powerUp[i].size / oldSize
// Matter.Body.scale(powerUp[i], scale, scale); //grow
// }
// }
// }
// },
// {
// name: "flip-flop",
// link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Flip-flop_(electronics)' class="link">flip-flop</a>`,
// description: `toggle <strong class="color-flop">ON</strong> and <strong class="color-flop">OFF</strong> after a <strong>collision</strong><br>unlock advanced <strong class='color-m'>tech</strong> that runs if <strong class="color-flop">ON</strong>`,
// // nameInfo: "<span id = 'tech-flip-flop'></span>",
// // addNameInfo() {
// // setTimeout(function () {
// // if (document.getElementById("tech-flip-flop")) {
// // if (tech.isFlipFlopOn) {
// // document.getElementById("tech-flip-flop").innerHTML = ` = <strong>ON</strong>`
// // m.eyeFillColor = m.fieldMeterColor //'#5af'
// // } else {
// // document.getElementById("tech-flip-flop").innerHTML = ` = <strong>OFF</strong>`
// // m.eyeFillColor = "transparent"
// // }
// // }
// // }, 100);
// // },
// maxCount: 1,
// count: 0,
// frequency: 1,
// frequencyDefault: 1,
// allowed() {
// return !tech.isRelay
// },
// requires: "not relay switch",
// effect() {
// tech.isFlipFlop = true //do you have this tech?
// if (!tech.isFlipFlopOn) {
// tech.isFlipFlopOn = true //what is the state of flip-Flop?
// }
// // if (!m.isShipMode) {
// // m.skin.flipFlop()
// // }
// },
// remove() {
// tech.isFlipFlop = false
// if (tech.isFlipFlopOn) {
// tech.isFlipFlopOn = false //what is the state of flip-Flop?
// }
// m.eyeFillColor = 'transparent'
// // m.resetSkin();
// }
// },
// {
// name: "NAND gate",
// description: "if <strong class='color-flop'>ON</strong><br><strong>1.555x</strong> <strong class='color-d'>damage</strong>",
// maxCount: 1,
// count: 0,
// frequency: 3,
// frequencyDefault: 3,
// allowed() {
// return tech.isFlipFlop || tech.isRelay
// },
// requires: "ON/OFF tech",
// effect() {
// tech.isFlipFlopCoupling = true;
// if (tech.isFlipFlopOn) {
// m.couplingChange(this.bonus)
// } else {
// for (let i = 0; i < mob.length; i++) {
// if (mob[i].isDecoupling) mob[i].alive = false //remove WIMP
// }
// spawn.WIMP()
// mob[mob.length - 1].isDecoupling = true //so you can find it to remove
// }
// tech.isFlipFlopDamage = true;
// },
// remove() {
// tech.isFlipFlopCoupling = false;
// if (this.count) {
// if (tech.isFlipFlop || tech.isRelay) {
// if (tech.isFlipFlopOn) {
// m.couplingChange(-this.bonus)
// } else {
// for (let i = 0; i < mob.length; i++) {
// if (mob[i].isDecoupling) mob[i].alive = false //remove WIMP
// }
// }
// }
// }
// tech.isFlipFlopDamage = false;
// }
// },
// {
// name: "integrated circuit",
// description: "if <strong class='color-flop'>ON</strong> <strong>+7</strong> power up <strong>choices</strong><br>if <strong class='color-flop'>OFF</strong> <strong>-1</strong> power up <strong>choices</strong>",
// maxCount: 1,
// count: 0,
// frequency: 3,
// frequencyDefault: 3,
// allowed() {
// return (tech.isFlipFlop || tech.isRelay) && !tech.isDeterminism
// },
// requires: "ON/OFF tech, not determinism",
// effect() {
// tech.isFlipFlopChoices = true //do you have this tech
// },
// remove() {
// tech.isFlipFlopChoices = false
// }
// },
// {
// name: "transistor",
// description: "if <strong class='color-flop'>ON</strong> generate <strong>+20</strong> <strong class='color-f'>energy</strong> per second<br>if <strong class='color-flop'>OFF</strong> drain <strong>-1</strong> <strong class='color-f'>energy</strong> per second",
// maxCount: 1,
// count: 0,
// frequency: 3,
// frequencyDefault: 3,
// allowed() {
// return tech.isFlipFlop || tech.isRelay
// },
// requires: "ON/OFF tech",
// effect() {
// tech.isFlipFlopEnergy = true;
// },
// remove() {
// tech.isFlipFlopEnergy = false;
// }
// },
// // {
// // name: "decoupling",
// // link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Decoupling_(cosmology)' class="link">decoupling</a>`,
// // descriptionFunction() {
// // //<span style = 'font-size:80%;'>(${ m.couplingDescription(this.bonus)})</span>
// // return `if <strong class='color-flop'>ON</strong> <strong>+5</strong> <strong class='color-coupling'>coupling</strong><br>if <strong class='color-flop'>OFF</strong> a dangerous particle slowly <strong>chases</strong> you`
// // },
// // maxCount: 1,
// // count: 0,
// // frequency: 3,
// // frequencyDefault: 3,
// // bonus: 5, //coupling given
// // allowed() {
// // return tech.isFlipFlop || tech.isRelay
// // },
// // requires: "ON/OFF tech",
// // effect() {
// // tech.isFlipFlopCoupling = true;
// // if (tech.isFlipFlopOn) {
// // m.couplingChange(this.bonus)
// // } else {
// // for (let i = 0; i < mob.length; i++) {
// // if (mob[i].isDecoupling) mob[i].alive = false //remove WIMP
// // }
// // spawn.WIMP()
// // mob[mob.length - 1].isDecoupling = true //so you can find it to remove
// // }
// // },
// // remove() {
// // tech.isFlipFlopCoupling = false;
// // if (this.count) {
// // if (tech.isFlipFlop || tech.isRelay) {
// // if (tech.isFlipFlopOn) {
// // m.couplingChange(-this.bonus)
// // } else {
// // for (let i = 0; i < mob.length; i++) {
// // if (mob[i].isDecoupling) mob[i].alive = false //remove WIMP
// // }
// // }
// // }
// // }
// // }
// // },
// {
// name: "relay switch",
// description: `toggle <strong class="color-flop">ON</strong> and <strong class="color-flop">OFF</strong> after picking up a <strong>power up</strong><br>unlock advanced <strong class='color-m'>tech</strong> that runs if <strong class="color-flop">ON</strong>`,
// // nameInfo: "<span id = 'tech-switch'></span>",
// // addNameInfo() {
// // setTimeout(function () {
// // if (document.getElementById("tech-switch")) {
// // if (tech.isFlipFlopOn) {
// // document.getElementById("tech-switch").innerHTML = ` = <strong>ON</strong>`
// // m.eyeFillColor = m.fieldMeterColor //'#5af'
// // } else {
// // document.getElementById("tech-switch").innerHTML = ` = <strong>OFF</strong>`
// // m.eyeFillColor = "transparent"
// // }
// // }
// // }, 100);
// // },
// maxCount: 1,
// count: 0,
// frequency: 1,
// frequencyDefault: 1,
// allowed() {
// return !tech.isFlipFlop
// },
// requires: "not flip-flop",
// effect() {
// m.isAltSkin = true
// tech.isRelay = true //do you have this tech?
// if (!tech.isFlipFlopOn) {
// tech.isFlipFlopOn = true //what is the state of flip-Flop?
// }
// // if (!m.isShipMode) {
// // m.skin.flipFlop()
// // }
// },
// remove() {
// tech.isRelay = false
// if (tech.isFlipFlopOn) {
// tech.isFlipFlopOn = false //what is the state of flip-Flop?
// }
// m.eyeFillColor = 'transparent'
// // m.resetSkin();
// }
// },
// {
// name: "lithium-ion",
// description: "if <strong>relay switch</strong> is <strong class='color-flop'>ON</strong><br><strong>+300</strong> maximum <strong class='color-f'>energy</strong>",
// maxCount: 1,
// count: 0,
// frequency: 3,
// frequencyDefault: 3,
// allowed() {
// return tech.isRelay
// },
// requires: "relay switch",
// effect() {
// tech.isRelayEnergy = true
// m.setMaxEnergy()
// },
// remove() {
// tech.isRelayEnergy = false
// m.setMaxEnergy()
// }
// },
// {
// name: "thermocouple",
// description: "if <strong>relay switch</strong> is <strong class='color-flop'>ON</strong><br>condense <strong>4-13</strong> <strong class='color-s'>ice IX</strong> crystals per second",
// maxCount: 9,
// count: 0,
// frequency: 3,
// frequencyDefault: 3,
// allowed() {
// return tech.isRelay
// },
// requires: "relay switch",
// effect() {
// tech.relayIce++
// },
// remove() {
// tech.relayIce = 0
// }
// },
{
name: "relay switch",
description: `toggle <strong class="color-flop">ON</strong> and <strong class="color-flop">OFF</strong> after picking up a <strong>power up</strong><br>unlock advanced <strong class='color-m'>tech</strong> that runs if <strong class="color-flop">ON</strong>`,
nameInfo: "<span id = 'tech-switch'></span>",
addNameInfo() {
setTimeout(function () {
if (document.getElementById("tech-switch")) {
if (tech.isFlipFlopOn) {
document.getElementById("tech-switch").innerHTML = ` = <strong>ON</strong>`
m.eyeFillColor = m.fieldMeterColor //'#5af'
} else {
document.getElementById("tech-switch").innerHTML = ` = <strong>OFF</strong>`
m.eyeFillColor = "transparent"
}
}
}, 100);
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isFlipFlop
},
requires: "not flip-flop",
effect() {
m.isAltSkin = true
tech.isRelay = true //do you have this tech?
if (!tech.isFlipFlopOn) {
tech.isFlipFlopOn = true //what is the state of flip-Flop?
}
// if (!m.isShipMode) {
// m.skin.flipFlop()
// }
},
remove() {
tech.isRelay = false
if (tech.isFlipFlopOn) {
tech.isFlipFlopOn = false //what is the state of flip-Flop?
}
m.eyeFillColor = 'transparent'
// m.resetSkin();
}
},
{
name: "lithium-ion",
description: "if <strong>relay switch</strong> is <strong class='color-flop'>ON</strong><br><strong>+300</strong> maximum <strong class='color-f'>energy</strong>",
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isRelay
},
requires: "relay switch",
effect() {
tech.isRelayEnergy = true
m.setMaxEnergy()
},
remove() {
tech.isRelayEnergy = false
m.setMaxEnergy()
}
},
{
name: "thermocouple",
description: "if <strong>relay switch</strong> is <strong class='color-flop'>ON</strong><br>condense <strong>4-13</strong> <strong class='color-s'>ice IX</strong> crystals per second",
maxCount: 9,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isRelay
},
requires: "relay switch",
effect() {
tech.relayIce++
},
remove() {
tech.relayIce = 0
}
},
{
name: "first derivative",
descriptionFunction() {
@@ -3421,6 +3421,7 @@ const tech = {
effect() {
tech.isHealAttract = true
powerUps.setPowerUpMode();
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.03);
},
remove() {
tech.isHealAttract = false
@@ -3515,12 +3516,12 @@ const tech = {
},
{
name: "anthropic principle",
nameInfo: "<span id = 'tech-anthropic'></span>",
addNameInfo() {
setTimeout(function () {
powerUps.research.changeRerolls(0)
}, 1000);
},
// nameInfo: "<span id = 'tech-anthropic'></span>",
// addNameInfo() {
// setTimeout(function () {
// powerUps.research.changeRerolls(0)
// }, 1000);
// },
descriptionFunction() {
return `once per level, instead of <strong>dying</strong><br>use ${powerUps.orb.research(1)} and spawn ${powerUps.orb.heal(16)}`
},
@@ -3871,9 +3872,12 @@ const tech = {
requires: "not determinism",
effect() {
tech.isExtraGunField = true;
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.05);
},
remove() {
tech.isExtraGunField = false;
if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
}
},
{
@@ -3936,7 +3940,7 @@ const tech = {
isBadRandomOption: true,
isInstant: true,
allowed() {
return !tech.extraChoices && !tech.isExtraGunField && !tech.isFlipFlopChoices && !tech.isExtraBotOption
return !tech.extraChoices && !tech.isExtraGunField && !tech.isExtraBotOption
},
requires: "not emergence, cross-disciplinary, integrated circuit",
effect() {
@@ -4106,9 +4110,13 @@ const tech = {
requires: "",
effect() {
tech.isMassProduction = true
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.03);
},
remove() {
tech.isMassProduction = false
if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
}
},
{
@@ -4307,7 +4315,7 @@ const tech = {
name: "residual dipolar coupling",
descriptionFunction() {
// return `clicking <strong class='color-cancel'>cancel</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>spawns ${powerUps.orb.coupling(5)}that each give <strong>+0.1</strong> <strong class='color-coupling'>coupling</strong>`//<br>${m.couplingDescription(1)} ${m.fieldMode === 0 ? "" : "per <strong class='color-coupling'>coupling</strong>"}
return `clicking <strong class='color-cancel'>cancel</strong> spawns ${powerUps.orb.coupling(8)}<br><em>${m.couplingDescription(1)} per ${powerUps.orb.coupling(1)}</em>`
return `clicking <strong class='color-cancel'>cancel</strong> spawns ${powerUps.orb.coupling(7)}<br><em>${m.couplingDescription(1)} per ${powerUps.orb.coupling(1)}</em>`
},
maxCount: 1,
count: 0,
@@ -4327,7 +4335,7 @@ const tech = {
{
name: "commodities exchange",
descriptionFunction() {
return `clicking <strong class='color-cancel'>cancel</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>spawns <strong>10-14</strong> ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`
return `clicking <strong class='color-cancel'>cancel</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>spawns <strong>8-12</strong> ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`
},
maxCount: 1,
count: 0,
@@ -4382,7 +4390,7 @@ const tech = {
},
remove() {
tech.isCancelDuplication = false
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
}
},
{
@@ -4430,13 +4438,13 @@ const tech = {
},
remove() {
tech.isPowerUpsVanish = false
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance }
}
},
{
name: "correlated damage",
descriptionFunction() {
return `<strong class='color-dup'>duplication</strong> increases <strong class='color-d'>damage</strong> by the same percent<br><em>(${(1 + Math.min(1, tech.duplicationChance())).toFixed(2)}x)</em>`
return `<strong class='color-dup'>duplication</strong> increases <strong class='color-d'>damage</strong><br><em>(${(1 + Math.min(1, tech.duplicationChance())).toFixed(2)}x)</em>`
},
maxCount: 1,
count: 0,
@@ -4467,9 +4475,11 @@ const tech = {
effect() {
tech.isDuplicateMobs = true;
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.08);
},
remove() {
tech.isDuplicateMobs = false;
if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
}
},
{
@@ -4506,11 +4516,11 @@ const tech = {
effect() {
tech.isStimulatedEmission = true
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.15);
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.20);
},
remove() {
tech.isStimulatedEmission = false
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
}
},
{
@@ -4536,6 +4546,7 @@ const tech = {
if (this.count > 0 && m.alive) {
tech.duplication += 0.11
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.11);
tech.damage /= this.damage
this.frequency = 0
}
@@ -4684,7 +4695,7 @@ const tech = {
{
name: "paradigm shift",
descriptionFunction() {
return `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <span class='color-remove'>ejects</span> it<br><strong>4</strong> ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"} each time`
return `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <span class='color-remove'>ejects</span> it<br><strong>${tech.pauseEjectTech.toFixed(1)}</strong> ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"} cost <em>(1.2x cost each use)</em>`
},
maxCount: 1,
count: 0,
@@ -4699,6 +4710,7 @@ const tech = {
},
remove() {
tech.isPauseEjectTech = false;
}
},
{
@@ -5332,7 +5344,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.relayIce || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0))
return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0))
},
requires: "a freeze effect",
effect() {
@@ -5351,7 +5363,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.relayIce || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0))
return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0))
},
requires: "a freeze effect",
effect() {
@@ -5370,7 +5382,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return (tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.relayIce || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0))) && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.nailsDeathMob
return (tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0))) && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.nailsDeathMob
},
requires: "a localized freeze effect, no other mob death tech",
effect() {
@@ -5389,7 +5401,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.relayIce || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)) || tech.iceIXOnDeath || tech.isIceShot
return (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)) || tech.iceIXOnDeath || tech.isIceShot
},
requires: "ice IX",
effect() {
@@ -5408,7 +5420,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.relayIce || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)) || tech.iceIXOnDeath || tech.isIceShot
return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)) || tech.iceIXOnDeath || tech.isIceShot
},
requires: "a localized freeze effect",
effect() {
@@ -5433,7 +5445,7 @@ const tech = {
// },
// requires: "perfect diamagnetism",
allowed() {
return (tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.relayIce || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)))
return (tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)))
},
requires: "a localized freeze effect",
effect() {
@@ -5485,7 +5497,7 @@ const tech = {
},
{
name: "Zectron",
description: `<strong>2x</strong> <strong>super ball</strong> density and <strong class='color-d'>damage</strong>, but<br>after colliding with <strong>super balls</strong> <strong>-5</strong> <strong class='color-f'>energy</strong>`,
description: `<strong>2x</strong> <strong>super ball</strong> density and <strong class='color-d'>damage</strong>, but<br>after colliding with <strong>super balls</strong> <strong>-4</strong> <strong class='color-f'>energy</strong>`,
isGunTech: true,
maxCount: 1,
count: 0,
@@ -5630,7 +5642,7 @@ const tech = {
tech.wavePacketDamage *= 1.4
},
remove() {
tech.waveFrequency = 0.2
tech.waveFrequency = 0.2 //adjust this to make the waves much larger
tech.wavePacketDamage = 1
}
},
@@ -8549,7 +8561,7 @@ const tech = {
},
remove() {
tech.cloakDuplication = 0
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
}
},
{
@@ -8719,7 +8731,7 @@ const tech = {
},
remove() {
tech.fieldDuplicate = 0
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (this.count > 0) powerUps.research.changeRerolls(3)
}
},
@@ -10964,6 +10976,25 @@ const tech = {
if (this.count) m.resetSkin();
}
},
{
name: "wall jump",
description: "jump on walls",
maxCount: 1,
count: 0,
frequency: 0,
isJunk: true,
allowed() {
return !m.isShipMode
},
requires: "",
effect() {
jumpSensor.vertices[0].x += -22
jumpSensor.vertices[3].x += -22
jumpSensor.vertices[1].x += 22
jumpSensor.vertices[2].x += 22
},
remove() { }
},
{
name: "posture",
description: "stand a bit taller",
@@ -11935,6 +11966,7 @@ const tech = {
isExplodeRadio: null,
isPauseSwitchField: null,
isPauseEjectTech: null,
pauseEjectTech: null,
isShieldPierce: null,
isDuplicateMobs: null,
is100Duplicate: null,
@@ -11945,15 +11977,6 @@ const tech = {
isSwitchReality: null,
isResearchReality: null,
isAnthropicDamage: null,
isFlipFlop: null,
isFlipFlopHarm: null,
isFlipFlopOn: null,
// isFlipFlopLevelReset: null,
isFlipFlopDamage: null,
isFlipFlopEnergy: null,
isFlipFlopChoices: null,
isRelay: null,
relayIce: null,
isMetaAnalysis: null,
isFoamAttract: null,
droneCycleReduction: null,
@@ -12046,8 +12069,6 @@ const tech = {
isTechDebt: null,
isPlasmaBall: null,
plasmaDischarge: null,
isFlipFlopHealth: null,
isRelayEnergy: null,
coyoteTime: null,
missileFireCD: null,
isBotField: null,