diff --git a/.DS_Store b/.DS_Store index f7316f4..addbf77 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/js/bullet.js b/js/bullet.js index 5d78c0d..9969664 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -3876,7 +3876,7 @@ const b = { y: position.y, radius: 5, color: "rgba(0,0,0,0.1)", - time: 21 * tech.foamFutureFire + time: 18 * tech.foamFutureFire }); setTimeout(() => { @@ -3884,7 +3884,7 @@ const b = { b.foam(position, velocity, radius) bullet[bullet.length - 1].damage = (1 + 1.53 * tech.foamFutureFire) * (tech.isFastFoam ? 0.048 : 0.012) //double damage } - }, 350 * tech.foamFutureFire); + }, 300 * tech.foamFutureFire); } else { m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 15 : 5) * b.fireCD); // cool down @@ -3993,7 +3993,8 @@ const b = { //draw magnetic field const X = m.pos.x const Y = m.pos.y - const unitVector = Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)) + // const unitVector = Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)) + const unitVector = { x: Math.cos(m.angle), y: Math.sin(m.angle) } const unitVectorPerp = Vector.perp(unitVector) function magField(mag, arc) { @@ -4218,7 +4219,8 @@ const b = { //draw magnetic field const X = m.pos.x const Y = m.pos.y - const unitVector = Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)) + const unitVector = { x: Math.cos(m.angle), y: Math.sin(m.angle) } + //Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)) const unitVectorPerp = Vector.perp(unitVector) function magField(mag, arc) { diff --git a/js/engine.js b/js/engine.js index f74a265..9be8869 100644 --- a/js/engine.js +++ b/js/engine.js @@ -99,6 +99,7 @@ function collisionChecks(event) { if ( m.immuneCycle < m.cycle && (obj === playerBody || obj === playerHead) && + // (obj === player) && !(tech.isFreezeHarmImmune && (mob[k].isSlowed || mob[k].isStunned)) ) { mob[k].foundPlayer(); diff --git a/js/index.js b/js/index.js index d009870..a40ce79 100644 --- a/js/index.js +++ b/js/index.js @@ -318,6 +318,9 @@ const build = {
        ${tech.tech[i].name} ${isCount}${tech.tech[i].description}` + } else if (tech.tech[i].isJunk) { + // text += `
  ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
` + techID.innerHTML = `
  ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}` } else { techID.innerHTML = `
  ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}` } @@ -741,11 +744,6 @@ window.addEventListener("keydown", function(event) { if (simulation.testing) { - - - - - } } } @@ -785,6 +783,10 @@ window.addEventListener("keydown", function(event) { H + infinite health + + + N fill health, energy @@ -795,6 +797,10 @@ window.addEventListener("keydown", function(event) { U next level + + J + clear mobs + I/O zoom in / out @@ -866,8 +872,14 @@ window.addEventListener("keydown", function(event) { b.giveGuns("all", 1000) break case "h": + m.health = Infinity + // m.energy = Infinity + document.getElementById("health").style.display = "none" + document.getElementById("health-bg").style.display = "none" + break + case "n": m.addHealth(Infinity) - m.energy = m.maxEnergy; + m.energy = m.maxEnergy break case "y": tech.giveTech() @@ -896,6 +908,11 @@ window.addEventListener("keydown", function(event) { case "u": level.nextLevel(); break + case "j": + for (let i = 0, len = mob.length; i < len; ++i) mob[i].damage(Infinity, true) + setTimeout(() => { for (let i = 0, len = mob.length; i < len; ++i) mob[i].damage(Infinity, true) }, 100); + setTimeout(() => { for (let i = 0, len = mob.length; i < len; ++i) mob[i].damage(Infinity, true) }, 200); + break } } }); diff --git a/js/level.js b/js/level.js index c27da10..f938918 100644 --- a/js/level.js +++ b/js/level.js @@ -32,6 +32,7 @@ const level = { // tech.giveTech("nail-bot") // for (let i = 0; i < 15; i++) tech.giveTech("plasma jet") // tech.isBlockPowerUps = true; + // m.shipMode() level.intro(); //starting level // level.testing(); //not in rotation @@ -57,8 +58,8 @@ const level = { // tech.giveTech("undefined") // lore.techCount = 10 // localSettings.loreCount = 1; - // simulation.isCheating = true; - // localSettings.loreCount = undefined; + // simulation.isCheating = false //true; + // localSettings.loreCount = 1; // localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage // level.null() } else { @@ -1085,7 +1086,7 @@ const level = { // spawn.striker(1600, -500) // spawn.shooter(1700, -120) // spawn.bomberBoss(1400, -500) - spawn.sniper(1800, -120) + // spawn.sniper(1800, -120) // spawn.streamBoss(1600, -500) // spawn.cellBossCulture(1600, -500) // spawn.cellBossCulture(1600, -500) @@ -1419,11 +1420,13 @@ const level = { powerUps.spawn(2050, -150, "heal", false); //starting gun // powerUps.spawn(2050, -150, "field", false); //starting gun if (localSettings.levelsClearedLastGame < 6) { - spawn.wireFoot(); - spawn.wireFootLeft(); - spawn.wireKnee(); - spawn.wireKneeLeft(); - spawn.wireHead(); + if (!simulation.isCheating) { + spawn.wireFoot(); + spawn.wireFootLeft(); + spawn.wireKnee(); + spawn.wireKneeLeft(); + spawn.wireHead(); + } } else { // const say = [] // if (localSettings.runCount > 200) { //experienced @@ -2590,7 +2593,7 @@ const level = { color: "rgba(0,0,0,0.2)" }); level.fill.push({ - x: 3600, + x: 3800, y: -110, width: 400, height: 110, @@ -2614,7 +2617,7 @@ const level = { }); level.fillBG.push({ x: 3350, - y: -1325, + y: -1300, width: 50, height: 1325, color: "#d4d4d7" @@ -2627,7 +2630,7 @@ const level = { color: "#d4f4f4" }); - spawn.mapRect(-300, 0, 5000, 300); //***********ground + spawn.mapRect(-300, 0, 5100, 300); //***********ground spawn.mapRect(-300, -350, 50, 400); //far left starting left wall spawn.mapRect(-300, -10, 500, 50); //far left starting ground spawn.mapRect(-300, -350, 500, 50); //far left starting ceiling @@ -2638,7 +2641,7 @@ const level = { spawn.mapRect(1600, -400, 1500, 500); //long center building spawn.mapRect(1345, -1100, 250, 25); //left platform spawn.mapRect(1755, -1100, 250, 25); //right platform - spawn.mapRect(1300, -1850, 780, 50); //left higher platform + spawn.mapRect(1300, -1850, 800, 50); //left higher platform spawn.mapRect(1300, -2150, 50, 350); //left higher platform left edge wall spawn.mapRect(1300, -2150, 450, 50); //left higher platform roof spawn.mapRect(1500, -1860, 100, 50); //ground bump wall @@ -2647,10 +2650,10 @@ const level = { spawn.mapRect(2500, -1450, 450, 350); //higher center floating large square spawn.mapRect(2500, -1675, 50, 300); //left wall on higher center floating large square spawn.mapRect(2500, -1700, 300, 50); //roof on higher center floating large square - spawn.mapRect(3300, -850, 150, 25); //ledge by far right building - spawn.mapRect(3300, -1350, 150, 25); //higher ledge by far right building - spawn.mapRect(3600, -1100, 400, 990); //far right building - spawn.boost(4150, 0, 1300); + spawn.mapRect(3275, -750, 200, 25); //ledge by far right building + spawn.mapRect(3275, -1300, 200, 25); //higher ledge by far right building + spawn.mapRect(3800, -1100, 400, 990); //far right building + spawn.boost(4450, 0, 1300); spawn.bodyRect(3200, -1375, 300, 25, 0.9); spawn.bodyRect(1825, -1875, 400, 25, 0.9); diff --git a/js/lore.js b/js/lore.js index 7b3c52b..c553a4e 100644 --- a/js/lore.js +++ b/js/lore.js @@ -4,9 +4,11 @@ const lore = { anand: { color: "#e0c", text: function(say, isSpeech = false) { - simulation.makeTextLog(`input.audio(${Date.now()} ms): "${say}"`, Infinity); - lore.talkingColor = this.color - if (isSpeech) this.speech(say) + if (level.levels[level.onLevel] === undefined) { //only talk if on the lore level (which is undefined because it is popped out of the level.levels array) + simulation.makeTextLog(`input.audio(${Date.now()} ms): "${say}"`, Infinity); + lore.talkingColor = this.color + if (isSpeech) this.speech(say) + } }, speech: function(say) { var utterance = new SpeechSynthesisUtterance(say); @@ -18,9 +20,11 @@ const lore = { miriam: { color: "#f20", text: function(say, isSpeech = false) { - simulation.makeTextLog(`input.audio(${Date.now()} ms): "${say}"`, Infinity); - lore.talkingColor = this.color - if (isSpeech) this.speech(say) + if (level.levels[level.onLevel] === undefined) { //only talk if on the lore level (which is undefined because it is popped out of the level.levels array) + simulation.makeTextLog(`input.audio(${Date.now()} ms): "${say}"`, Infinity); + lore.talkingColor = this.color + if (isSpeech) this.speech(say) + } }, speech: function(say) { var utterance = new SpeechSynthesisUtterance(say); @@ -58,9 +62,14 @@ const lore = { delay += 3700 setTimeout(() => { lore.talkingColor = "#dff" }, delay); //set color of graphic on level.null when no one is talking delay += 25000 - setTimeout(() => { lore.miriam.text("Poor thing... I hope it figures out how to escape.", true) }, delay); - delay += 3500 - setTimeout(() => { lore.talkingColor = "#dff" }, delay); //set color of graphic on level.null when no one is talking + setTimeout(() => { + if (!simulation.isCheating) { + lore.miriam.text("Poor thing... I hope it figures out how to escape.", true) + delay += 3500 + setTimeout(() => { lore.talkingColor = "#dff" }, delay); //set color of graphic on level.null when no one is talking + } + }, delay); + }, () => { if (localSettings.loreCount < 2) { @@ -129,9 +138,9 @@ const lore = { }, delay); }, () => { - let delay = 6000 - setTimeout(() => { lore.miriam.text("I've never seen it generate this level before.", true) }, delay); - delay += 2700 + // let delay = 6000 + // setTimeout(() => { lore.miriam.text("I've never seen it generate this level before.", true) }, delay); + // delay += 2700 }, ], diff --git a/js/player.js b/js/player.js index 763e4ce..f953fac 100644 --- a/js/player.js +++ b/js/player.js @@ -57,8 +57,8 @@ const m = { lastHarmCycle: 0, width: 50, radius: 30, - fillColor: "#fff", - fillColorDark: "#ccc", + fillColor: null, //set by setFillColors + fillColorDark: null, //set by setFillColors color: { hue: 0, sat: 0, @@ -66,7 +66,7 @@ const m = { }, setFillColors() { this.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)` - this.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light-20}%)` + this.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light-25}%)` }, height: 42, yOffWhen: { @@ -236,20 +236,7 @@ const m = { x: player.position.x, y: player.position.y - 30.28592321 }) - // Matter.Body.translate(playerHead, { - // x: 0, - // y: -40 - // }); } - - // playerHead.collisionFilter = { - // group: 0, - // category: cat.player, - // mask: cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield - // } - // playerHead.isSensor = false; - // playerHead.collisionFilter.category = cat.player - // playerHead.collisionFilter.mask = cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield } }, hardLandCD: 0, @@ -803,12 +790,13 @@ const m = { ctx.save(); ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 ctx.translate(m.pos.x, m.pos.y); + m.calcLeg(Math.PI, -3); m.drawLeg("#4a4a4a"); m.calcLeg(0, 0); m.drawLeg("#333"); - ctx.rotate(m.angle); + ctx.rotate(m.angle); ctx.beginPath(); ctx.arc(0, 0, 30, 0, 2 * Math.PI); let grd = ctx.createLinearGradient(-30, 0, 30, 0); @@ -2586,4 +2574,304 @@ const m = { }, }, ], + isShipMode: false, + shipMode() { + if (!m.isShipMode) { + m.isShipMode = true + simulation.isCheating = true + const points = [ + { x: 29.979168754143455, y: 4.748337243898336 }, + { x: 27.04503734408824, y: 13.7801138209198 }, + { x: 21.462582474874278, y: 21.462582475257523 }, + { x: 13.780113820536943, y: 27.045037344471485 }, + { x: 4.74833724351507, y: 29.979168754526473 }, + { x: -4.748337245049098, y: 29.979168754526473 }, + { x: -13.780113822071026, y: 27.045037344471485 }, + { x: -21.46258247640829, y: 21.462582475257523 }, + { x: -27.045037345621797, y: 13.7801138209198 }, + { x: -29.979168755677012, y: 4.748337243898336 }, + { x: -29.979168755677012, y: -4.7483372446656045 }, + { x: -27.045037345621797, y: -13.78011382168726 }, + { x: -21.46258247640829, y: -21.462582476024817 }, + { x: -13.780113822071026, y: -27.045037345239006 }, + { x: -4.748337245049098, y: -29.97916875529422 }, + { x: 4.74833724351507, y: -29.97916875529422 }, + { x: 13.780113820536943, y: -27.045037345239006 }, + { x: 21.462582474874278, y: -21.462582476024817 }, + { x: 27.04503734408824, y: -13.78011382168726 }, + { x: 29.979168754143455, y: -4.7483372446656045 } + ] + // + Matter.Body.setVertices(player, Matter.Vertices.create(points, player)) + // console.log(circle) + player.parts.pop() + player.parts.pop() + player.parts.pop() + player.parts.pop() + // Matter.Body.setDensity(player, 0.01); //extra dense //normal is 0.001 //makes effective life much larger + m.defaultMass = 30 + Matter.Body.setMass(player, m.defaultMass); + player.friction = 0.07 + // player.frictionStatic = 0.1 + // Matter.Body.setInertia(player, Infinity); //disable rotation + + // const circle = Bodies.polygon(player.position.x, player.position.x, 30, 30) + // player.parts[0] = circle + // console.log(player.parts[0]) + // Matter.Body.setVertices(player.parts[0], Matter.Vertices.create(points, player.parts[0])) + // console.log(player.parts[0].vertices) + + level.playerExitCheck = () => { + if ( + player.position.x > level.exit.x && + player.position.x < level.exit.x + 100 && + player.position.y > level.exit.y - 150 && + player.position.y < level.exit.y - 40 && + player.speed < 4 + ) { + level.nextLevel() + } + } + m.move = () => { + m.pos.x = player.position.x; + m.pos.y = player.position.y; + m.Vx = player.velocity.x; + m.Vy = player.velocity.y; + + //tracks the last 10s of player information + // console.log(m.history) + m.history.splice(m.cycle % 600, 1, { + position: { + x: player.position.x, + y: player.position.y, + }, + velocity: { + x: player.velocity.x, + y: player.velocity.y + }, + yOff: m.yOff, + angle: m.angle, + health: m.health, + energy: m.energy, + activeGun: b.activeGun + }); + } + + m.look = () => { //disable mouse aiming + //always on mouse look + // m.angle = Math.atan2( + // simulation.mouseInGame.y - m.pos.y, + // simulation.mouseInGame.x - m.pos.x + // ); + //smoothed mouse look translations + const scale = 0.8; + m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale; + m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale; + + m.transX += (m.transSmoothX - m.transX) * 0.07; + m.transY += (m.transSmoothY - m.transY) * 0.07; + } + + simulation.camera = () => { + const dx = simulation.mouse.x / window.innerWidth - 0.5 //x distance from mouse to window center scaled by window width + const dy = simulation.mouse.y / window.innerHeight - 0.5 //y distance from mouse to window center scaled by window height + const d = Math.max(dx * dx, dy * dy) + simulation.edgeZoomOutSmooth = (1 + 4 * d * d) * 0.04 + simulation.edgeZoomOutSmooth * 0.96 + + + ctx.save(); + ctx.translate(canvas.width2, canvas.height2); //center + ctx.scale(simulation.zoom / simulation.edgeZoomOutSmooth, simulation.zoom / simulation.edgeZoomOutSmooth); //zoom in once centered + ctx.translate(-canvas.width2 + m.transX, -canvas.height2 + m.transY); //translate + //calculate in game mouse position by undoing the zoom and translations + simulation.mouseInGame.x = (simulation.mouse.x - canvas.width2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.width2 - m.transX; + simulation.mouseInGame.y = (simulation.mouse.y - canvas.height2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.height2 - m.transY; + } + + m.draw = () => { //just draw the circle + ctx.save(); + ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 + ctx.translate(player.position.x, player.position.y); + ctx.rotate(player.angle); + + ctx.beginPath(); + ctx.arc(0, 0, 30, 0, 2 * Math.PI); + let grd = ctx.createLinearGradient(-30, 0, 30, 0); + grd.addColorStop(0, m.fillColorDark); + grd.addColorStop(1, m.fillColor); + ctx.fillStyle = grd; + ctx.fill(); + ctx.arc(15, 0, 4, 0, 2 * Math.PI); + ctx.strokeStyle = "#333"; + ctx.lineWidth = 2; + ctx.stroke(); + ctx.restore(); + } + m.spin = 0 + // m.groundControl = () => {} //disable entering ground + m.onGround = false + playerOnGroundCheck = () => {} + m.airControl = () => { //tank controls + player.force.y -= player.mass * simulation.g; //undo gravity + const thrust = 0.03 * tech.squirrelJump //Math.max(0.1 / (0.01 + player.speed), 0.03) * tech.squirrelJump + // console.log(player.speed, thrust) + if (input.up) { //thrust + player.force.x += thrust * Math.cos(m.angle) + player.force.y += thrust * Math.sin(m.angle) + + const friction = 0.99 + Matter.Body.setVelocity(player, { + x: friction * player.velocity.x, + y: friction * player.velocity.y + }); + } else if (input.down) { + player.force.x -= 0.7 * thrust * Math.cos(m.angle) + player.force.y -= 0.7 * thrust * Math.sin(m.angle) + + const friction = 0.96 + Matter.Body.setVelocity(player, { + x: friction * player.velocity.x, + y: friction * player.velocity.y + }); + } + const spinChange = 1.1 + if (input.right) { + player.torque += spinChange + // m.spin += spinChange + } else if (input.left) { + // m.spin -= spinChange + player.torque -= spinChange + } + Matter.Body.setAngularVelocity(player, player.angularVelocity * 0.9) + // m.spin *= 0.88 //spin friction + m.angle += m.spin // + m.angle = player.angle + } + //fix collisions + + collisionChecks = (event) => { + const pairs = event.pairs; + for (let i = 0, j = pairs.length; i != j; i++) { + //mob + (player,bullet,body) collisions + for (let k = 0; k < mob.length; k++) { + if (mob[k].alive && m.alive) { + if (pairs[i].bodyA === mob[k]) { + collideMob(pairs[i].bodyB); + break; + } else if (pairs[i].bodyB === mob[k]) { + collideMob(pairs[i].bodyA); + break; + } + + function collideMob(obj) { + //player + mob collision + if ( + m.immuneCycle < m.cycle && + // (obj === playerBody || obj === playerHead) && + (obj === player) && + !(tech.isFreezeHarmImmune && (mob[k].isSlowed || mob[k].isStunned)) + ) { + mob[k].foundPlayer(); + let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0 + if (tech.isRewindAvoidDeath && m.energy > 0.66) { //CPT reversal runs in m.damage, but it stops the rest of the collision code here too + m.damage(dmg); + return + } + m.damage(dmg); + if (tech.isPiezo) m.energy += 4; + if (tech.isBayesian) powerUps.ejectTech() + if (mob[k].onHit) mob[k].onHit(k); + m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to collision 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) + }); + + if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && mob[k].dropPowerUp && m.energy > 0.34 * m.maxEnergy) { + m.energy -= 0.33 * m.maxEnergy + m.immuneCycle = 0; //player doesn't go immune to collision damage + mob[k].death(); + simulation.drawList.push({ //add dmg to draw queue + x: pairs[i].activeContacts[0].vertex.x, + y: pairs[i].activeContacts[0].vertex.y, + radius: dmg * 2000, + color: "rgba(255,0,255,0.2)", + time: simulation.drawTime + }); + } else { + simulation.drawList.push({ //add dmg to draw queue + x: pairs[i].activeContacts[0].vertex.x, + y: pairs[i].activeContacts[0].vertex.y, + radius: dmg * 500, + color: simulation.mobDmgColor, + time: simulation.drawTime + }); + } + return; + // } + } + //mob + bullet collisions + if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) { + obj.beforeDmg(mob[k]); //some bullets do actions when they hits things, like despawn //forces don't seem to work here + let dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity))) + if (tech.isCrit && mob[k].isStunned) dmg *= 4 + mob[k].foundPlayer(); + mob[k].damage(dmg); + simulation.drawList.push({ //add dmg to draw queue + x: pairs[i].activeContacts[0].vertex.x, + y: pairs[i].activeContacts[0].vertex.y, + radius: Math.log(2 * dmg + 1.1) * 40, + color: simulation.playerDmgColor, + time: simulation.drawTime + }); + return; + } + //mob + body collisions + if (obj.classType === "body" && obj.speed > 6) { + const v = Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)); + if (v > 9) { + let dmg = 0.05 * b.dmgScale * v * obj.mass * tech.throwChargeRate; + if (mob[k].isShielded) dmg *= 0.35 + mob[k].damage(dmg, true); + if (tech.isBlockPowerUps && !mob[k].alive && mob[k].dropPowerUp) { + let type = tech.isEnergyNoAmmo ? "heal" : "ammo" + if (Math.random() < 0.4) { + type = "heal" + } else if (Math.random() < 0.3 && !tech.isSuperDeterminism) { + type = "research" + } + powerUps.spawn(mob[k].position.x, mob[k].position.y, type); + // for (let i = 0, len = Math.ceil(2 * Math.random()); i < len; i++) {} + } + + const stunTime = dmg / Math.sqrt(obj.mass) + if (stunTime > 0.5) mobs.statusStun(mob[k], 30 + 60 * Math.sqrt(stunTime)) + if (mob[k].distanceToPlayer2() < 1000000 && !m.isCloak) mob[k].foundPlayer(); + if (tech.fragments && obj.speed > 10 && !obj.hasFragmented) { + obj.hasFragmented = true; + b.targetedNail(obj.position, tech.fragments * 4) + } + simulation.drawList.push({ + x: pairs[i].activeContacts[0].vertex.x, + y: pairs[i].activeContacts[0].vertex.y, + radius: Math.log(2 * dmg + 1.1) * 40, + color: simulation.playerDmgColor, + time: simulation.drawTime + }); + return; + } + } + } + } + } + } + } + } + }, }; \ No newline at end of file diff --git a/js/spawn.js b/js/spawn.js index 313794d..be151aa 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -103,9 +103,8 @@ const spawn = { level.levels.push("null") level.exit.x = 5500; level.exit.y = -330; - simulation.makeTextLog(`level.levels.push("null")`) //
