diff --git a/n-gon/img/working mass.webp b/n-gon/img/working mass.webp new file mode 100644 index 00000000..d98237bc Binary files /dev/null and b/n-gon/img/working mass.webp differ diff --git a/n-gon/js/bullet.js b/n-gon/js/bullet.js index 65e48913..cceb11c1 100644 --- a/n-gon/js/bullet.js +++ b/n-gon/js/bullet.js @@ -3312,8 +3312,8 @@ const b = { const distB = Vector.magnitude(Vector.sub(this.position, b.position)) return distA < distB ? a : b }) - if (found && m.energy > 0.05) { - m.energy -= 0.05 + if (found && m.energy > 0.041) { + m.energy -= 0.04 //remove the body and spawn a new drone Composite.remove(engine.world, found) body.splice(body.indexOf(found), 1) @@ -3552,8 +3552,8 @@ const b = { const distB = Vector.magnitude(Vector.sub(this.position, b.position)) return distA < distB ? a : b }) - if (found && m.energy > 0.05) { - m.energy -= 0.1 + if (found && m.energy > 0.091) { + m.energy -= 0.09 //remove the body and spawn a new drone Composite.remove(engine.world, found) body.splice(body.indexOf(found), 1) diff --git a/n-gon/js/engine.js b/n-gon/js/engine.js index f7c6865d..fb7c481c 100644 --- a/n-gon/js/engine.js +++ b/n-gon/js/engine.js @@ -174,15 +174,8 @@ function collisionChecks(event) { if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles //extra kick between player and mob //this section would be better with forces but they don't work... let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x); - Matter.Body.setVelocity(player, { - x: player.velocity.x + 8 * Math.cos(angle), - y: player.velocity.y + 8 * Math.sin(angle) - }); - Matter.Body.setVelocity(mob[k], { - x: mob[k].velocity.x - 8 * Math.cos(angle), - y: mob[k].velocity.y - 8 * Math.sin(angle) - }); - + Matter.Body.setVelocity(player, { x: player.velocity.x + 8 * Math.cos(angle), y: player.velocity.y + 8 * Math.sin(angle) }); + Matter.Body.setVelocity(mob[k], { x: mob[k].velocity.x - 8 * Math.cos(angle), y: mob[k].velocity.y - 8 * Math.sin(angle) }); if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.1 && mob[k].damageReduction > 0) { m.energy -= 0.1 //* Math.max(m.maxEnergy, m.energy) //0.33 * m.energy if (m.immuneCycle === m.cycle + m.collisionImmuneCycles) m.immuneCycle = 0; //player doesn't go immune to collision damage @@ -250,7 +243,7 @@ function collisionChecks(event) { if (mob[k].isShielded) dmg *= 0.7 mob[k].damage(dmg, true); - if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && m.throwCycle > m.cycle) { + if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && Math.random() < 0.5) { options = ["coupling", "boost", "heal", "research"] if (!tech.isEnergyNoAmmo) options.push("ammo") powerUps.spawn(mob[k].position.x, mob[k].position.y, options[Math.floor(Math.random() * options.length)]); diff --git a/n-gon/js/level.js b/n-gon/js/level.js index fa739a57..51e091b1 100644 --- a/n-gon/js/level.js +++ b/n-gon/js/level.js @@ -44,10 +44,9 @@ const level = { // requestAnimationFrame(() => { tech.giveTech("optical amplifier") }); // for (let i = 0; i < 1; ++i) tech.giveTech("combinatorial optimization") // tech.giveTech("Newtons 2nd law") - // for (let i = 0; i < 1; ++i) tech.giveTech("lens") // for (let i = 0; i < 1; ++i) tech.giveTech("tungsten carbide") - // for (let i = 0; i < 1; ++i) tech.giveTech("nitinol") - // for (let i = 0; i < 1; ++i) tech.giveTech("reaction mass") + // for (let i = 0; i < 1; ++i) tech.giveTech("working mass") + // for (let i = 0; i < 1; ++i) tech.giveTech("buckling") // requestAnimationFrame(() => { for (let i = 0; i < 10; i++) b.orbitBot(m.pos, false) }); // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("ersatz bots") }); // for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide") @@ -57,11 +56,11 @@ const level = { // for (let i = 0; i < 1; i++) powerUps.directSpawn(-50, -70, "difficulty", false); // for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling"); // spawn.mapRect(575, -700, 25, 425); //block mob line of site on testing - // level.yingYang(); + // level.testing(); - // for (let i = 0; i < 1; ++i) spawn.laserLayer(1400, -500) + // for (let i = 0; i < 1; ++i) spawn.snakeSpitBoss(1400, -500) // Matter.Body.setPosition(player, { x: -200, y: -3330 }); - // for (let i = 0; i < 4; ++i) spawn.ghoster(1300, -500 + 100 * Math.random()) + // for (let i = 0; i < 4; ++i) spawn.sucker(1300, -500 + 100 * Math.random()) // spawn.hopper(1900, -500) // spawn.zombie(-3000, -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color) // for (let i = 0; i < 5; ++i) spawn.starter(1000 + 1000 * Math.random(), -500 + 300 * Math.random()) @@ -4235,7 +4234,6 @@ const level = { powerUps.addResearchToLevel() //needs to run after mobs are spawned }, towers() { - // simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // simulation.isHorizontalFlipped = true level.announceMobTypes() const isFlipped = (simulation.isHorizontalFlipped && Math.random() < 0.33) ? true : false @@ -4448,6 +4446,12 @@ const level = { spawn.bodyRect(8975, -1575, 50, 50, 0.2); spawn.bodyRect(5725, -1700, 125, 175, 0.2); spawn.bodyRect(6850, -1725, 150, 200, 0.2); + spawn.bodyRect(500, -400, 100, 50, 0.3); + spawn.bodyRect(6025, 1050, 100, 50, 0.2); + spawn.bodyRect(6000, -800, 75, 200, 0.2); + spawn.bodyRect(6775, -75, 125, 75, 0.5); + spawn.bodyRect(7200, 1300, 50, 200, 0.5); + //mobs spawn.randomMob(5700, -75, 0); diff --git a/n-gon/js/player.js b/n-gon/js/player.js index 5cfaed38..6e83d3a7 100644 --- a/n-gon/js/player.js +++ b/n-gon/js/player.js @@ -240,11 +240,7 @@ const m = { jump() { m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass //apply a fraction of the jump force to the body the player is jumping off of - Matter.Body.applyForce(m.standingOn, m.pos, { - x: 0, - y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) - }); - + Matter.Body.applyForce(m.standingOn, m.pos, { x: 0, y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) }); player.force.y = -m.jumpForce; //player jump force Matter.Body.setVelocity(player, { //zero player y-velocity for consistent jumps x: player.velocity.x, @@ -473,13 +469,10 @@ const m = { m.displayHealth(); document.getElementById("text-log").style.display = "none" document.getElementById("fade-out").style.opacity = 0.9; //slowly fade to 90% white on top of canvas - // build.shareURL(false) setTimeout(function () { Composite.clear(engine.world); Engine.clear(engine); simulation.splashReturn(); - //if you die after clearing fewer than 4 levels the difficulty settings automatically opens - if ((level.levelsCleared < 4 || level.levelsCleared > 12) && !simulation.isTraining && !simulation.isCheating) document.getElementById("constraint-details").open = true; }, 5000); } }, @@ -3488,11 +3481,11 @@ const m = { }, { name: "molecular assembler", - description: `excess energy used to print ${simulation.molecularMode === 0 ? "spores" : simulation.molecularMode === 1 ? "missiles" : simulation.molecularMode === 2 ? "ice IX" : "drones"}
use energy to deflect mobs
12 energy per second`, + description: `excess energy used to print ${simulation.molecularMode === 0 ? "spores" : simulation.molecularMode === 1 ? "missiles" : simulation.molecularMode === 2 ? "ice IX" : "drones"}
use energy to deflect mobs
12 energy per second`, setDescription() { - return `excess energy used to print ${simulation.molecularMode === 0 ? "spores" : simulation.molecularMode === 1 ? "missiles" : simulation.molecularMode === 2 ? "ice IX" : "drones"}
use energy to deflect mobs
12 energy per second` + return `excess energy used to print ${simulation.molecularMode === 0 ? "spores" : simulation.molecularMode === 1 ? "missiles" : simulation.molecularMode === 2 ? "ice IX" : "drones"}
use energy to deflect mobs
12 energy per second` }, - doubleJumpPhase: 0, + blockJumpPhase: 0, effect: () => { m.fieldMeterColor = "#ff0" m.eyeFillColor = m.fieldMeterColor @@ -3604,20 +3597,106 @@ const m = { } m.drawRegenEnergy() - if (tech.isDoubleJump) { - - - // if (input.up && m.buttonCD_jump + 20 < m.cycle && m.yOffWhen.stand > 23 && m.lastOnGroundCycle + 5 > m.cycle) m.jump() - - if (this.doubleJumpPhase === 0 && input.up) { //1st jump - - } else if (this.doubleJumpPhase === 0 && input.up) { + if (tech.isBlockJump) { + if (m.onGround && m.buttonCD_jump + 10 < m.cycle) this.blockJumpPhase = 0 //reset after touching ground or block + if (this.blockJumpPhase === 0 && !m.onGround) { //1st jump or fall + this.blockJumpPhase = 1 + } else if (this.blockJumpPhase === 1 && !input.up && m.buttonCD_jump + 10 < m.cycle) { //not pressing jump + this.blockJumpPhase = 2 + } else if (this.blockJumpPhase === 2 && input.up && m.buttonCD_jump + 10 < m.cycle) { //2nd jump + this.blockJumpPhase = 3 + + //make a block + const radius = 25 + Math.floor(15 * Math.random()) + body[body.length] = Matter.Bodies.polygon(m.pos.x, m.pos.y + 65 + radius, 4, radius, { + friction: 0.05, + frictionAir: 0.001, + collisionFilter: { + category: cat.body, + mask: cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + }, + classType: "body", + }); + const block = body[body.length - 1] + //mess with the block shape (this code is horrible) + Composite.add(engine.world, block); //add to world + const r1 = radius * (1 + 0.4 * Math.random()) + const r2 = radius * (1 + 0.4 * Math.random()) + let angle = 0 + const vertices = [] + for (let i = 0, len = block.vertices.length; i < len; i++) { + angle += 2 * Math.PI / len + vertices.push({ x: block.position.x + r1 * Math.cos(angle), y: block.position.y + r2 * Math.sin(angle) }) + } + Matter.Body.setVertices(block, vertices) + Matter.Body.setAngle(block, Math.PI / 4) + Matter.Body.setVelocity(block, { x: 0.9 * player.velocity.x, y: 10 }); + Matter.Body.applyForce(block, m.pos, { x: 0, y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) }); + if (tech.isBlockRestitution) { + block.restitution = 0.999 //extra bouncy + block.friction = block.frictionStatic = block.frictionAir = 0.001 + } + if (tech.isAddBlockMass) { + const expand = function (that, massLimit) { + if (that.mass < massLimit) { + const scale = 1.04; + Matter.Body.scale(that, scale, scale); + setTimeout(expand, 20, that, massLimit); + } + }; + expand(block, Math.min(20, block.mass * 3)) + } + //jump + m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass + let horizontalVelocity = 8 * (- input.left + input.right) + Matter.Body.setVelocity(player, { x: player.velocity.x + horizontalVelocity, y: -7.5 + 0.25 * player.velocity.y }); + player.force.y = -m.jumpForce; //player jump force + } else if (this.blockJumpPhase === 3 && m.onGround && m.buttonCD_jump + 10 < m.cycle) { + //reset + this.blockJumpPhase = 0 //reset + } + } - } else { //reset - } + // if (tech.isBlockJump) { + // //make sure only 1 ephemera is running + // simulation.ephemera.push({ + // name: "2 jump", + // mode: 0, + // do() { + // // console.log('hi') + // if (m.buttonCD_jump + 20 < m.cycle && m.onGround) simulation.removeEphemera(this.name) + // if (this.mode === 0) { + // if (!input.up) this.mode = 1 + // } else if (this.mode === 1) { + // if (input.up && m.buttonCD_jump + 20 < m.cycle) { + // simulation.removeEphemera(this.name) + // //make a block + // body[body.length] = Matter.Bodies.polygon(m.pos.x, m.pos.y + 80, 4, 30 + Math.floor(10 * Math.random()), { + // friction: 0.05, + // frictionAir: 0.001, + // collisionFilter: { + // category: cat.body, + // mask: cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + // }, + // classType: "body", + // // isPrinted: true, + // }); + // const who = body[body.length - 1] + // Composite.add(engine.world, who); //add to world + // Matter.Body.setVelocity(who, { x: player.velocity.x * 0.5, y: +30 }); + // Matter.Body.applyForce(who, m.pos, { x: 0, y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) }); + + // //jump again + // m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass + // player.force.y = -m.jumpForce; //player jump force + // Matter.Body.setVelocity(player, { x: player.velocity.x, y: -7.5 + 0.25 * player.velocity.y }); + // } + // } + // }, + // }) - } + // } } } }, @@ -4663,6 +4742,66 @@ const m = { m.fieldRadius = 0 } m.drawRegenEnergy("rgba(0,0,0,0.2)") + + if (tech.isBlockJump) { + if (m.onGround && m.buttonCD_jump + 10 < m.cycle) this.blockJumpPhase = 0 //reset after touching ground or block + if (this.blockJumpPhase === 0 && !m.onGround) { //1st jump or fall + this.blockJumpPhase = 1 + } else if (this.blockJumpPhase === 1 && !input.up && m.buttonCD_jump + 10 < m.cycle) { //not pressing jump + this.blockJumpPhase = 2 + } else if (this.blockJumpPhase === 2 && input.up && m.buttonCD_jump + 10 < m.cycle) { //2nd jump + this.blockJumpPhase = 3 + + //make a block + const radius = 25 + Math.floor(15 * Math.random()) + body[body.length] = Matter.Bodies.polygon(m.pos.x, m.pos.y + 60 + radius, 4, radius, { + friction: 0.05, + frictionAir: 0.001, + collisionFilter: { + category: cat.body, + mask: cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + }, + classType: "body", + }); + const block = body[body.length - 1] + //mess with the block shape (this code is horrible) + Composite.add(engine.world, block); //add to world + const r1 = radius * (1 + 0.4 * Math.random()) + const r2 = radius * (1 + 0.4 * Math.random()) + let angle = 0 + const vertices = [] + for (let i = 0, len = block.vertices.length; i < len; i++) { + angle += 2 * Math.PI / len + vertices.push({ x: block.position.x + r1 * Math.cos(angle), y: block.position.y + r2 * Math.sin(angle) }) + } + Matter.Body.setVertices(block, vertices) + Matter.Body.setAngle(block, Math.PI / 4) + Matter.Body.setVelocity(block, { x: 0.9 * player.velocity.x, y: 10 }); + Matter.Body.applyForce(block, m.pos, { x: 0, y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) }); + if (tech.isBlockRestitution) { + block.restitution = 0.999 //extra bouncy + block.friction = block.frictionStatic = block.frictionAir = 0.001 + } + if (tech.isAddBlockMass) { + const expand = function (that, massLimit) { + if (that.mass < massLimit) { + const scale = 1.04; + Matter.Body.scale(that, scale, scale); + setTimeout(expand, 20, that, massLimit); + } + }; + expand(block, Math.min(20, block.mass * 3)) + } + //jump + m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass + let horizontalVelocity = 8 * (- input.left + input.right) + Matter.Body.setVelocity(player, { x: player.velocity.x + horizontalVelocity, y: -7.5 + 0.25 * player.velocity.y }); + player.force.y = -m.jumpForce; //player jump force + } else if (this.blockJumpPhase === 3 && m.onGround && m.buttonCD_jump + 10 < m.cycle) { + //reset + this.blockJumpPhase = 0 //reset + } + } } } }, @@ -5619,7 +5758,7 @@ const m = { let dmg = tech.blockDamage * m.dmgScale * v * obj.mass * (tech.isMobBlockFling ? 2 : 1); if (mob[k].isShielded) dmg *= 0.7 mob[k].damage(dmg, true); - if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && m.throwCycle > m.cycle) { + if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && Math.random() < 0.5) { let type = tech.isEnergyNoAmmo ? "heal" : "ammo" if (Math.random() < 0.4) { type = "heal" diff --git a/n-gon/js/powerup.js b/n-gon/js/powerup.js index a6414da8..d96f70e6 100644 --- a/n-gon/js/powerup.js +++ b/n-gon/js/powerup.js @@ -1437,11 +1437,10 @@ const powerUps = { }, }, spawnDelay(type, count, delay = 2) { - const lastHarmCycle = m.lastHarmCycle //stop releasing power ups if you take damage count *= delay let cycle = () => { if (count > 0) { - if (m.alive && lastHarmCycle === m.lastHarmCycle) requestAnimationFrame(cycle); + if (m.alive) requestAnimationFrame(cycle); if (!simulation.paused && !simulation.isChoosing && powerUp.length < 300) { //&& !(simulation.cycle % 2) count-- if (!(count % delay)) { @@ -1622,7 +1621,7 @@ const powerUps = { for (let i = 0; i < tech.tech[choose].count; i++) { powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); - powerUp[powerUp.length - 1].isDuplicated = true + // powerUp[powerUp.length - 1].isDuplicated = true } // remove a random tech from the list of tech you have tech.tech[choose].remove(); diff --git a/n-gon/js/simulation.js b/n-gon/js/simulation.js index 61aeffc1..0ae161f0 100644 --- a/n-gon/js/simulation.js +++ b/n-gon/js/simulation.js @@ -814,7 +814,6 @@ const simulation = { simulation.isChoosing = false; b.setFireMethod() b.setFireCD(); - // simulation.updateTechHUD(); for (let i = 0; i < b.guns.length; i++) b.guns[i].isRecentlyShown = false //reset recently shown back to zero for (let i = 0; i < m.fieldUpgrades.length; i++) m.fieldUpgrades[i].isRecentlyShown = false //reset recently shown back to zero for (let i = 0; i < tech.tech.length; i++) tech.tech[i].isRecentlyShown = false //reset recently shown back to zero @@ -827,17 +826,12 @@ const simulation = { powerUps.boost.endCycle = 0 powerUps.isFieldSpawned = false m.setFillColors(); - // m.maxHealth = 1 - // m.maxEnergy = 1 - // m.energy = 1 input.isPauseKeyReady = true simulation.wipe = function () { //set wipe to normal ctx.clearRect(0, 0, canvas.width, canvas.height); } m.hole.isOn = false simulation.paused = false; - // simulation.cycle = 0 - // m.cycle = 0 engine.timing.timeScale = 1; simulation.fpsCap = simulation.fpsCapDefault; simulation.isAutoZoom = true; @@ -853,18 +847,11 @@ const simulation = { document.getElementById("text-log").style.display = "none" document.getElementById("fade-out").style.opacity = 0; document.title = "n-gon"; - // simulation.makeTextLog(`input.key.up: ["${input.key.up}", "ArrowUp"]`); - // simulation.makeTextLog(`input.key.left: ["${input.key.left}", "ArrowLeft"]`); - // simulation.makeTextLog(`input.key.down: ["${input.key.down}", "ArrowDown"]`); - // simulation.makeTextLog(`input.key.right: ["${input.key.right}", "ArrowRight"]`); simulation.makeTextLog(`Math.seed = ${Math.initialSeed}`); simulation.makeTextLog(`const engine = Engine.create(); //simulation begin`); simulation.makeTextLog(`engine.timing.timeScale = 1`); - // simulation.makeTextLog(`input.key.field: ["${input.key.field}", "MouseRight"]`); - - // document.getElementById("health").style.display = "inline" - // document.getElementById("health-bg").style.display = "inline" m.alive = true; + m.definePlayerMass(); m.onGround = false m.lastOnGroundCycle = 0 m.health = 0; @@ -874,23 +861,10 @@ const simulation = { //set to default field tech.healMaxEnergyBonus = 0 - // m.setMaxEnergy(); m.energy = 0 m.immuneCycle = 0; - // simulation.makeTextLog(`${simulation.SVGrightMouse} ${m.fieldUpgrades[m.fieldMode].name}

${m.fieldUpgrades[m.fieldMode].description}`, 600); - // simulation.makeTextLog(` - // input.key.up = ["${input.key.up}", "ArrowUp"] - //
input.key.left = ["${input.key.left}", "ArrowLeft"] - //
input.key.down = ["${input.key.down}", "ArrowDown"] - //
input.key.right = ["${input.key.right}", "ArrowRight"] - //
- //
m.fieldMode = "${m.fieldUpgrades[m.fieldMode].name}" - //
input.key.field = ["${input.key.field}", "right mouse"] - //
m.field.description = "${m.fieldUpgrades[m.fieldMode].description}" - // `, 800); m.coupling = 0 m.setField(0) //this calls m.couplingChange(), which sets max health and max energy - // m.energy = 0; //exit testing if (simulation.testing) { simulation.testing = false; diff --git a/n-gon/js/spawn.js b/n-gon/js/spawn.js index 1e3c9acc..5759357f 100644 --- a/n-gon/js/spawn.js +++ b/n-gon/js/spawn.js @@ -1427,7 +1427,7 @@ const spawn = { me.seePlayerFreq = Math.floor(11 + 7 * Math.random()) me.seeAtDistance2 = 1400000; me.cellMassMax = 70 - me.collisionFilter.mask = cat.player | cat.bullet //| cat.body | cat.map + me.collisionFilter.mask = cat.player | cat.bullet | cat.body// | cat.map Matter.Body.setDensity(me, 0.0001 + 0.00002 * simulation.difficulty) // normal density is 0.001 me.damageReduction = 0.17 @@ -1755,7 +1755,7 @@ const spawn = { me.seeAtDistance2 = 1000000; me.accelMag = 0.0002 + 0.0004 * simulation.accelScale; Matter.Body.setDensity(me, 0.0003); //normal is 0.001 - me.collisionFilter.mask = cat.bullet | cat.player //| cat.body + me.collisionFilter.mask = cat.bullet | cat.player | cat.body me.memory = Infinity; me.seePlayerFreq = 30 me.lockedOn = null; @@ -2314,7 +2314,7 @@ const spawn = { me.seeAtDistance2 = (me.eventHorizon + 400) * (me.eventHorizon + 400); //vision limit is event horizon me.accelMag = 0.00012 * simulation.accelScale; me.frictionAir = 0.025; - me.collisionFilter.mask = cat.player | cat.bullet //| cat.body + me.collisionFilter.mask = cat.player | cat.bullet | cat.body me.memory = Infinity; Matter.Body.setDensity(me, 0.015); //extra dense //normal is 0.001 //makes effective life much larger me.do = function () { @@ -4263,7 +4263,7 @@ const spawn = { powerUps.spawnBossPowerUp(this.position.x, this.position.y) }; Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger - me.damageReduction = 0.25 + me.damageReduction = 0.33 me.startingDamageReduction = me.damageReduction me.isInvulnerable = false me.nextHealthThreshold = 0.75 @@ -4279,7 +4279,7 @@ const spawn = { } }; me.lasers = [] //keeps track of static laser beams - me.laserLimit = 2 + (simulation.difficultyMode < 3 ? 1 : 2) + me.laserLimit = 2 + (simulation.difficultyMode > 2) + (simulation.difficultyMode > 4) me.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5) me.cycle = 0 me.laserDelay = 210 @@ -5910,7 +5910,7 @@ const spawn = { me.alpha = 1; //used in drawGhost me.isNotCloaked = false; //used in drawGhost me.isBadTarget = true; - me.collisionFilter.mask = cat.bullet //| cat.body + me.collisionFilter.mask = cat.bullet | cat.body me.showHealthBar = false; me.memory = 900; me.delay = 60 @@ -5961,7 +5961,7 @@ const spawn = { if (!this.isNotCloaked) { this.isNotCloaked = true; this.isBadTarget = false; - this.collisionFilter.mask = cat.player | cat.bullet + this.collisionFilter.mask = cat.player | cat.bullet | cat.body } } //draw body @@ -5976,7 +5976,7 @@ const spawn = { } else if (this.isNotCloaked) { this.isNotCloaked = false; this.isBadTarget = true; - this.collisionFilter.mask = cat.bullet; //can't touch player or walls + this.collisionFilter.mask = cat.bullet | cat.body; //can't touch player or walls } }; }, @@ -7392,7 +7392,7 @@ const spawn = { snakeBody(x, y, radius = 10) { mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)"); let me = mob[mob.length - 1]; - me.collisionFilter.mask = cat.bullet | cat.player //| cat.mob //| cat.body + me.collisionFilter.mask = cat.bullet | cat.player | cat.body //| cat.mob me.damageReduction = 0.028 Matter.Body.setDensity(me, 0.0001); //normal is 0.001 diff --git a/n-gon/js/tech.js b/n-gon/js/tech.js index e956a7b6..e5014ea1 100644 --- a/n-gon/js/tech.js +++ b/n-gon/js/tech.js @@ -108,20 +108,8 @@ const tech = { if (tech.junkChance < 0.001 || tech.junkChance === undefined) tech.junkChance = 0 } }, - giveRandomJUNK() { - const list = [] - for (let i = 0; i < tech.tech.length; i++) { - if (tech.tech[i].isJunk) list.push(tech.tech[i].name) - } - let name = list[Math.floor(Math.random() * list.length)] - simulation.makeTextLog(`tech.giveTech("${name}")`); - tech.giveTech(name) - }, + giveTech(index = 'random') { - // if (Math.random() < tech.junkChance) { - // tech.giveRandomJUNK(); - // return - // } if (index === 'random') { let options = []; for (let i = 0; i < tech.tech.length; i++) { @@ -2342,7 +2330,7 @@ const tech = { { name: "buckling", descriptionFunction() { - return `if a block you threw kills a mob
spawn either ${powerUps.orb.coupling(1)}, ${powerUps.orb.boost(1)}, ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}` + return `if a block kills a mob there's a 50% chance
to spawn either ${powerUps.orb.coupling(1)}, ${powerUps.orb.boost(1)}, ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}` }, maxCount: 1, count: 0, @@ -4291,7 +4279,7 @@ const tech = { remove() { if (this.count > 0 && m.alive) { tech.damage /= this.damage - powerUps.spawnDelay("research", 15) + requestAnimationFrame(() => { powerUps.spawnDelay("research", 15) }); this.frequency = 0 } } @@ -4349,16 +4337,16 @@ const tech = { remove() { if (this.count > 0 && m.alive) { tech.damage /= this.damage - powerUps.spawnDelay("ammo", this.ammo) this.frequency = 0 + requestAnimationFrame(() => { powerUps.spawnDelay("ammo", this.ammo) }); } } }, { name: "deprecated", - scale: 0.05, + scale: 0.07, descriptionFunction() { - return `after removing this gain
1.05x damage per removed tech(${(1 + this.scale * ((this.frequency === 0 ? 0 : 1) + tech.removeCount)).toFixed(2)}x)` + return `after removing this gain
${1 + this.scale}x damage per removed tech(${(1 + this.scale * ((this.frequency === 0 ? 0 : 1) + tech.removeCount)).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -6453,7 +6441,7 @@ const tech = { }, { name: "von Neumann probe", //"drone repair", - description: "after a drone expires it will use -5 energy
and a nearby block to replicate itself", + description: "after a drone expires it will use -4 energy
and a nearby block to replicate itself", // description: "broken drones repair if the drone gun is active
repairing has a 25% chance to use 1 drone", isGunTech: true, maxCount: 1, @@ -6461,7 +6449,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("drones") + return tech.haveGunCheck("drones") || (m.fieldMode === 4 && simulation.molecularMode === 3) }, requires: "drones", effect() { @@ -7862,8 +7850,7 @@ const tech = { // }, { name: "additive manufacturing", - description: "hold crouch and use your field to print a block
with 1.8x density, damage, and launch speed", - // description: "simultaneously fire and activate your field to make
molecular assembler print a throwable block
+80% block throwing speed", + description: "hold crouch and use your field to print a block
with 1.8x density, damage, and launch speed", isFieldTech: true, maxCount: 1, count: 0, @@ -7881,6 +7868,29 @@ const tech = { tech.isPrinter = false; } }, + { + name: "working mass", + // description: "molecular assembler prints one block
to jump off while midair", + descriptionFunction() { + const fieldName = m.fieldMode === 8 ? "pilot wave" : "molecular assembler" + return `${fieldName} prints a block
to jump off while midair a second time` + }, + isFieldTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return (m.fieldMode === 4 || m.fieldMode === 8) + }, + requires: "molecular assembler, pilot wave", + effect() { + tech.isBlockJump = true + }, + remove() { + tech.isBlockJump = false + } + }, { name: "pair production", description: "after picking up a power up
+200 energy", @@ -7901,26 +7911,6 @@ const tech = { tech.isMassEnergy = false; } }, - // { - // name: "working mass", - // // description: "after jumping jump again in midair
double jumping requires 50% of current energy
double jumping boosts speed", - // description: "", - // isFieldTech: true, - // maxCount: 1, - // count: 0, - // frequency: 2, - // frequencyDefault: 2, - // allowed() { - // return m.fieldMode === 4 - // }, - // requires: "molecular assembler", - // effect() { - // tech.isDoubleJump = true - // }, - // remove() { - // tech.isDoubleJump = false - // } - // }, { name: "electric generator", description: "after deflecting mobs
molecular assembler generates +50 energy", @@ -8195,7 +8185,7 @@ const tech = { }, { name: "Lorentz transformation", - description: `use ${powerUps.orb.research(3)}
1.5x movement, jumping, and fire rate`, + description: `use ${powerUps.orb.research(3)}
1.5x movement, jumping, and fire rate`, isFieldTech: true, maxCount: 1, count: 0, @@ -9271,9 +9261,15 @@ const tech = { allowed: () => true, requires: "", effect() { - tech.giveRandomJUNK() - tech.giveRandomJUNK() - tech.giveRandomJUNK() + for (let i = 0; i < 3; i++) { + const list = [] + for (let i = 0; i < tech.tech.length; i++) { + if (tech.tech[i].isJunk) list.push(tech.tech[i].name) + } + let name = list[Math.floor(Math.random() * list.length)] + simulation.makeTextLog(`tech.giveTech("${name}")`); + tech.giveTech(name) + } }, remove() { } }, @@ -11848,5 +11844,5 @@ const tech = { interestRate: null, isImmunityDamage: null, isMobDeathImmunity: null, - isDoubleJump: null, + isBlockJump: null, } \ No newline at end of file diff --git a/n-gon/style.css b/n-gon/style.css index 1146a258..7855b461 100644 --- a/n-gon/style.css +++ b/n-gon/style.css @@ -935,6 +935,11 @@ summary { text-shadow: 1px 0px 2px #234; } +.color-print { + color: #567; + font-family: 'Courier New', Courier, monospace; +} + .color-defense { background-color: hsla(227, 9%, 71%, 0.279); padding: 2px; diff --git a/n-gon/todo.txt b/n-gon/todo.txt index f4bd3569..74d161df 100644 --- a/n-gon/todo.txt +++ b/n-gon/todo.txt @@ -1,19 +1,17 @@ ******************************************************** NEXT PATCH ************************************************** -you can now jump off mobs while invulnerable - includes time dilated -pause display text updated with details menus -difficulty parameters - 0.82->0.84x damage done per level - 1.25->1.23x damage taken per level -tungsten carbide 300->400 health, but 0.08->0.02 seconds of coyote time and longer crouch time -nitinol 0.08->0.17 seconds of coyote time and much less crouching on hard landings, but 0.8->1 damage taken -mass-energy equivalence no longer costs 2 research -long power up spawns, like from interest or supply chain: - will pause new spawns until total power ups are below 300 to reduce lag - stop spawning if you take damage - -bug fixes +tech: working mass - in midair molecular assembler or pilot wave prints a block to jump off + +buckling: 100%->50% chance to spawn a power up from any block that kills a mob + no longer requires the block to be thrown +mobs: powerUpBoss, snakeBoss tails, cellBoss, ghoster, sucker - all collide with blocks now +added a few more blocks to towers level +deprecated: 1.05->1.07 damage per removed tech +laserLayerBoss has 33% less health and has fewer lasers at higher difficulties + +bugfix + disabled spawnDelay stopping on damage because it had too many negative tech interactions + metastability + paradigm shift no longer makes all ejected tech explode ******************************************************* DESIGN ****************************************************** @@ -36,22 +34,33 @@ list of powerful synergies duplication 100% interest + coupling, research + (peer review? or Bayesian statistics) electronegativity and high energy? - electronegativity + anyon + duplication + Maxwells demon + interest + electronegativity + anyon + duplication + Maxwells demon + interest + pair production chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level *********************************************************** TODO ***************************************************** -tech: working mass - double jump - cost flat energy not a % - field Tech for molecular assembler and print and throw a block down on 2nd jump - remove block after time or keep it around? - credit to TNTiger17 (although I'm not looking for more code contributions) +make player mass an adjustable var in the skin + does this mess with jump height or air control? +increase mass and movement speed at the same time + increase jump differently because it scales extra with mass + m.defaultMass = 4.5 + m.definePlayerMass() + possible player.mass bad interactions + grapple + +JUNK tech - player takes damage from block collisions + is this gonna contribute to lag? + +player damage seems low +player damage taken seems fine, or maybe increase difficulty rework: explicit changes to the game to increase difficulty UI - add a wire attached to difficulty power up like the one attached to player, but thinner +laser: slow light is the least fun laser tech, make it more fun + tokamak synergy tech tech: stellarator - after firing a block with tokamak, heal (scale heal amount with block mass?) tech: inertial confinement - while charging tokamak you can fly, and invulnerable @@ -823,11 +832,6 @@ intro map: diegeticly draw a mouse with field highlighted also indicate space? dynamically adjust drawing after picking up a gun -increase mass and movement speed at the same time - increase jump differently because it scales extra with mass - m.defaultMass = 4.5 - m.definePlayerMass() - give history boss legs? field tech - disable blocking, but does high damage to mobs inside field