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

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

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,

107
todo.txt
View File

@@ -1,31 +1,76 @@
******************************************************** NEXT PATCH **************************************************
adjusted text and math for the fire rate system to use the new "x" syntax
tech search is no longer case sensitive
newLevel - towers
please give feedback
boost level elements can now be pointed at any angle
Zectron 1.9->2x damage, -25% -> -5 energy
exothermic process -20% -> -5 energy
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
instant/unRemovable tech has a unique icon and no longer shows up in the tech list
marginal utility - no longer spawns ammo
heuristics - no longer spawn a gun, 1.2->1.3 fire rate
open-source - gives 1 extra bot option and 3x bot tech frequency
robotics - now just spawns 2 bots
induction brake - doesn't spawn heals, but lasts 15->17 seconds
accretion - doesn't spawn heals, but gets 3% duplication
mass production - doesn't spawn power ups, but gets 3% duplication
Ψ(t) collapse - doesn't spawn research, spawns 5 research from bosses
decoherence - doesn't spawn research, spawns 2 research from bosses
fine-structure constant - doesn't spawn coupling, spawn 9 coupling from bosses
Bayesian statistics - 1.03->1.05x damage, doesn't spawn research
Born rule code rewritten, but it should have a similar effect as before
triple point - 1.5->5 second freeze, but no coupling spawn
geodesics - no longer spawns ammo and guns, but gives 1.5x damage
ideal gas law - doesn't remove ammo, 12->6x foam ammo per ammo power up
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
*********************************************************** TODO *****************************************************
increase difficulty
quantum physics lecture notes:
https://www.scottaaronson.com/democritus/lec9.html
Quantum mechanics is what you would inevitably come up with if you started from probability theory, and then said, let's try to generalize it so that the numbers we used to call "probabilities" can be negative numbers.
flip player upside down
how
rotate player in matter.js
make sure floor sensor works
flip player crouch direction
redraw legs, orb
flip gravity
when to use?
fieldTech: negative mass?
effect in level
tech - while immune to damage taken:
3x damage
no ammo costs?
tech - immune to damage taken after killing a mob
tech - after a power up is duplicated
update text to random effect after choosing tech, or after each trigger, or on first display of tech
pick 1 effect at random
become immune to damage taken for 5 seconds
summon JUNK bots for 10 seconds
2x current energy
gain 1.01x damage permanently
field tech: negative mass - quickly pull/teleport in all nearby blocks and then fire them away from player
what triggers effect?
auto aim blocks?
after picking up heals gain ____
0.1x damage taken for 12s
after picking up ammo gain ____
4x fire rate for 12s
after picking up research gain ____
+10 choices for 12s
tech: Energy generation increases with you velocity
Newtons' 3rd law?
after clicking on a new tech (or getting it in any way) animate adding the tech to your collection
fade in on right side text list?
tech - getting caught in an explosion gives you _____
damage for 10 seconds?
@@ -52,14 +97,6 @@ make sure healing isn't effected by simulation.healScale
tech - destroys a random tech each new level and gains +damage each time
List of ways to break the game
CPT + high energy regen
research -> bot fabrication -> ersatz bots -> various bot upgrades
grappling hook + high fire rate + alternator + time dilation
duplication 100%
interest + coupling, research + peer review?
electronegativity and high energy?
boss - tracks the position, velocity, angle of power ups, blocks, and bullets it fires
reactor only?
will rewind time
@@ -1182,8 +1219,20 @@ possible names for tech
retrovirus: these things make JUNK DNA so link it somehow to that tech?
Upon infection with a retrovirus, a cell converts the retroviral RNA into DNA and sometimes the DNA will be passed on to progeny as JUNK DNA
amalgam, amalgamation - the action, process, or result of combining or uniting.
thermoplastic - the stuff in 3-D printers, use for molecular assembler tech
******************************************************** CARS IMAGES ********************************************************
******************************************************** DESIGN ********************************************************
List of ways to break the game
options exchange + paradigm shift + CPT to undo health cost = repeatable cancel triggers
CPT + high energy regen
research -> bot fabrication -> ersatz bots -> various bot upgrades
grappling hook + high fire rate + alternator + time dilation
duplication 100%
interest + coupling, research + peer review?
electronegativity and high energy?
******************************************************** IMAGES ********************************************************
process: discord midjourney prompts -> "pixelmator pro" adjust color, repair, scale to 384x256, export PNG -> webP? -> place in /img folder
make n-gon a progressive web app to manage image downloads, cache