${powerUps.research.count} - - //remove block map element + simulation.makeTextLog(`undecided = ${lore.techCount}/10
level.levels.push("null")`); + //remove block map element so exit is clear Matter.World.remove(engine.world, map[map.length - 1]); map.splice(map.length - 1, 1); simulation.draw.setPaths(); //redraw map draw path @@ -113,8 +112,8 @@ const spawn = { //reset game setTimeout(() => { simulation.makeTextLog(`simulation.complete()`); - let delay = 1000 - for (let i = 0; i < 1.01; i += 0.01 + 0.1 * Math.random()) { + let delay = 2000 + for (let i = 0; i < 1; i += 0.01 + 0.2 * Math.random() * Math.random()) { setTimeout(function() { simulation.makeTextLog(`simulation.analysis = ${(i).toFixed(3)}`); }, delay); @@ -122,13 +121,15 @@ const spawn = { } setTimeout(function() { simulation.makeTextLog(`simulation.analysis = 1`); - }, delay); - delay += 2000 - setTimeout(() => { - if (!simulation.paused && !simulation.testing) { - simulation.makeTextLog(`World.clear(engine.world)`); - setTimeout(() => { m.death() }, 2000); - } + setTimeout(() => { + simulation.makeTextLog(`undecided = ${lore.techCount}/10`); + setTimeout(() => { + if (!simulation.paused && !simulation.testing) { + simulation.makeTextLog(`World.clear(engine.world)`); + setTimeout(() => { m.death() }, 4000); + } + }, 3000); + }, 2000); }, delay); }, 5000); } @@ -161,8 +162,10 @@ const spawn = { //push away mobs for (let i = 0, len = mob.length; i < len; ++i) { if (mob[i] !== this) { - const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, mob[i].position)), -65) - Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, velocity)); + mob[i].damage(Infinity, true); + + // const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, mob[i].position)), -65) + // Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, velocity)); } } diff --git a/js/tech.js b/js/tech.js index 588ef76..1121144 100644 --- a/js/tech.js +++ b/js/tech.js @@ -3220,7 +3220,7 @@ const tech = { }, { name: "quantum foam", - description: "foam gun fires 0.35 seconds into the future
increase foam gun damage by 153%", + description: "foam gun fires 0.3 seconds into the future
increase foam gun damage by 153%", isGunTech: true, maxCount: 9, count: 0, @@ -4216,7 +4216,7 @@ const tech = { this.count-- }, remove() {} - } + }, ], addLoreTechToPool() { //adds lore tech to tech pool if (!simulation.isCheating) { @@ -4268,6 +4268,43 @@ const tech = { // }, // remove() {} // }, + { + name: "banish", + description: "erase all junk tech from the possible pool
probably...", + maxCount: 1, + count: 0, + numberInPool: 0, + isNonRefundable: true, + isCustomHide: true, + isJunk: true, + allowed() { + return true + }, + requires: "", + effect() { + tech.removeJunkTechFromPool() + }, + remove() {} + }, + { + name: "ship", + description: "fly around with no legs
reduce combat difficulty by 1 level", + maxCount: 1, + count: 0, + numberInPool: 0, + isNonRefundable: true, + isCustomHide: true, + isJunk: true, + allowed() { + return !m.isShipMode + }, + requires: "", + effect() { + m.shipMode() + level.difficultyDecrease(simulation.difficultyMode) + }, + remove() {} + }, { name: "lubrication", description: "reduce block density and friction for this level", @@ -4544,7 +4581,7 @@ const tech = { isCustomHide: true, isJunk: true, allowed() { - return true + return !m.isShipMode }, requires: "", effect() { @@ -4593,7 +4630,7 @@ const tech = { isCustomHide: true, isJunk: true, allowed() { - return true + return !m.isShipMode }, requires: "", effect() { @@ -4637,7 +4674,7 @@ const tech = { isCustomHide: true, isJunk: true, allowed() { - return true + return !m.isShipMode }, requires: "", effect() { @@ -4833,7 +4870,7 @@ const tech = { }, requires: "at least 1 gun", effect() { - for (let i = 0; i < b.inventory.length; i++) powerUps.spawn(m.pos.x, m.pos.y, "gun"); + for (let i = 0; i < b.inventory.length; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "gun"); //removes guns and ammo b.inventory = []; @@ -4861,7 +4898,7 @@ const tech = { }, requires: "at least 4 research", effect() { - for (let i = 0; i < powerUps.research.count; i++) powerUps.spawn(m.pos.x, m.pos.y, "research"); + for (let i = 0; i < powerUps.research.count; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "research"); powerUps.research.count = 0 }, remove() {} diff --git a/todo.txt b/todo.txt index c3393ab..f7c6f6c 100644 --- a/todo.txt +++ b/todo.txt @@ -1,11 +1,8 @@ ******************************************************** NEXT PATCH ******************************************************** -all mobs that move through walls and blocks now have a transparent fill -player and power ups float in hazards - -tech: apomixis - after reaching 100% duplication spawn 4 level bosses -tech: quantum foam - +153% foam damage, fire 0.35s into the future -bullets are bigger, and easier to see +added 2 new testing keys: J = clear mobs, H = infinity health +added junk tech: ship (it's hard to control, but you get better with practice) + m.shipMode() in console ******************************************************** BUGS ******************************************************** @@ -35,7 +32,23 @@ use the floor of portal sensor on the player? to unstuck player ******************************************************** TODO ******************************************************** -increase bullet size, but don't increase bullet damage +tech: health becomes drones + requires mass-energy? + junk tech? + +tech: 1/3 of the time foam fires 1 extra backwards foam + +make a secret only accessible to the ship (very small + flying) + +map: laboratory + rooms with switches that change physics + gravity room + portal room + laser room + radiation room + portal + rotor + falling blocks = perpetual motion room + a button that spawns a heal. + final boss: hide boss after spawning mobs reduce health by 1/3? @@ -264,14 +277,6 @@ give mobs more animal-like behaviors like rain world this might be hard to code isolated mobs try to group up -map: laboratory - rooms with switches that change physics - gravity room - portal room - laser room - radiation room - a button that spawns a heal. - mob: wall mounted guns / lasers not part of randomized mob pool, customized to each level