Halbach array

tech: Halbach array - throwing a block will also throw other nearby blocks

tech non-renewables now spawns ammo, but ammo can't be picked up
grenade tech that cause multiple explosions have less knock back for mobs
constraint:  0->0.5x healing
wormhole 7->8% duplication
many worlds takes a few frames between each tech given

bug fixes
 harpoon ammo gain on autonomous defense fixed
 constraints are properly randomized again
This commit is contained in:
landgreen
2024-10-20 16:01:05 -07:00
parent 9c2c9be4ed
commit 8bb8222b73
10 changed files with 416 additions and 298 deletions

BIN
img/Halbach array.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -374,7 +374,7 @@ const b = {
explosionRange() { explosionRange() {
return tech.explosiveRadius * (tech.isExplosionHarm ? 1.7 : 1) * (tech.isSmallExplosion ? 0.7 : 1) * (tech.isExplodeRadio ? 1.25 : 1) return tech.explosiveRadius * (tech.isExplosionHarm ? 1.7 : 1) * (tech.isSmallExplosion ? 0.7 : 1) * (tech.isExplodeRadio ? 1.25 : 1)
}, },
explosion(where, radius, color = "rgba(255,25,0,0.6)") { // typically explode is used for some bullets with .onEnd explosion(where, radius, color = "rgba(255,25,0,0.6)", reducedKnock = 1) { // typically explode is used for some bullets with .onEnd
radius *= tech.explosiveRadius radius *= tech.explosiveRadius
let dist, sub, knock; let dist, sub, knock;
@@ -525,7 +525,7 @@ const b = {
if (Matter.Query.ray(map, mob[i].position, where).length > 0) dmg *= 0.5 //reduce damage if a wall is in the way if (Matter.Query.ray(map, mob[i].position, where).length > 0) dmg *= 0.5 //reduce damage if a wall is in the way
mob[i].damage(dmg * damageScale * m.dmgScale); mob[i].damage(dmg * damageScale * m.dmgScale);
mob[i].locatePlayer(); mob[i].locatePlayer();
knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg * damageScale) * mob[i].mass * (mob[i].isBoss ? 0.003 : 0.01)); knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg * damageScale) * mob[i].mass * (mob[i].isBoss ? 0.003 : 0.01) * reducedKnock);
if (tech.isStun) { if (tech.isStun) {
mobs.statusStun(mob[i], 30) mobs.statusStun(mob[i], 30)
} else if (!mob[i].isInvulnerable) { } else if (!mob[i].isInvulnerable) {
@@ -536,7 +536,7 @@ const b = {
damageScale *= 0.87 //reduced damage for each additional explosion target damageScale *= 0.87 //reduced damage for each additional explosion target
} else if (!mob[i].seePlayer.recall && dist < alertRange) { } else if (!mob[i].seePlayer.recall && dist < alertRange) {
mob[i].locatePlayer(); mob[i].locatePlayer();
knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg * damageScale) * mob[i].mass * (mob[i].isBoss ? 0 : 0.006)); knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg * damageScale) * mob[i].mass * (mob[i].isBoss ? 0 : 0.006 * reducedKnock));
if (tech.isStun) { if (tech.isStun) {
mobs.statusStun(mob[i], 30) mobs.statusStun(mob[i], 30)
} else if (!mob[i].isInvulnerable) { } else if (!mob[i].isInvulnerable) {
@@ -630,11 +630,8 @@ const b = {
count++ count++
if (count < 84) requestAnimationFrame(cycle); if (count < 84) requestAnimationFrame(cycle);
if (!(count % 7)) { if (!(count % 7)) {
const unit = Vector.rotate({ const unit = Vector.rotate({ x: 1, y: 0 }, 6.28 * Math.random())
x: 1, b.explosion(Vector.add(where, Vector.mult(unit, size * (count * 0.01 + 0.03 * Math.random()))), size * (0.4 + Math.random() * 0.35), `hsla(${360 * Math.random()},100%,66%,0.6)`, 0.2); //makes bullet do explosive damage at end
y: 0
}, 6.28 * Math.random())
b.explosion(Vector.add(where, Vector.mult(unit, size * (count * 0.01 + 0.03 * Math.random()))), size * (0.4 + Math.random() * 0.35), `hsla(${360 * Math.random()},100%,66%,0.6)`); //makes bullet do explosive damage at end
} }
} }
} }
@@ -656,7 +653,7 @@ const b = {
x: 1, x: 1,
y: 0 y: 0
}, curl * 6.28 * count / 18 + off) }, curl * 6.28 * count / 18 + off)
b.explosion(Vector.add(where, Vector.mult(unit, size * 0.75)), size * 0.7, color); //makes bullet do explosive damage at end b.explosion(Vector.add(where, Vector.mult(unit, size * 0.75)), size * 0.7, color, 0.5); //makes bullet do explosive damage at end
} }
} }
} }
@@ -677,7 +674,7 @@ const b = {
if (count < 30 && m.alive) requestAnimationFrame(cycle); if (count < 30 && m.alive) requestAnimationFrame(cycle);
if (count === 0) { if (count === 0) {
const color = `hsla(${360 * Math.random()},100%,66%,0.6)` const color = `hsla(${360 * Math.random()},100%,66%,0.6)`
b.explosion(where, size * 0.8, color); b.explosion(where, size * 0.8, color, 0.5);
} }
if (count === 8) { if (count === 8) {
const color = `hsla(${360 * Math.random()},100%,66%,0.6)` const color = `hsla(${360 * Math.random()},100%,66%,0.6)`
@@ -686,7 +683,7 @@ const b = {
x: 1, x: 1,
y: 0 y: 0
}, 6.28 * i / len) }, 6.28 * i / len)
b.explosion(Vector.add(where, Vector.mult(unit, 1.1 * range)), size * 0.6, color); //makes bullet do explosive damage at end b.explosion(Vector.add(where, Vector.mult(unit, 1.1 * range)), size * 0.6, color, 0.5); //makes bullet do explosive damage at end
} }
} }
if (count === 16) { if (count === 16) {
@@ -696,7 +693,7 @@ const b = {
x: 1, x: 1,
y: 0 y: 0
}, 6.28 * i / len) }, 6.28 * i / len)
b.explosion(Vector.add(where, Vector.mult(unit, 1.4 * range)), size * 0.45, color); //makes bullet do explosive damage at end b.explosion(Vector.add(where, Vector.mult(unit, 1.4 * range)), size * 0.45, color, 0.5); //makes bullet do explosive damage at end
} }
} }
count++ count++
@@ -1611,6 +1608,7 @@ const b = {
Matter.Body.setVelocity(this.caughtPowerUp, { x: 0, y: 0 }) Matter.Body.setVelocity(this.caughtPowerUp, { x: 0, y: 0 })
} else { } else {
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
if (tech.isEnergyNoAmmo && powerUp[i].name === "ammo") continue
const radius = powerUp[i].circleRadius + 50 const radius = powerUp[i].circleRadius + 50
if (Vector.magnitudeSquared(Vector.sub(this.vertices[2], powerUp[i].position)) < radius * radius) { if (Vector.magnitudeSquared(Vector.sub(this.vertices[2], powerUp[i].position)) < radius * radius) {
if (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal) { if (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal) {
@@ -1906,6 +1904,7 @@ const b = {
Matter.Body.setVelocity(this.caughtPowerUp, { x: 0, y: 0 }) Matter.Body.setVelocity(this.caughtPowerUp, { x: 0, y: 0 })
} else { //&& simulation.cycle % 2 } else { //&& simulation.cycle % 2
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
if (tech.isEnergyNoAmmo && powerUp[i].name === "ammo") continue
const radius = powerUp[i].circleRadius + 50 const radius = powerUp[i].circleRadius + 50
if (Vector.magnitudeSquared(Vector.sub(this.vertices[2], powerUp[i].position)) < radius * radius && !powerUp[i].isGrabbed) { if (Vector.magnitudeSquared(Vector.sub(this.vertices[2], powerUp[i].position)) < radius * radius && !powerUp[i].isGrabbed) {
if (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal) { if (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal) {
@@ -3307,9 +3306,11 @@ const b = {
for (let i = 0, len = powerUp.length; i < len; ++i) { //grab, but don't lock onto nearby power up for (let i = 0, len = powerUp.length; i < len; ++i) { //grab, but don't lock onto nearby power up
if ( if (
Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 &&
(powerUp[i].name !== "heal" || m.health < 0.97 * m.maxHealth || tech.isDroneGrab) && !(
(powerUp[i].name !== "field" || !tech.isSuperDeterminism) (m.health > 0.93 * m.maxHealth && !tech.isDroneGrab && powerUp[i].name === "heal") ||
// &&(b.inventory.length > 1 || powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) (tech.isSuperDeterminism && powerUp[i].name === "field") ||
((tech.isEnergyNoAmmo || b.inventory.length === 0) && powerUp[i].name === "ammo")
)
) { ) {
//draw pickup for a single cycle //draw pickup for a single cycle
ctx.beginPath(); ctx.beginPath();
@@ -3337,11 +3338,11 @@ const b = {
//look for power ups to lock onto //look for power ups to lock onto
let closeDist = Infinity; let closeDist = Infinity;
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
if ( if (!(
(powerUp[i].name !== "heal" || m.health < 0.97 * m.maxHealth || tech.isDroneGrab) && (m.health > 0.93 * m.maxHealth && !tech.isDroneGrab && powerUp[i].name === "heal") ||
(powerUp[i].name !== "field" || !tech.isSuperDeterminism) (tech.isSuperDeterminism && powerUp[i].name === "field") ||
// &&(b.inventory.length > 1 || powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ((tech.isEnergyNoAmmo || b.inventory.length === 0) && powerUp[i].name === "ammo")
) { )) {
if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) { if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) {
//draw pickup for a single cycle //draw pickup for a single cycle
ctx.beginPath(); ctx.beginPath();
@@ -3543,9 +3544,11 @@ const b = {
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
if ( if (
Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 &&
(powerUp[i].name !== "heal" || m.health < 0.93 * m.maxHealth || tech.isDroneGrab) && !(
(powerUp[i].name !== "field" || !tech.isSuperDeterminism) (m.health > 0.93 * m.maxHealth && !tech.isDroneGrab && powerUp[i].name === "heal") ||
// &&(powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) (tech.isSuperDeterminism && powerUp[i].name === "field") ||
((tech.isEnergyNoAmmo || b.inventory.length === 0) && powerUp[i].name === "ammo")
)
) { ) {
//draw pickup for a single cycle //draw pickup for a single cycle
ctx.beginPath(); ctx.beginPath();
@@ -3574,11 +3577,11 @@ const b = {
//look for power ups to lock onto //look for power ups to lock onto
let closeDist = Infinity; let closeDist = Infinity;
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
if ( if (!(
(powerUp[i].name !== "heal" || m.health < 0.93 * m.maxHealth || tech.isDroneGrab) && (m.health > 0.93 * m.maxHealth && !tech.isDroneGrab && powerUp[i].name === "heal") ||
(powerUp[i].name !== "field" || !tech.isSuperDeterminism) (tech.isSuperDeterminism && powerUp[i].name === "field") ||
// &&(powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ((tech.isEnergyNoAmmo || b.inventory.length === 0) && powerUp[i].name === "ammo")
) { )) {
if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) { if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) {
//draw pickup for a single cycle //draw pickup for a single cycle
ctx.beginPath(); ctx.beginPath();

View File

@@ -163,10 +163,10 @@ function collisionChecks(event) {
let count = maxCount - 1 let count = maxCount - 1
const angle = Math.atan2(mob[k].position.y - player.position.y, mob[k].position.x - player.position.x); const angle = Math.atan2(mob[k].position.y - player.position.y, mob[k].position.x - player.position.x);
const mass = 0.75 * ((tech.isLargeHarpoon) ? 1 + Math.min(0.05 * Math.sqrt(b.guns[9].ammo), 10) : 1) const mass = 0.75 * ((tech.isLargeHarpoon) ? 1 + Math.min(0.05 * Math.sqrt(b.guns[9].ammo), 10) : 1)
b.harpoon(m.pos, mob[k], angle, mass, true, 7) // harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) { b.harpoon(m.pos, mob[k], angle, mass, true, 7, false) // harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) {
bullet[bullet.length - 1].drain = 0 bullet[bullet.length - 1].drain = 0
for (; count > 0; count--) { for (; count > 0; count--) {
b.harpoon(m.pos, mob[k], angle + count * 2 * Math.PI / maxCount, mass, true, 7) b.harpoon(m.pos, mob[k], angle + count * 2 * Math.PI / maxCount, mass, true, 7, false)
bullet[bullet.length - 1].drain = 0 bullet[bullet.length - 1].drain = 0
} }
} }
@@ -245,8 +245,7 @@ function collisionChecks(event) {
mob[k].damage(dmg, true); mob[k].damage(dmg, true);
if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && Math.random() < 0.5) { if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && Math.random() < 0.5) {
options = ["coupling", "boost", "heal", "research"] options = ["coupling", "boost", "heal", "research", "ammo"]
if (!tech.isEnergyNoAmmo) options.push("ammo")
powerUps.spawn(mob[k].position.x, mob[k].position.y, options[Math.floor(Math.random() * options.length)]); powerUps.spawn(mob[k].position.x, mob[k].position.y, options[Math.floor(Math.random() * options.length)]);
} }

View File

@@ -30,7 +30,7 @@ const level = {
// tech.tech[297].frequency = 100 // tech.tech[297].frequency = 100
// tech.addJunkTechToPool(0.5) // tech.addJunkTechToPool(0.5)
// m.couplingChange(10) // m.couplingChange(10)
// m.setField("standing wave") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook // m.setField("negative mass") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook
// m.energy = 0 // m.energy = 0
// powerUps.research.count = 3 // powerUps.research.count = 3
// tech.isHookWire = true // tech.isHookWire = true
@@ -38,21 +38,21 @@ const level = {
// simulation.molecularMode = 2 // simulation.molecularMode = 2
// m.damage(0.1); // m.damage(0.1);
// b.giveGuns("nail gun") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("nail gun") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("spores") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("harpoon") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// tech.laserColor = "#fff" // tech.laserColor = "#fff"
// tech.laserColorAlpha = "rgba(255, 255, 255, 0.5)" // tech.laserColorAlpha = "rgba(255, 255, 255, 0.5)"
// b.guns[8].ammo = 100000000 // b.guns[8].ammo = 100000000
// requestAnimationFrame(() => { tech.giveTech("stimulated emission") }); // requestAnimationFrame(() => { tech.giveTech("non-renewables") });
// tech.giveTech("dark matter") // tech.giveTech("dark matter")
// tech.addJunkTechToPool(0.5) // tech.addJunkTechToPool(0.5)
// for (let i = 0; i < 1; ++i) tech.giveTech("entropic gravity") // for (let i = 0; i < 1; ++i) tech.giveTech("many-worlds")
// for (let i = 0; i < 1; ++i) tech.giveTech("nitinol") // for (let i = 0; i < 1; ++i) tech.giveTech("quantum immortality")
// m.skin.egg(); // m.skin.egg();
// for (let i = 0; i < 1; ++i) tech.giveTech("depolarization") // for (let i = 0; i < 1; ++i) tech.giveTech("non-renewables")
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("wikipedia") }); // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("quasiparticles") });
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("field coupling") }); // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("field coupling") });
// for (let i = 0; i < 1; i++) tech.giveTech("interest") // for (let i = 0; i < 1; i++) tech.giveTech("interest")
// m.lastKillCycle = m.cycle // m.lastKillCycle = m.cycle
@@ -64,7 +64,7 @@ const level = {
level[simulation.isTraining ? "walk" : "initial"]() //normal starting level ************************************************** level[simulation.isTraining ? "walk" : "initial"]() //normal starting level **************************************************
// for (let i = 0; i < 1; ++i) spawn.snakeBoss(1900, -500) // for (let i = 0; i < 5; ++i) spawn.sneaker(1900, -500)
// for (let i = 0; i < 1; i++) spawn.mantisBoss(1900, -500) // for (let i = 0; i < 1; i++) spawn.mantisBoss(1900, -500)
// for (let i = 0; i < 1; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "entanglement"); // for (let i = 0; i < 1; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "entanglement");
@@ -77,7 +77,7 @@ const level = {
// for (let i = 0; i < 5; i++) tech.giveTech("undefined") // for (let i = 0; i < 5; i++) tech.giveTech("undefined")
// lore.techCount = 1 // lore.techCount = 1
// level.levelsCleared = 10 // level.levelsCleared = 10
// localSettings.loreCount = 2 //this sets what conversation is heard // localSettings.loreCount = 1 //this sets what conversation is heard
// localSettings.levelsClearedLastGame = 10 // localSettings.levelsClearedLastGame = 10
// if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage // if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
// level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation // level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation
@@ -333,12 +333,12 @@ const level = {
constraintDescription2: "", constraintDescription2: "",
constraint: [ constraint: [
{ {
description: "healing disabled", description: "0.5x healing",
effect() { effect() {
level.isNoHeal = true level.isLowHeal = true
}, },
remove() { remove() {
level.isNoHeal = false level.isLowHeal = false
} }
}, },
{ {
@@ -599,7 +599,7 @@ const level = {
isReducedRegen: 1, isReducedRegen: 1,
isHideHealth: false, isHideHealth: false,
isNoPause: false, isNoPause: false,
isNoHeal: false, isLowHeal: false,
levelAnnounce() { levelAnnounce() {
const cheating = simulation.isCheating ? "(testing)" : "" const cheating = simulation.isCheating ? "(testing)" : ""
if (level.levelsCleared === 0) { if (level.levelsCleared === 0) {

View File

@@ -1299,7 +1299,7 @@ const mobs = {
powerUps.setPowerUpMode(); //needed after adjusting duplication chance powerUps.setPowerUpMode(); //needed after adjusting duplication chance
} }
} else if (tech.isShieldAmmo && this.shield && this.shieldCount === 1) { } else if (tech.isShieldAmmo && this.shield && this.shieldCount === 1) {
let type = tech.isEnergyNoAmmo ? "heal" : "ammo" let type = "ammo"
if (Math.random() < 0.4) { if (Math.random() < 0.4) {
type = "heal" type = "heal"
} else if (Math.random() < 0.3 && !tech.isSuperDeterminism) { } else if (Math.random() < 0.3 && !tech.isSuperDeterminism) {

View File

@@ -316,101 +316,127 @@ const m = {
m.isHolding = true; m.isHolding = true;
}, },
alive: false, alive: false,
isSwitchingWorlds: false,
switchWorlds() { switchWorlds() {
powerUps.boost.endCycle = 0 if (!m.isSwitchingWorlds) {
const totalGuns = b.inventory.length powerUps.boost.endCycle = 0
//track ammo/ ammoPack count const totalGuns = b.inventory.length
let ammoCount = 0 //track ammo/ ammoPack count
for (let i = 0, len = b.inventory.length; i < len; i++) { let ammoCount = 0
if (b.guns[b.inventory[i]].ammo !== Infinity) { for (let i = 0, len = b.inventory.length; i < len; i++) {
ammoCount += b.guns[b.inventory[i]].ammo / b.guns[b.inventory[i]].ammoPack if (b.guns[b.inventory[i]].ammo !== Infinity) {
} else { ammoCount += b.guns[b.inventory[i]].ammo / b.guns[b.inventory[i]].ammoPack
ammoCount += 5
}
}
simulation.isTextLogOpen = false; //prevent console spam
//remove all tech and count current tech total
let totalTech = 0;
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].isJunk) tech.tech[i].frequency = 0
if (tech.tech[i].count > 0 && !tech.tech[i].isLore) {
if (tech.tech[i].frequencyDefault) {
tech.tech[i].frequency = tech.tech[i].frequencyDefault
} else { } else {
tech.tech[i].frequency = 1 ammoCount += 5
}
if (
!tech.tech[i].isNonRefundable &&
// !tech.tech[i].isFromAppliedScience &&
!tech.tech[i].isAltRealityTech
) {
totalTech += tech.tech[i].count
tech.tech[i].remove();
tech.tech[i].isLost = false
tech.tech[i].count = 0
} }
} }
}
// lore.techCount = 0;
// tech.removeLoreTechFromPool();
// tech.addLoreTechToPool();
// tech.removeJunkTechFromPool();
tech.junkChance = 0;
tech.duplication = 0;
tech.extraMaxHealth = 0;
tech.totalCount = 0;
tech.removeCount = 0;
const randomBotCount = b.totalBots()
b.zeroBotCount()
//remove all bullets, respawn bots
for (let i = 0; i < bullet.length; ++i) Matter.Composite.remove(engine.world, bullet[i]);
bullet = [];
//randomize health simulation.isTextLogOpen = false; //prevent console spam
m.health = m.health * (1 + 0.5 * (Math.random() - 0.5)) //remove all tech and count current tech total
if (m.health > 1) m.health = 1; let totalTech = 0;
m.displayHealth();
//randomize field
m.setField(Math.ceil(Math.random() * (m.fieldUpgrades.length - 1)))
//removes guns and ammo
b.inventory = [];
b.activeGun = null;
b.inventoryGun = 0;
for (let i = 0, len = b.guns.length; i < len; ++i) {
b.guns[i].have = false;
if (b.guns[i].ammo !== Infinity) {
b.guns[i].ammo = 0;
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack;
}
}
//give random guns
for (let i = 0; i < totalGuns; i++) b.giveGuns()
//randomize ammo based on ammo/ammoPack count
for (let i = 0, len = b.inventory.length; i < len; i++) {
if (b.guns[b.inventory[i]].ammo !== Infinity) b.guns[b.inventory[i]].ammo = Math.max(0, Math.floor(ammoCount / b.inventory.length * b.guns[b.inventory[i]].ammoPack * (2.5 + 0.3 * (Math.random() - 0.5))))
}
// console.log(b.activeGun)
//randomize tech
for (let i = 0; i < totalTech; i++) {
//find what tech I could get
let options = [];
for (let i = 0, len = tech.tech.length; i < len; i++) { for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isBadRandomOption && !tech.tech[i].isLore && !tech.tech[i].isJunk) { if (tech.tech[i].isJunk) tech.tech[i].frequency = 0
for (let j = 0; j < tech.tech[i].frequency; j++) options.push(i); if (tech.tech[i].count > 0 && !tech.tech[i].isLore) {
if (tech.tech[i].frequencyDefault) {
tech.tech[i].frequency = tech.tech[i].frequencyDefault
} else {
tech.tech[i].frequency = 1
}
if (
!tech.tech[i].isNonRefundable &&
// !tech.tech[i].isFromAppliedScience &&
!tech.tech[i].isAltRealityTech
) {
totalTech += tech.tech[i].count
tech.tech[i].remove();
tech.tech[i].isLost = false
tech.tech[i].count = 0
}
} }
} }
//add a new tech from options pool // lore.techCount = 0;
if (options.length > 0) tech.giveTech(options[Math.floor(Math.random() * options.length)]) // tech.removeLoreTechFromPool();
// tech.addLoreTechToPool();
// tech.removeJunkTechFromPool();
tech.junkChance = 0;
tech.duplication = 0;
tech.extraMaxHealth = 0;
tech.totalCount = 0;
tech.removeCount = 0;
const randomBotCount = b.totalBots()
b.zeroBotCount()
//remove all bullets, respawn bots
for (let i = 0; i < bullet.length; ++i) Matter.Composite.remove(engine.world, bullet[i]);
bullet = [];
//randomize health
m.health = m.health * (1 + 0.5 * (Math.random() - 0.5))
if (m.health > 1) m.health = 1;
m.displayHealth();
//randomize field
m.setField(Math.ceil(Math.random() * (m.fieldUpgrades.length - 1)))
//removes guns and ammo
b.inventory = [];
b.activeGun = null;
b.inventoryGun = 0;
for (let i = 0, len = b.guns.length; i < len; ++i) {
b.guns[i].have = false;
if (b.guns[i].ammo !== Infinity) {
b.guns[i].ammo = 0;
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack;
}
}
//give random guns
for (let i = 0; i < totalGuns; i++) b.giveGuns()
//randomize ammo based on ammo/ammoPack count
for (let i = 0, len = b.inventory.length; i < len; i++) {
if (b.guns[b.inventory[i]].ammo !== Infinity) b.guns[b.inventory[i]].ammo = Math.max(0, Math.floor(ammoCount / b.inventory.length * b.guns[b.inventory[i]].ammoPack * (2.5 + 0.3 * (Math.random() - 0.5))))
}
//randomize tech
// for (let i = 0; i < totalTech; i++) {
// let options = [];
// for (let i = 0, len = tech.tech.length; i < len; i++) {
// if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isBadRandomOption && !tech.tech[i].isLore && !tech.tech[i].isJunk) {
// for (let j = 0; j < tech.tech[i].frequency; j++) options.push(i);
// }
// }
// if (options.length > 0) tech.giveTech(options[Math.floor(Math.random() * options.length)]) //add a new tech from options pool
// }
let loop = () => {
if (!(m.cycle % 10)) {
if (totalTech > 0 && m.alive) {
totalTech--
let options = [];
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isBadRandomOption && !tech.tech[i].isLore && !tech.tech[i].isJunk) {
for (let j = 0; j < tech.tech[i].frequency; j++) options.push(i);
}
}
if (options.length > 0) tech.giveTech(options[Math.floor(Math.random() * options.length)]) //add a new tech from options pool
requestAnimationFrame(loop);
} else {
m.isSwitchingWorlds = false
}
} else if (m.alive) {
requestAnimationFrame(loop);
} else {
m.isSwitchingWorlds = false
}
}
requestAnimationFrame(loop);
b.respawnBots();
for (let i = 0; i < randomBotCount; i++) b.randomBot()
simulation.makeGunHUD(); //update gun HUD
simulation.updateTechHUD();
simulation.isTextLogOpen = true;
m.drop();
if (simulation.paused) build.pauseGrid() //update the build when paused
} }
b.respawnBots();
for (let i = 0; i < randomBotCount; i++) b.randomBot()
simulation.makeGunHUD(); //update gun HUD
simulation.updateTechHUD();
simulation.isTextLogOpen = true;
m.drop();
if (simulation.paused) build.pauseGrid() //update the build when paused
}, },
dmgScale: null, //scales all damage, but not raw .dmg dmgScale: null, //scales all damage, but not raw .dmg
death() { death() {
@@ -440,8 +466,8 @@ const m = {
ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillRect(0, 0, canvas.width, canvas.height);
} }
spawn.setSpawnList(); //new mob types spawn.setSpawnList(); //new mob types
simulation.clearNow = true; //triggers a map reset // simulation.clearNow = true; //triggers a map reset
m.switchWorlds() // m.switchWorlds()
simulation.isTextLogOpen = true; simulation.isTextLogOpen = true;
simulation.inGameConsole(`simulation.amplitude <span class='color-symbol'>=</span> 0.${len - i - 1}`, swapPeriod); simulation.inGameConsole(`simulation.amplitude <span class='color-symbol'>=</span> 0.${len - i - 1}`, swapPeriod);
simulation.isTextLogOpen = false; simulation.isTextLogOpen = false;
@@ -528,8 +554,8 @@ const m = {
// } // }
}, },
addHealth(heal) { addHealth(heal) {
if (!tech.isEnergyHealth && !level.isNoHeal) { if (!tech.isEnergyHealth) {
m.health += heal * simulation.healScale; m.health += heal * simulation.healScale * (level.isLowHeal ? 0.5 : 1);
if (m.health > m.maxHealth) m.health = m.maxHealth; if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth(); m.displayHealth();
} }
@@ -2765,6 +2791,29 @@ const m = {
} }
} else { } else {
if (tech.isGroupThrow) {
const range = 810000
for (let i = 0; i < body.length; i++) {
const sub = Vector.sub(m.pos, body[i].position)
const dist2 = Vector.magnitudeSquared(sub)
if (dist2 < range) {
body[i].force.y -= body[i].mass * (simulation.g * 1.01); //remove a bit more then standard gravity
if (dist2 > 40000) {
const f = Vector.mult(Vector.normalise(sub), 0.0008 * body[i].mass)
body[i].force.x += f.x
body[i].force.y += f.y
Matter.Body.setVelocity(body[i], { x: 0.96 * body[i].velocity.x, y: 0.96 * body[i].velocity.y });
}
}
}
ctx.beginPath();
ctx.arc(m.pos.x, m.pos.y, Math.sqrt(range), 0, 2 * Math.PI);
ctx.fillStyle = "rgba(245,245,255,0.15)";
ctx.fill();
// ctx.globalCompositeOperation = "difference";
// ctx.globalCompositeOperation = "source-over";
}
//draw charge //draw charge
const x = m.pos.x + 15 * Math.cos(m.angle); const x = m.pos.x + 15 * Math.cos(m.angle);
const y = m.pos.y + 15 * Math.sin(m.angle); const y = m.pos.y + 15 * Math.sin(m.angle);
@@ -2885,6 +2934,21 @@ const m = {
}; };
expand(m.holdingTarget, Math.min(20, m.holdingTarget.mass * 3)) expand(m.holdingTarget, Math.min(20, m.holdingTarget.mass * 3))
} }
if (tech.isGroupThrow) {
const range = 810000
for (let i = 0; i < body.length; i++) {
if (body[i] !== m.holdingTarget) {
const dist2 = Vector.magnitudeSquared(Vector.sub(m.pos, body[i].position))
if (dist2 < range) {
const blockSpeed = 90 * charge * Math.min(0.85, 0.8 / Math.pow(body[i].mass, 0.25)) * Math.pow((range - dist2) / range, 0.2)
Matter.Body.setVelocity(body[i], {
x: body[i].velocity.x * 0.5 + Math.cos(m.angle) * blockSpeed,
y: body[i].velocity.y * 0.5 + Math.sin(m.angle) * blockSpeed
});
}
}
}
}
} }
} }
} else { } else {
@@ -3041,6 +3105,7 @@ const m = {
grabPowerUp() { //look for power ups to grab with field grabPowerUp() { //look for power ups to grab with field
if (m.fireCDcycle < m.cycle) m.fireCDcycle = m.cycle - 1 if (m.fireCDcycle < m.cycle) m.fireCDcycle = m.cycle - 1
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
if (tech.isEnergyNoAmmo && powerUp[i].name === "ammo") continue
const dxP = m.pos.x - powerUp[i].position.x; const dxP = m.pos.x - powerUp[i].position.x;
const dyP = m.pos.y - powerUp[i].position.y; const dyP = m.pos.y - powerUp[i].position.y;
const dist2 = dxP * dxP + dyP * dyP + 10; const dist2 = dxP * dxP + dyP * dyP + 10;
@@ -3868,15 +3933,9 @@ const m = {
} }
//add extra friction for horizontal motion //add extra friction for horizontal motion
if (input.down || input.up || input.left || input.right) { if (input.down || input.up || input.left || input.right) {
Matter.Body.setVelocity(player, { Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.98 });
x: player.velocity.x * 0.99,
y: player.velocity.y * 0.98
});
} else { //slow rise and fall } else { //slow rise and fall
Matter.Body.setVelocity(player, { Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.98 });
x: player.velocity.x * 0.99,
y: player.velocity.y * 0.98
});
} }
// if (tech.isFreezeMobs) { // if (tech.isFreezeMobs) {
// const ICE_DRAIN = 0.0005 // const ICE_DRAIN = 0.0005
@@ -4967,6 +5026,8 @@ const m = {
//grab power ups into the field //grab power ups into the field
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
if (tech.isEnergyNoAmmo && powerUp[i].name === "ammo") continue
const dxP = m.fieldPosition.x - powerUp[i].position.x; const dxP = m.fieldPosition.x - powerUp[i].position.x;
const dyP = m.fieldPosition.y - powerUp[i].position.y; const dyP = m.fieldPosition.y - powerUp[i].position.y;
const dist2 = dxP * dxP + dyP * dyP + 200; const dist2 = dxP * dxP + dyP * dyP + 200;
@@ -4978,14 +5039,11 @@ const m = {
powerUp[i].force.x += 0.05 * (dxP / Math.sqrt(dist2)) * powerUp[i].mass; powerUp[i].force.x += 0.05 * (dxP / Math.sqrt(dist2)) * powerUp[i].mass;
powerUp[i].force.y += 0.05 * (dyP / Math.sqrt(dist2)) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity powerUp[i].force.y += 0.05 * (dyP / Math.sqrt(dist2)) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity
//extra friction //extra friction
Matter.Body.setVelocity(powerUp[i], { Matter.Body.setVelocity(powerUp[i], { x: powerUp[i].velocity.x * 0.11, y: powerUp[i].velocity.y * 0.11 });
x: powerUp[i].velocity.x * 0.11,
y: powerUp[i].velocity.y * 0.11
});
if ( if (
dist2 < 5000 && dist2 < 5000 &&
!simulation.isChoosing && !simulation.isChoosing &&
(powerUp[i].name !== "heal" || m.maxHealth - m.health > 0.01 || tech.isOverHeal) (tech.isOverHeal || powerUp[i].name !== "heal" || m.maxHealth - m.health > 0.01)
// (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth) // (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth)
// (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity) // (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity)
) { //use power up if it is close enough ) { //use power up if it is close enough
@@ -5104,13 +5162,13 @@ const m = {
{ {
name: "wormhole", name: "wormhole",
//<strong class='color-worm'>wormholes</strong> attract <strong class='color-block'>blocks</strong> and power ups<br> //<strong class='color-worm'>wormholes</strong> attract <strong class='color-block'>blocks</strong> and power ups<br>
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong>+7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>7</strong> <strong class='color-f'>energy</strong> per second", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong> description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong>+8%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>7</strong> <strong class='color-f'>energy</strong> per second", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
drain: 0, drain: 0,
effect: function () { effect: function () {
m.fieldMeterColor = "#bbf" //"#0c5" m.fieldMeterColor = "#bbf" //"#0c5"
m.eyeFillColor = m.fieldMeterColor m.eyeFillColor = m.fieldMeterColor
m.duplicateChance = 0.07 m.duplicateChance = 0.08
m.fieldRange = 0 m.fieldRange = 0
powerUps.setPowerUpMode(); //needed after adjusting duplication chance powerUps.setPowerUpMode(); //needed after adjusting duplication chance
@@ -5146,6 +5204,7 @@ const m = {
//suck power ups //suck power ups
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
if (tech.isEnergyNoAmmo && powerUp[i].name === "ammo") continue
//which hole is closer //which hole is closer
const dxP1 = m.hole.pos1.x - powerUp[i].position.x; const dxP1 = m.hole.pos1.x - powerUp[i].position.x;
const dyP1 = m.hole.pos1.y - powerUp[i].position.y; const dyP1 = m.hole.pos1.y - powerUp[i].position.y;
@@ -5165,26 +5224,6 @@ const m = {
powerUp[i].force.y += 4 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity powerUp[i].force.y += 4 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity
Matter.Body.setVelocity(powerUp[i], { x: powerUp[i].velocity.x * 0.05, y: powerUp[i].velocity.y * 0.05 }); Matter.Body.setVelocity(powerUp[i], { x: powerUp[i].velocity.x * 0.05, y: powerUp[i].velocity.y * 0.05 });
if (dist2 < 1000 && !simulation.isChoosing) { //use power up if it is close enough if (dist2 < 1000 && !simulation.isChoosing) { //use power up if it is close enough
// if (true) { //AoE radiation effect
// const range = 800
// for (let i = 0, len = mob.length; i < len; ++i) {
// if (mob[i].alive && !mob[i].isShielded) {
// dist = Vector.magnitude(Vector.sub(powerUp[i].position, mob[i].position)) - mob[i].radius;
// if (dist < range) mobs.statusDoT(mob[i], 0.5) //apply radiation damage status effect on direct hits
// }
// }
// simulation.drawList.push({
// x: powerUp[i].position.x,
// y: powerUp[i].position.y,
// radius: range,
// color: "rgba(0,150,200,0.3)",
// time: 4
// });
// }
m.fieldRange *= 0.8 m.fieldRange *= 0.8
powerUps.onPickUp(powerUp[i]); powerUps.onPickUp(powerUp[i]);
powerUp[i].effect(); powerUp[i].effect();
@@ -6053,7 +6092,7 @@ const m = {
if (mob[k].isShielded) dmg *= 0.7 if (mob[k].isShielded) dmg *= 0.7
mob[k].damage(dmg, true); mob[k].damage(dmg, true);
if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && Math.random() < 0.5) { if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && Math.random() < 0.5) {
let type = tech.isEnergyNoAmmo ? "heal" : "ammo" let type = "ammo"
if (Math.random() < 0.4) { if (Math.random() < 0.4) {
type = "heal" type = "heal"
} else if (Math.random() < 0.4 && !tech.isSuperDeterminism) { } else if (Math.random() < 0.4 && !tech.isSuperDeterminism) {

View File

@@ -293,7 +293,7 @@ const powerUps = {
if (tech.isCancelRerolls) { if (tech.isCancelRerolls) {
for (let i = 0, len = 8 + 4 * Math.random(); i < len; i++) { for (let i = 0, len = 8 + 4 * Math.random(); i < len; i++) {
let spawnType let spawnType
if (Math.random() < 0.4 && !tech.isEnergyNoAmmo) { if (Math.random() < 0.4) {
spawnType = "ammo" spawnType = "ammo"
} else if (Math.random() < 0.33 && !tech.isSuperDeterminism) { } else if (Math.random() < 0.33 && !tech.isSuperDeterminism) {
spawnType = "research" spawnType = "research"
@@ -461,24 +461,24 @@ const powerUps = {
document.getElementById("choose-grid").classList.add('choose-grid-no-images'); document.getElementById("choose-grid").classList.add('choose-grid-no-images');
document.getElementById("choose-grid").classList.remove('choose-grid'); document.getElementById("choose-grid").classList.remove('choose-grid');
document.getElementById("choose-grid").style.gridTemplateColumns = "200px"//adjust this to increase the width of the whole menu, but mostly the center column document.getElementById("choose-grid").style.gridTemplateColumns = "200px"//adjust this to increase the width of the whole menu, but mostly the center column
let levelChoices = `<div class="choose-grid-module" style="font-size: 1.5rem;color:rgb(110,155,160);text-align:center;"><strong>WARP</strong></div>` let text = `<div class="choose-grid-module" style="font-size: 1.5rem;color:rgb(110,155,160);text-align:center;"><strong>WARP</strong></div>`
levelChoices += `<div class="choose-grid-module" style="font-size: 1rem;color:rgb(110,155,160);background-color:#444;text-align:center;">level.uniqueLevels</div>` text += `<div class="choose-grid-module" id="exit" style="font-size: 1rem;color:rgb(110,155,160);text-align:right;padding-right:5px;"><strong>cancel</strong></div>`
text += `<div class="choose-grid-module" style="font-size: 1rem;color:rgb(110,155,160);background-color:#444;text-align:center;">level.uniqueLevels</div>`
for (let i = 0; i < level.uniqueLevels.length; i++) { for (let i = 0; i < level.uniqueLevels.length; i++) {
levelChoices += `<div class="choose-grid-module" style="font-size: 1rem;padding-left:5px;" onclick="powerUps.warp.load('${level.uniqueLevels[i]}')">${level.uniqueLevels[i]}</div>` //id="uniqueLevels-warp-${i}" text += `<div class="choose-grid-module" style="font-size: 1rem;padding-left:5px;" onclick="powerUps.warp.load('${level.uniqueLevels[i]}')">${level.uniqueLevels[i]}</div>` //id="uniqueLevels-warp-${i}"
} }
levelChoices += `<div class="choose-grid-module" style="color:rgb(110,155,160);background-color:#444;text-align:center;">level.playableLevels</div>` text += `<div class="choose-grid-module" style="color:rgb(110,155,160);background-color:#444;text-align:center;">level.playableLevels</div>`
for (let i = 0; i < level.playableLevels.length; i++) { for (let i = 0; i < level.playableLevels.length; i++) {
levelChoices += `<div class="choose-grid-module" style="padding-left:5px;" onclick="powerUps.warp.load('${level.playableLevels[i]}')">${level.playableLevels[i]}</div>` text += `<div class="choose-grid-module" style="padding-left:5px;" onclick="powerUps.warp.load('${level.playableLevels[i]}')">${level.playableLevels[i]}</div>`
} }
levelChoices += `<div class="choose-grid-module" style="color:rgb(110,155,160);background-color:#444;text-align:center;">level.communityLevels</div>` text += `<div class="choose-grid-module" style="color:rgb(110,155,160);background-color:#444;text-align:center;">level.communityLevels</div>`
for (let i = 0; i < level.communityLevels.length; i++) { for (let i = 0; i < level.communityLevels.length; i++) {
levelChoices += `<div class="choose-grid-module" style="padding-left:5px;" onclick="powerUps.warp.load('${level.communityLevels[i]}')">${level.communityLevels[i]}</div>` text += `<div class="choose-grid-module" style="padding-left:5px;" onclick="powerUps.warp.load('${level.communityLevels[i]}')">${level.communityLevels[i]}</div>`
} }
levelChoices += `<div class="choose-grid-module" style="color:rgb(110,155,160);background-color:#444;text-align:center;">level.trainingLevels</div>` text += `<div class="choose-grid-module" style="color:rgb(110,155,160);background-color:#444;text-align:center;">level.trainingLevels</div>`
for (let i = 0; i < level.trainingLevels.length; i++) { for (let i = 0; i < level.trainingLevels.length; i++) {
levelChoices += `<div class="choose-grid-module" style="padding-left:5px;" onclick="powerUps.warp.load('${level.trainingLevels[i]}')">${level.trainingLevels[i]}</div>` text += `<div class="choose-grid-module" style="padding-left:5px;" onclick="powerUps.warp.load('${level.trainingLevels[i]}')">${level.trainingLevels[i]}</div>`
} }
let text = `${levelChoices} <div class="choose-grid-module" id="exit" style="font-size: 1.4rem;color:rgb(110,155,160);text-align:right;padding-right:5px;"><strong>exit</strong></div>`
document.getElementById("choose-grid").innerHTML = text document.getElementById("choose-grid").innerHTML = text
//show level info //show level info
document.getElementById("choose-grid").style.opacity = "1" document.getElementById("choose-grid").style.opacity = "1"
@@ -1777,10 +1777,7 @@ const powerUps = {
} }
}, },
spawn(x, y, name, moving = true, size = powerUps[name].size()) { spawn(x, y, name, moving = true, size = powerUps[name].size()) {
if ( if ((!tech.isSuperDeterminism || (name !== 'research'))) {
(!tech.isSuperDeterminism || (name !== 'research')) &&
!(tech.isEnergyNoAmmo && name === 'ammo')
) {
if (tech.isBoostReplaceAmmo && name === 'ammo') { if (tech.isBoostReplaceAmmo && name === 'ammo') {
name = 'boost' name = 'boost'
size = powerUps[name].size() size = powerUps[name].size()

View File

@@ -3,73 +3,151 @@
const simulation = { const simulation = {
loop() { }, //main game loop, gets set to normal or testing loop loop() { }, //main game loop, gets set to normal or testing loop
normalLoop() { normalLoop() {
simulation.gravity(); try {
Engine.update(engine, simulation.delta); simulation.gravity();
simulation.wipe(); Engine.update(engine, simulation.delta);
simulation.textLog(); simulation.wipe();
if (m.onGround) { simulation.textLog();
m.groundControl() if (m.onGround) {
} else { m.groundControl()
m.airControl() } else {
m.airControl()
}
m.move();
m.look();
simulation.camera();
level.custom();
powerUps.do();
mobs.draw();
simulation.draw.cons();
simulation.draw.body();
if (!m.isBodiesAsleep) mobs.loop();
mobs.healthBar();
m.draw();
m.hold();
level.customTopLayer();
simulation.draw.drawMapPath();
b.fire();
b.bulletRemove();
b.bulletDraw();
if (!m.isBodiesAsleep) b.bulletDo();
simulation.drawCircle();
simulation.runEphemera();
ctx.restore();
} catch (error) {
simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${(error.stack && error.stack.replace(/\n/g, "<br>")) || (error.message + ` <u>${error.filename}:${error.lineno}</u>`)}`);
} finally {
simulation.drawCursor();
} }
m.move();
m.look();
simulation.camera();
level.custom();
powerUps.do();
mobs.draw();
simulation.draw.cons();
simulation.draw.body();
if (!m.isBodiesAsleep) mobs.loop();
mobs.healthBar();
m.draw();
m.hold();
level.customTopLayer();
simulation.draw.drawMapPath();
b.fire();
b.bulletRemove();
b.bulletDraw();
if (!m.isBodiesAsleep) b.bulletDo();
simulation.drawCircle();
simulation.runEphemera();
ctx.restore();
simulation.drawCursor();
}, },
testingLoop() { testingLoop() {
simulation.gravity(); try {
Engine.update(engine, simulation.delta); simulation.gravity();
simulation.wipe(); Engine.update(engine, simulation.delta);
simulation.textLog(); simulation.wipe();
if (m.onGround) { simulation.textLog();
m.groundControl() if (m.onGround) {
} else { m.groundControl()
m.airControl() } else {
} m.airControl()
m.move(); }
m.look(); m.move();
simulation.camera(); m.look();
level.custom(); simulation.camera();
m.draw(); level.custom();
m.hold(); m.draw();
level.customTopLayer(); m.hold();
simulation.draw.wireFrame(); level.customTopLayer();
if (input.fire && m.fireCDcycle < m.cycle) { simulation.draw.wireFrame();
m.fireCDcycle = m.cycle + 15; //fire cooldown if (input.fire && m.fireCDcycle < m.cycle) {
for (let i = 0, len = mob.length; i < len; i++) { m.fireCDcycle = m.cycle + 15; //fire cooldown
if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) { for (let i = 0, len = mob.length; i < len; i++) {
console.log(mob[i]) if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) {
console.log(mob[i])
}
} }
} }
simulation.draw.cons();
simulation.draw.testing();
simulation.drawCircle();
simulation.runEphemera();
simulation.constructCycle()
} catch (error) {
simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${(error.stack && error.stack.replace(/\n/g, "<br>")) || (error.message + ` <u>${error.filename}:${error.lineno}</u>`)}`);
} finally {
ctx.restore();
simulation.testingOutput();
simulation.drawCursor();
} }
simulation.draw.cons();
simulation.draw.testing();
simulation.drawCircle();
simulation.runEphemera();
simulation.constructCycle()
ctx.restore();
simulation.testingOutput();
simulation.drawCursor();
}, },
// normalLoop() {
// simulation.gravity();
// Engine.update(engine, simulation.delta);
// simulation.wipe();
// simulation.textLog();
// if (m.onGround) {
// m.groundControl()
// } else {
// m.airControl()
// }
// m.move();
// m.look();
// simulation.camera();
// level.custom();
// powerUps.do();
// mobs.draw();
// simulation.draw.cons();
// simulation.draw.body();
// if (!m.isBodiesAsleep) mobs.loop();
// mobs.healthBar();
// m.draw();
// m.hold();
// level.customTopLayer();
// simulation.draw.drawMapPath();
// b.fire();
// b.bulletRemove();
// b.bulletDraw();
// if (!m.isBodiesAsleep) b.bulletDo();
// simulation.drawCircle();
// simulation.runEphemera();
// ctx.restore();
// simulation.drawCursor();
// },
// testingLoop() {
// simulation.gravity();
// Engine.update(engine, simulation.delta);
// simulation.wipe();
// simulation.textLog();
// if (m.onGround) {
// m.groundControl()
// } else {
// m.airControl()
// }
// m.move();
// m.look();
// simulation.camera();
// level.custom();
// m.draw();
// m.hold();
// level.customTopLayer();
// simulation.draw.wireFrame();
// if (input.fire && m.fireCDcycle < m.cycle) {
// m.fireCDcycle = m.cycle + 15; //fire cooldown
// for (let i = 0, len = mob.length; i < len; i++) {
// if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) {
// console.log(mob[i])
// }
// }
// }
// simulation.draw.cons();
// simulation.draw.testing();
// simulation.drawCircle();
// simulation.runEphemera();
// simulation.constructCycle()
// ctx.restore();
// simulation.testingOutput();
// simulation.drawCursor();
// },
isTimeSkipping: false, isTimeSkipping: false,
timeSkip(cycles = 60) { timeSkip(cycles = 60) {
simulation.isTimeSkipping = true; simulation.isTimeSkipping = true;
@@ -864,7 +942,7 @@ const simulation = {
} else { } else {
Composite.add(engine.world, [player]) Composite.add(engine.world, [player])
} }
// shuffle(level.constraint) shuffle(level.constraint)
level.populateLevels() level.populateLevels()
input.endKeySensing(); input.endKeySensing();
simulation.ephemera = [] simulation.ephemera = []
@@ -889,6 +967,7 @@ const simulation = {
tech.plasmaBotCount = 0; tech.plasmaBotCount = 0;
tech.missileBotCount = 0; tech.missileBotCount = 0;
m.isSwitchingWorlds = false
simulation.isChoosing = false; simulation.isChoosing = false;
b.setFireMethod() b.setFireMethod()
b.setFireCD(); b.setFireCD();
@@ -935,7 +1014,7 @@ const simulation = {
m.onGround = false m.onGround = false
m.lastOnGroundCycle = 0 m.lastOnGroundCycle = 0
m.health = 0; m.health = 0;
level.isNoHeal = false level.isLowHeal = false
m.addHealth(0.25) m.addHealth(0.25)
m.drop(); m.drop();
m.holdingTarget = null m.holdingTarget = null

View File

@@ -917,7 +917,7 @@ const tech = {
//give the tech that was found for this gun //give the tech that was found for this gun
if (gunTechPool.length) { if (gunTechPool.length) {
const index = Math.floor(Math.random() * gunTechPool.length) const index = Math.floor(Math.random() * gunTechPool.length)
simulation.inGameConsole(`<span class='color-var'>tech</span>.giveTech("<span class='color-text'>${tech.tech[gunTechPool[index]].name}</span>")`, 360) simulation.inGameConsole(`<span class='color-var'>tech</span>.giveTech("<strong class='color-text'>${tech.tech[gunTechPool[index]].name}</strong>")`, 360)
tech.giveTech(gunTechPool[index]) // choose from the gun pool tech.giveTech(gunTechPool[index]) // choose from the gun pool
simulation.boldActiveGunHUD(); simulation.boldActiveGunHUD();
} }
@@ -1103,7 +1103,7 @@ const tech = {
}, },
{ {
name: "non-renewables", name: "non-renewables",
description: `<strong>2x</strong> <strong class='color-d'>damage</strong><br>${powerUps.orb.ammo()} can't <strong>spawn</strong>`, description: `<strong>2x</strong> <strong class='color-d'>damage</strong><br>you can't pickup ${powerUps.orb.ammo()}`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -1116,15 +1116,17 @@ const tech = {
effect() { effect() {
tech.damage *= this.damage tech.damage *= this.damage
tech.isEnergyNoAmmo = true; tech.isEnergyNoAmmo = true;
powerUps.ammo.color = "#c1c6c9"//"#abb3b8"// "#535e63"
}, },
remove() { remove() {
if (this.count && m.alive) tech.damage /= this.damage if (this.count && m.alive) tech.damage /= this.damage
tech.isEnergyNoAmmo = false; tech.isEnergyNoAmmo = false;
powerUps.ammo.color = "#467"
} }
}, },
{ {
name: "desublimated ammunition", name: "desublimated ammunition",
description: `if <strong>crouching</strong><br>alternating shots use no <strong class='color-ammo'>ammo</strong>`, description: `if <strong>crouching</strong><br>alternating shots cost no <strong class='color-ammo'>ammo</strong>`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2419,6 +2421,24 @@ const tech = {
tech.blockDamage = 0.075 tech.blockDamage = 0.075
} }
}, },
{
name: "Halbach array",
description: "throwing a <strong class='color-block'>block</strong> will<br>also throw other nearby <strong class='color-block'>blocks</strong>",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return (tech.blockDamage > 0.075 || tech.isPrinter) && m.fieldMode !== 8 && m.fieldMode !== 9 && !tech.isTokamak
},
requires: "mass driver, printer, not wormhole, pilot wave, tokamak",
effect() {
tech.isGroupThrow = true
},
remove() {
tech.isGroupThrow = false
}
},
{ {
name: "inflation", name: "inflation",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Inflation_(cosmology)' class="link">inflation</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Inflation_(cosmology)' class="link">inflation</a>`,
@@ -2430,7 +2450,7 @@ const tech = {
allowed() { allowed() {
return (tech.blockDamage > 0.075 || tech.isPrinter) && m.fieldMode !== 8 && m.fieldMode !== 9 && !tech.isTokamak return (tech.blockDamage > 0.075 || tech.isPrinter) && m.fieldMode !== 8 && m.fieldMode !== 9 && !tech.isTokamak
}, },
requires: "mass driver, not pilot wave, tokamak, wormhole", requires: "mass driver, printer, not pilot wave, tokamak, wormhole",
effect() { effect() {
tech.isAddBlockMass = true tech.isAddBlockMass = true
}, },
@@ -2448,7 +2468,7 @@ const tech = {
allowed() { allowed() {
return (tech.blockDamage > 0.075 || tech.isPrinter) && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && m.fieldUpgrades[m.fieldMode].name !== "wormhole" && !tech.isTokamak return (tech.blockDamage > 0.075 || tech.isPrinter) && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && m.fieldUpgrades[m.fieldMode].name !== "wormhole" && !tech.isTokamak
}, },
requires: "mass driver, not pilot wave, tokamak, wormhole", requires: "mass driver, printer, not pilot wave, tokamak, wormhole",
effect() { effect() {
tech.isBlockRestitution = true tech.isBlockRestitution = true
}, },
@@ -2466,7 +2486,7 @@ const tech = {
allowed() { allowed() {
return (tech.blockDamage > 0.075 || tech.isPrinter) && !tech.nailsDeathMob && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.iceIXOnDeath return (tech.blockDamage > 0.075 || tech.isPrinter) && !tech.nailsDeathMob && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.iceIXOnDeath
}, },
requires: "mass driver, no other mob death tech", requires: "mass driver, printer, no other mob death tech",
effect() { effect() {
tech.isMobBlockFling = true tech.isMobBlockFling = true
}, },
@@ -2486,7 +2506,7 @@ const tech = {
allowed() { allowed() {
return (tech.blockDamage > 0.075 || tech.isPrinter) && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && !tech.isTokamak return (tech.blockDamage > 0.075 || tech.isPrinter) && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && !tech.isTokamak
}, },
requires: "mass driver, not pilot wave, tokamak", requires: "mass driver, printer, not pilot wave, tokamak",
effect() { effect() {
tech.isBlockPowerUps = true tech.isBlockPowerUps = true
}, },
@@ -2688,7 +2708,7 @@ const tech = {
}, },
requires: "", requires: "",
effect() { effect() {
m.collisionImmuneCycles += 480; m.collisionImmuneCycles += 420;
if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage
}, },
remove() { remove() {
@@ -5994,9 +6014,9 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("grenades") && !tech.isVacuumBomb && !tech.isSmartRadius return tech.haveGunCheck("grenades") && !tech.isVacuumBomb && !tech.isSmartRadius && !tech.isEnergyHealth
}, },
requires: "grenades, not vacuum bomb, shaped charges", requires: "grenades, not vacuum bomb, shaped charges, mass-energy",
effect() { effect() {
tech.isImmuneExplosion = true; tech.isImmuneExplosion = true;
tech.isRPG = true; tech.isRPG = true;
@@ -7281,7 +7301,7 @@ const tech = {
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return ((tech.haveGunCheck("wave") && tech.isInfiniteWaveAmmo) || tech.haveGunCheck("laser") || (tech.haveGunCheck("harpoon") && !tech.isRailGun)) && !tech.isEnergyNoAmmo return ((tech.haveGunCheck("wave") && tech.isInfiniteWaveAmmo) || tech.haveGunCheck("laser") || (tech.haveGunCheck("harpoon") && !tech.isRailGun))
}, },
requires: "harpoon, laser, wave, frequency, not railgun, non-renewables", requires: "harpoon, laser, wave, frequency, not railgun, non-renewables",
effect() { effect() {

View File

@@ -1,17 +1,26 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
images are back as an option due to public outcry tech: Halbach array - throwing a block will also throw other nearby blocks
tech non-renewables now spawns ammo, but ammo can't be picked up
grenade tech that cause multiple explosions have less knock back for mobs
constraint: 0->0.5x healing
wormhole 7->8% duplication
many worlds takes a few frames between each tech given
bug fixes bug fixes
getting a power up quickly after warp, difficulty or instructions power ups was making the screen go blank harpoon ammo gain on autonomous defense fixed
heuristics resets on death properly now constraints are properly randomized again
******************************************************** BUGS ******************************************************** ******************************************************** BUGS ********************************************************
couple reports of crashes from many-worlds
can't consistenly reproduce, but it happened several times this way around level 5-7
on initial level I press T and took the warp and exited it, then I too a field and the screen went blank for me crash on factory level 7
might be linked to having all the guns?
the crash was in matter.js something about collisions and undefined
maybe too many things were spawned in the same spot?
also occurs when you just gain many random tech in testing mode
figure out why seeded random isn't making runs the same: figure out why seeded random isn't making runs the same:
shuffle is being used for a wide variety of things that don't need a seeded random shuffle is being used for a wide variety of things that don't need a seeded random
@@ -41,30 +50,14 @@ player can become crouched while not touching the ground if they exit the ground
*********************************************************** TODO ***************************************************** *********************************************************** TODO *****************************************************
make a text orb for JUNK text to make JUNK more clear
extended vertical flip to edge cases: extended vertical flip to edge cases:
!!stored circular graphics simulation.drawList.push !!stored circular graphics simulation.drawList.push
add more tips:
download latest version of n-gon
https://codeload.github.com/landgreen/n-gon/zip/refs/heads/master
new level based laser element new level based laser element
!!update new version into other levels !!update new version into other levels
level technique: pairs of touch activated elevators jump on one to get high enough to jump on the next one
new vertical flip level
long horizontal
several buttons
shorten flip time?
constraints should show future constraints in pause menu
pre calculate all constraints for up to 13 levels?
loop constraints after that
procedural animation procedural animation
https://www.youtube.com/watch?v=qlfh_rv6khY https://www.youtube.com/watch?v=qlfh_rv6khY
@@ -93,7 +86,7 @@ tech: - after killing a Boss
new level - rework testChamber new level - rework testChamber
Boss (or mob) that quickly moves towards player, but they moves perpendicularly to player, like dodging Boss (or mob) that quickly moves towards player, but then moves perpendicularly to player, like dodging
could respond to when player presses fire key or to when it takes damage could respond to when player presses fire key or to when it takes damage
new snakeBoss type that eats mobs new snakeBoss type that eats mobs
@@ -139,12 +132,6 @@ increase mass and movement speed at the same time
possible player.mass bad interactions possible player.mass bad interactions
grapple grapple
bullets should trigger shrinking platforms level element?
level element - player activated elevators
could be fast and throw player
could just rise up slow (slow might have a bad jerky animation)
rework energy and health HUD rework energy and health HUD
make both diegetic? make both diegetic?
how? not sure there is a good way to do this... how? not sure there is a good way to do this...
@@ -158,12 +145,6 @@ tech - after a power up is duplicated
gain 1.01x damage permanently gain 1.01x damage permanently
cool name: cool name:
field tech: negative mass - quickly pull/teleport in all nearby blocks and then fire them away from player
how does player triggers effect?
picking up a block pulls in all nearby blocks, throwing block fires all nearby blocks
taking damage
auto aim 50% of blocks at mobs
after picking up heals gain ____ after picking up heals gain ____
0.1x damage taken for 12s 0.1x damage taken for 12s
after picking up ammo gain ____ after picking up ammo gain ____