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() {
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
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
mob[i].damage(dmg * damageScale * m.dmgScale);
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) {
mobs.statusStun(mob[i], 30)
} else if (!mob[i].isInvulnerable) {
@@ -536,7 +536,7 @@ const b = {
damageScale *= 0.87 //reduced damage for each additional explosion target
} else if (!mob[i].seePlayer.recall && dist < alertRange) {
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) {
mobs.statusStun(mob[i], 30)
} else if (!mob[i].isInvulnerable) {
@@ -630,11 +630,8 @@ const b = {
count++
if (count < 84) requestAnimationFrame(cycle);
if (!(count % 7)) {
const unit = Vector.rotate({
x: 1,
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
const unit = Vector.rotate({ x: 1, 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)`, 0.2); //makes bullet do explosive damage at end
}
}
}
@@ -656,7 +653,7 @@ const b = {
x: 1,
y: 0
}, 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 === 0) {
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) {
const color = `hsla(${360 * Math.random()},100%,66%,0.6)`
@@ -686,7 +683,7 @@ const b = {
x: 1,
y: 0
}, 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) {
@@ -696,7 +693,7 @@ const b = {
x: 1,
y: 0
}, 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++
@@ -1611,6 +1608,7 @@ const b = {
Matter.Body.setVelocity(this.caughtPowerUp, { x: 0, y: 0 })
} else {
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (tech.isEnergyNoAmmo && powerUp[i].name === "ammo") continue
const radius = powerUp[i].circleRadius + 50
if (Vector.magnitudeSquared(Vector.sub(this.vertices[2], powerUp[i].position)) < radius * radius) {
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 })
} else { //&& simulation.cycle % 2
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (tech.isEnergyNoAmmo && powerUp[i].name === "ammo") continue
const radius = powerUp[i].circleRadius + 50
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) {
@@ -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
if (
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)
// &&(b.inventory.length > 1 || powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab)
!(
(m.health > 0.93 * m.maxHealth && !tech.isDroneGrab && powerUp[i].name === "heal") ||
(tech.isSuperDeterminism && powerUp[i].name === "field") ||
((tech.isEnergyNoAmmo || b.inventory.length === 0) && powerUp[i].name === "ammo")
)
) {
//draw pickup for a single cycle
ctx.beginPath();
@@ -3337,11 +3338,11 @@ const b = {
//look for power ups to lock onto
let closeDist = Infinity;
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (
(powerUp[i].name !== "heal" || m.health < 0.97 * m.maxHealth || tech.isDroneGrab) &&
(powerUp[i].name !== "field" || !tech.isSuperDeterminism)
// &&(b.inventory.length > 1 || powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab)
) {
if (!(
(m.health > 0.93 * m.maxHealth && !tech.isDroneGrab && powerUp[i].name === "heal") ||
(tech.isSuperDeterminism && powerUp[i].name === "field") ||
((tech.isEnergyNoAmmo || b.inventory.length === 0) && powerUp[i].name === "ammo")
)) {
if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) {
//draw pickup for a single cycle
ctx.beginPath();
@@ -3543,9 +3544,11 @@ const b = {
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (
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)
// &&(powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab)
!(
(m.health > 0.93 * m.maxHealth && !tech.isDroneGrab && powerUp[i].name === "heal") ||
(tech.isSuperDeterminism && powerUp[i].name === "field") ||
((tech.isEnergyNoAmmo || b.inventory.length === 0) && powerUp[i].name === "ammo")
)
) {
//draw pickup for a single cycle
ctx.beginPath();
@@ -3574,11 +3577,11 @@ const b = {
//look for power ups to lock onto
let closeDist = Infinity;
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (
(powerUp[i].name !== "heal" || m.health < 0.93 * m.maxHealth || tech.isDroneGrab) &&
(powerUp[i].name !== "field" || !tech.isSuperDeterminism)
// &&(powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab)
) {
if (!(
(m.health > 0.93 * m.maxHealth && !tech.isDroneGrab && powerUp[i].name === "heal") ||
(tech.isSuperDeterminism && powerUp[i].name === "field") ||
((tech.isEnergyNoAmmo || b.inventory.length === 0) && powerUp[i].name === "ammo")
)) {
if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) {
//draw pickup for a single cycle
ctx.beginPath();

View File

@@ -163,10 +163,10 @@ function collisionChecks(event) {
let count = maxCount - 1
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)
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
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
}
}
@@ -245,8 +245,7 @@ function collisionChecks(event) {
mob[k].damage(dmg, true);
if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && Math.random() < 0.5) {
options = ["coupling", "boost", "heal", "research"]
if (!tech.isEnergyNoAmmo) options.push("ammo")
options = ["coupling", "boost", "heal", "research", "ammo"]
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.addJunkTechToPool(0.5)
// 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
// powerUps.research.count = 3
// tech.isHookWire = true
@@ -38,21 +38,21 @@ const level = {
// simulation.molecularMode = 2
// 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("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
// tech.laserColor = "#fff"
// tech.laserColorAlpha = "rgba(255, 255, 255, 0.5)"
// b.guns[8].ammo = 100000000
// requestAnimationFrame(() => { tech.giveTech("stimulated emission") });
// requestAnimationFrame(() => { tech.giveTech("non-renewables") });
// tech.giveTech("dark matter")
// tech.addJunkTechToPool(0.5)
// for (let i = 0; i < 1; ++i) tech.giveTech("entropic gravity")
// for (let i = 0; i < 1; ++i) tech.giveTech("nitinol")
// for (let i = 0; i < 1; ++i) tech.giveTech("many-worlds")
// for (let i = 0; i < 1; ++i) tech.giveTech("quantum immortality")
// m.skin.egg();
// for (let i = 0; i < 1; ++i) tech.giveTech("depolarization")
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("wikipedia") });
// for (let i = 0; i < 1; ++i) tech.giveTech("non-renewables")
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("quasiparticles") });
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("field coupling") });
// for (let i = 0; i < 1; i++) tech.giveTech("interest")
// m.lastKillCycle = m.cycle
@@ -64,7 +64,7 @@ const 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) 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")
// lore.techCount = 1
// level.levelsCleared = 10
// localSettings.loreCount = 2 //this sets what conversation is heard
// localSettings.loreCount = 1 //this sets what conversation is heard
// localSettings.levelsClearedLastGame = 10
// 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
@@ -333,12 +333,12 @@ const level = {
constraintDescription2: "",
constraint: [
{
description: "healing disabled",
description: "0.5x healing",
effect() {
level.isNoHeal = true
level.isLowHeal = true
},
remove() {
level.isNoHeal = false
level.isLowHeal = false
}
},
{
@@ -599,7 +599,7 @@ const level = {
isReducedRegen: 1,
isHideHealth: false,
isNoPause: false,
isNoHeal: false,
isLowHeal: false,
levelAnnounce() {
const cheating = simulation.isCheating ? "(testing)" : ""
if (level.levelsCleared === 0) {

View File

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

View File

@@ -316,101 +316,127 @@ const m = {
m.isHolding = true;
},
alive: false,
isSwitchingWorlds: false,
switchWorlds() {
powerUps.boost.endCycle = 0
const totalGuns = b.inventory.length
//track ammo/ ammoPack count
let ammoCount = 0
for (let i = 0, len = b.inventory.length; i < len; i++) {
if (b.guns[b.inventory[i]].ammo !== Infinity) {
ammoCount += b.guns[b.inventory[i]].ammo / b.guns[b.inventory[i]].ammoPack
} else {
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
if (!m.isSwitchingWorlds) {
powerUps.boost.endCycle = 0
const totalGuns = b.inventory.length
//track ammo/ ammoPack count
let ammoCount = 0
for (let i = 0, len = b.inventory.length; i < len; i++) {
if (b.guns[b.inventory[i]].ammo !== Infinity) {
ammoCount += b.guns[b.inventory[i]].ammo / b.guns[b.inventory[i]].ammoPack
} 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
ammoCount += 5
}
}
}
// 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
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))))
}
// console.log(b.activeGun)
//randomize tech
for (let i = 0; i < totalTech; i++) {
//find what tech I could get
let options = [];
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].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 (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 {
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
if (options.length > 0) tech.giveTech(options[Math.floor(Math.random() * options.length)])
// 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
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
death() {
@@ -440,8 +466,8 @@ const m = {
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
spawn.setSpawnList(); //new mob types
simulation.clearNow = true; //triggers a map reset
m.switchWorlds()
// simulation.clearNow = true; //triggers a map reset
// m.switchWorlds()
simulation.isTextLogOpen = true;
simulation.inGameConsole(`simulation.amplitude <span class='color-symbol'>=</span> 0.${len - i - 1}`, swapPeriod);
simulation.isTextLogOpen = false;
@@ -528,8 +554,8 @@ const m = {
// }
},
addHealth(heal) {
if (!tech.isEnergyHealth && !level.isNoHeal) {
m.health += heal * simulation.healScale;
if (!tech.isEnergyHealth) {
m.health += heal * simulation.healScale * (level.isLowHeal ? 0.5 : 1);
if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth();
}
@@ -2765,6 +2791,29 @@ const m = {
}
} 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
const x = m.pos.x + 15 * Math.cos(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))
}
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 {
@@ -3041,6 +3105,7 @@ const m = {
grabPowerUp() { //look for power ups to grab with field
if (m.fireCDcycle < m.cycle) m.fireCDcycle = m.cycle - 1
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 dyP = m.pos.y - powerUp[i].position.y;
const dist2 = dxP * dxP + dyP * dyP + 10;
@@ -3868,15 +3933,9 @@ const m = {
}
//add extra friction for horizontal motion
if (input.down || input.up || input.left || input.right) {
Matter.Body.setVelocity(player, {
x: player.velocity.x * 0.99,
y: player.velocity.y * 0.98
});
Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.98 });
} else { //slow rise and fall
Matter.Body.setVelocity(player, {
x: player.velocity.x * 0.99,
y: player.velocity.y * 0.98
});
Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.98 });
}
// if (tech.isFreezeMobs) {
// const ICE_DRAIN = 0.0005
@@ -4967,6 +5026,8 @@ const m = {
//grab power ups into the field
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 dyP = m.fieldPosition.y - powerUp[i].position.y;
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.y += 0.05 * (dyP / Math.sqrt(dist2)) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity
//extra friction
Matter.Body.setVelocity(powerUp[i], {
x: powerUp[i].velocity.x * 0.11,
y: powerUp[i].velocity.y * 0.11
});
Matter.Body.setVelocity(powerUp[i], { x: powerUp[i].velocity.x * 0.11, y: powerUp[i].velocity.y * 0.11 });
if (
dist2 < 5000 &&
!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 !== "ammo" || b.guns[b.activeGun].ammo !== Infinity)
) { //use power up if it is close enough
@@ -5104,13 +5162,13 @@ const m = {
{
name: "wormhole",
//<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,
effect: function () {
m.fieldMeterColor = "#bbf" //"#0c5"
m.eyeFillColor = m.fieldMeterColor
m.duplicateChance = 0.07
m.duplicateChance = 0.08
m.fieldRange = 0
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
@@ -5146,6 +5204,7 @@ const m = {
//suck power ups
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (tech.isEnergyNoAmmo && powerUp[i].name === "ammo") continue
//which hole is closer
const dxP1 = m.hole.pos1.x - powerUp[i].position.x;
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
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 (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
powerUps.onPickUp(powerUp[i]);
powerUp[i].effect();
@@ -6053,7 +6092,7 @@ const m = {
if (mob[k].isShielded) dmg *= 0.7
mob[k].damage(dmg, true);
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) {
type = "heal"
} else if (Math.random() < 0.4 && !tech.isSuperDeterminism) {

View File

@@ -293,7 +293,7 @@ const powerUps = {
if (tech.isCancelRerolls) {
for (let i = 0, len = 8 + 4 * Math.random(); i < len; i++) {
let spawnType
if (Math.random() < 0.4 && !tech.isEnergyNoAmmo) {
if (Math.random() < 0.4) {
spawnType = "ammo"
} else if (Math.random() < 0.33 && !tech.isSuperDeterminism) {
spawnType = "research"
@@ -461,24 +461,24 @@ const powerUps = {
document.getElementById("choose-grid").classList.add('choose-grid-no-images');
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
let levelChoices = `<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>`
let text = `<div class="choose-grid-module" style="font-size: 1.5rem;color:rgb(110,155,160);text-align:center;"><strong>WARP</strong></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++) {
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++) {
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++) {
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++) {
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
//show level info
document.getElementById("choose-grid").style.opacity = "1"
@@ -1777,10 +1777,7 @@ const powerUps = {
}
},
spawn(x, y, name, moving = true, size = powerUps[name].size()) {
if (
(!tech.isSuperDeterminism || (name !== 'research')) &&
!(tech.isEnergyNoAmmo && name === 'ammo')
) {
if ((!tech.isSuperDeterminism || (name !== 'research'))) {
if (tech.isBoostReplaceAmmo && name === 'ammo') {
name = 'boost'
size = powerUps[name].size()

View File

@@ -3,73 +3,151 @@
const simulation = {
loop() { }, //main game loop, gets set to normal or testing loop
normalLoop() {
simulation.gravity();
Engine.update(engine, simulation.delta);
simulation.wipe();
simulation.textLog();
if (m.onGround) {
m.groundControl()
} else {
m.airControl()
try {
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();
} 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() {
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])
try {
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()
} 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,
timeSkip(cycles = 60) {
simulation.isTimeSkipping = true;
@@ -864,7 +942,7 @@ const simulation = {
} else {
Composite.add(engine.world, [player])
}
// shuffle(level.constraint)
shuffle(level.constraint)
level.populateLevels()
input.endKeySensing();
simulation.ephemera = []
@@ -889,6 +967,7 @@ const simulation = {
tech.plasmaBotCount = 0;
tech.missileBotCount = 0;
m.isSwitchingWorlds = false
simulation.isChoosing = false;
b.setFireMethod()
b.setFireCD();
@@ -935,7 +1014,7 @@ const simulation = {
m.onGround = false
m.lastOnGroundCycle = 0
m.health = 0;
level.isNoHeal = false
level.isLowHeal = false
m.addHealth(0.25)
m.drop();
m.holdingTarget = null

View File

@@ -917,7 +917,7 @@ const tech = {
//give the tech that was found for this gun
if (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
simulation.boldActiveGunHUD();
}
@@ -1103,7 +1103,7 @@ const tech = {
},
{
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,
count: 0,
frequency: 1,
@@ -1116,15 +1116,17 @@ const tech = {
effect() {
tech.damage *= this.damage
tech.isEnergyNoAmmo = true;
powerUps.ammo.color = "#c1c6c9"//"#abb3b8"// "#535e63"
},
remove() {
if (this.count && m.alive) tech.damage /= this.damage
tech.isEnergyNoAmmo = false;
powerUps.ammo.color = "#467"
}
},
{
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,
count: 0,
frequency: 1,
@@ -2419,6 +2421,24 @@ const tech = {
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",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Inflation_(cosmology)' class="link">inflation</a>`,
@@ -2430,7 +2450,7 @@ const tech = {
allowed() {
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() {
tech.isAddBlockMass = true
},
@@ -2448,7 +2468,7 @@ const tech = {
allowed() {
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() {
tech.isBlockRestitution = true
},
@@ -2466,7 +2486,7 @@ const tech = {
allowed() {
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() {
tech.isMobBlockFling = true
},
@@ -2486,7 +2506,7 @@ const tech = {
allowed() {
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() {
tech.isBlockPowerUps = true
},
@@ -2688,7 +2708,7 @@ const tech = {
},
requires: "",
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
},
remove() {
@@ -5994,9 +6014,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
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() {
tech.isImmuneExplosion = true;
tech.isRPG = true;
@@ -7281,7 +7301,7 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
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",
effect() {

View File

@@ -1,17 +1,26 @@
******************************************************** 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
getting a power up quickly after warp, difficulty or instructions power ups was making the screen go blank
heuristics resets on death properly now
harpoon ammo gain on autonomous defense fixed
constraints are properly randomized again
******************************************************** BUGS ********************************************************
can't consistenly reproduce, but it happened several times this way
on initial level I press T and took the warp and exited it, then I too a field and the screen went blank
couple reports of crashes from many-worlds
around level 5-7
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:
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 *****************************************************
make a text orb for JUNK text to make JUNK more clear
extended vertical flip to edge cases:
!!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
!!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
https://www.youtube.com/watch?v=qlfh_rv6khY
@@ -93,7 +86,7 @@ tech: - after killing a Boss
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
new snakeBoss type that eats mobs
@@ -139,12 +132,6 @@ increase mass and movement speed at the same time
possible player.mass bad interactions
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
make both diegetic?
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
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 ____
0.1x damage taken for 12s
after picking up ammo gain ____