diff --git a/img/Halbach array.webp b/img/Halbach array.webp new file mode 100644 index 0000000..5d166c3 Binary files /dev/null and b/img/Halbach array.webp differ diff --git a/js/bullet.js b/js/bullet.js index 49e6fd3..93f4e75 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -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(); diff --git a/js/engine.js b/js/engine.js index c60ec97..e3a655d 100644 --- a/js/engine.js +++ b/js/engine.js @@ -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)]); } diff --git a/js/level.js b/js/level.js index df02b0c..1b71906 100644 --- a/js/level.js +++ b/js/level.js @@ -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) { diff --git a/js/mob.js b/js/mob.js index 35eb6bd..102434b 100644 --- a/js/mob.js +++ b/js/mob.js @@ -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) { diff --git a/js/player.js b/js/player.js index 861e610..e204643 100644 --- a/js/player.js +++ b/js/player.js @@ -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 = 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", //wormholes attract blocks and power ups
- description: "use energy to tunnel through a wormhole
+7% chance to duplicate spawned power ups
7 energy per second", //
bullets may also traverse wormholes + description: "use energy to tunnel through a wormhole
+8% chance to duplicate spawned power ups
7 energy per second", //
bullets may also traverse wormholes 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) { diff --git a/js/powerup.js b/js/powerup.js index 64aa91c..6fedd09 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -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 = `
WARP
` - levelChoices += `
level.uniqueLevels
` + let text = `
WARP
` + text += `
cancel
` + text += `
level.uniqueLevels
` for (let i = 0; i < level.uniqueLevels.length; i++) { - levelChoices += `
${level.uniqueLevels[i]}
` //id="uniqueLevels-warp-${i}" + text += `
${level.uniqueLevels[i]}
` //id="uniqueLevels-warp-${i}" } - levelChoices += `
level.playableLevels
` + text += `
level.playableLevels
` for (let i = 0; i < level.playableLevels.length; i++) { - levelChoices += `
${level.playableLevels[i]}
` + text += `
${level.playableLevels[i]}
` } - levelChoices += `
level.communityLevels
` + text += `
level.communityLevels
` for (let i = 0; i < level.communityLevels.length; i++) { - levelChoices += `
${level.communityLevels[i]}
` + text += `
${level.communityLevels[i]}
` } - levelChoices += `
level.trainingLevels
` + text += `
level.trainingLevels
` for (let i = 0; i < level.trainingLevels.length; i++) { - levelChoices += `
${level.trainingLevels[i]}
` + text += `
${level.trainingLevels[i]}
` } - let text = `${levelChoices}
exit
` 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() diff --git a/js/simulation.js b/js/simulation.js index 2a38814..3ba0920 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -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(`ERROR: ${(error.stack && error.stack.replace(/\n/g, "
")) || (error.message + ` ${error.filename}:${error.lineno}`)}`); + } 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(`ERROR: ${(error.stack && error.stack.replace(/\n/g, "
")) || (error.message + ` ${error.filename}:${error.lineno}`)}`); + } 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 diff --git a/js/tech.js b/js/tech.js index f98eae7..0073bf4 100644 --- a/js/tech.js +++ b/js/tech.js @@ -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(`tech.giveTech("${tech.tech[gunTechPool[index]].name}")`, 360) + simulation.inGameConsole(`tech.giveTech("${tech.tech[gunTechPool[index]].name}")`, 360) tech.giveTech(gunTechPool[index]) // choose from the gun pool simulation.boldActiveGunHUD(); } @@ -1103,7 +1103,7 @@ const tech = { }, { name: "non-renewables", - description: `2x damage
${powerUps.orb.ammo()} can't spawn`, + description: `2x damage
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 crouching
alternating shots use no ammo`, + description: `if crouching
alternating shots cost no ammo`, maxCount: 1, count: 0, frequency: 1, @@ -2419,6 +2421,24 @@ const tech = { tech.blockDamage = 0.075 } }, + { + name: "Halbach array", + description: "throwing a block will
also throw other nearby blocks", + 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: `inflation`, @@ -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() { diff --git a/todo.txt b/todo.txt index 48c2cbf..f521596 100644 --- a/todo.txt +++ b/todo.txt @@ -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 ____