From ebd22741d4d8c68e30e37e959cca43f1e4421123 Mon Sep 17 00:00:00 2001 From: landgreen Date: Sat, 31 Aug 2024 08:28:05 -0700 Subject: [PATCH] subway stations subway 2 new subway stations more visible button graphics on subway new constraints no health bars no pause while choosing tech: coherence - past choices are added to all future tech requires decoherence research and cancel buttons have a sticky scroll positioning eternalism: you can't pause while choosing, but you can otherwise pause now 1.25->1.3 damage bugs MIRV missiles now interact with time dilation properly --- img/coherence.webp | Bin 0 -> 54928 bytes js/bullet.js | 27 +---- js/index.js | 2 +- js/level.js | 297 +++++++++++++++++++++++++++++++++++++++++++-- js/mob.js | 19 ++- js/player.js | 116 ++++++++++++++++++ js/powerup.js | 85 +++++++------ js/tech.js | 44 +++++-- style.css | 9 ++ todo.txt | 119 +++++++----------- 10 files changed, 557 insertions(+), 161 deletions(-) create mode 100644 img/coherence.webp diff --git a/img/coherence.webp b/img/coherence.webp new file mode 100644 index 0000000000000000000000000000000000000000..c433b176ef25e8665c6e63495bdc454b876eedaa GIT binary patch literal 54928 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 literal 0 HcmV?d00001 diff --git a/js/bullet.js b/js/bullet.js index 5459cac..49e6fd3 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -6723,10 +6723,7 @@ const b = { // } // } else { m.fireCDcycle = m.cycle + tech.missileFireCD * b.fireCDscale / countReduction; // cool down - const direction = { - x: Math.cos(m.angle), - y: Math.sin(m.angle) - } + const direction = { x: Math.cos(m.angle), y: Math.sin(m.angle) } // const where = { // x: m.pos.x + 30 * direction.x, // y: m.pos.y + 30 * direction.y @@ -6752,23 +6749,17 @@ const b = { let count = 0 const fireMissile = () => { if (m.crouch) { - b.missile({ - x: m.pos.x + 30 * direction.x, - y: m.pos.y + 30 * direction.y - }, m.angle, 20, sqrtCountReduction) + b.missile({ x: m.pos.x + 30 * direction.x, y: m.pos.y + 30 * direction.y }, m.angle, 20, sqrtCountReduction) bullet[bullet.length - 1].force.x += 0.5 * push.x * (Math.random() - 0.5) bullet[bullet.length - 1].force.y += 0.004 + 0.5 * push.y * (Math.random() - 0.5) } else { - b.missile({ - x: m.pos.x + 30 * direction.x, - y: m.pos.y + 30 * direction.y - }, m.angle, -15, sqrtCountReduction) + b.missile({ x: m.pos.x + 30 * direction.x, y: m.pos.y + 30 * direction.y }, m.angle, -15, sqrtCountReduction) bullet[bullet.length - 1].force.x += push.x * (Math.random() - 0.5) bullet[bullet.length - 1].force.y += 0.005 + push.y * (Math.random() - 0.5) } } const cycle = () => { - if ((simulation.paused || m.isBodiesAsleep) && m.alive) { + if ((simulation.paused) && m.alive) { requestAnimationFrame(cycle) } else { count++ @@ -6781,15 +6772,9 @@ const b = { requestAnimationFrame(cycle); } else { if (m.crouch) { - b.missile({ - x: m.pos.x + 40 * direction.x, - y: m.pos.y + 40 * direction.y - }, m.angle, 25) + b.missile({ x: m.pos.x + 40 * direction.x, y: m.pos.y + 40 * direction.y }, m.angle, 25) } else { - b.missile({ - x: m.pos.x + 40 * direction.x, - y: m.pos.y + 40 * direction.y - }, m.angle, -12) + b.missile({ x: m.pos.x + 40 * direction.x, y: m.pos.y + 40 * direction.y }, m.angle, -12) bullet[bullet.length - 1].force.y += 0.04 * (Math.random() - 0.2) } } diff --git a/js/index.js b/js/index.js index d36ff1b..ad9d3fd 100644 --- a/js/index.js +++ b/js/index.js @@ -1421,7 +1421,7 @@ window.addEventListener("keydown", function (event) { // level.levelAnnounce(); document.body.style.cursor = "none"; requestAnimationFrame(cycle); - } else if (!tech.isNoDraftPause) { + } else { //if (!tech.isNoDraftPause) simulation.paused = true; build.pauseGrid() document.body.style.cursor = "auto"; diff --git a/js/level.js b/js/level.js index 18ee245..d990d5b 100644 --- a/js/level.js +++ b/js/level.js @@ -17,7 +17,9 @@ const level = { if (level.levelsCleared === 0) { //this code only runs on the first level // simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode // simulation.isHorizontalFlipped = true - // level.levelsCleared = 4 + // spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns + // spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns + // level.levelsCleared = 11 // level.updateDifficulty() // tech.giveTech("performance") // m.maxHealth = m.health = 1//00000000 @@ -44,17 +46,20 @@ const level = { // b.guns[8].ammo = 100000000 // requestAnimationFrame(() => { tech.giveTech("stimulated emission") }); // tech.giveTech("Hilbert space") - // for (let i = 0; i < 1; ++i) tech.giveTech("decoherence") - // for (let i = 0; i < 1; ++i) tech.giveTech("mass-energy equivalence") + // tech.addJunkTechToPool(0.5) + // for (let i = 0; i < 1; ++i) tech.giveTech("coherence") + // for (let i = 0; i < 1; ++i) tech.giveTech("nitinol") + // m.skin.egg(); + // for (let i = 0; i < 1; ++i) tech.giveTech("depolarization") // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("wikipedia") }); // 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 - // for (let i = 0; i < 1; i++) powerUps.directSpawn(450, -50, "tech"); - // for (let i = 0; i < 3; i++) powerUps.directSpawn(m.pos.x + 200, m.pos.y - 50, "boost", false); + // for (let i = 0; i < 4; i++) powerUps.directSpawn(450, -50, "tech"); + // for (let i = 0; i < 7; i++) powerUps.directSpawn(m.pos.x + 200, m.pos.y - 250, "research", false); // spawn.bodyRect(575, -700, 150, 150); //block mob line of site on testing - // level.heal(); + // level.subway(); level[simulation.isTraining ? "walk" : "initial"]() //normal starting level ************************************************** @@ -334,6 +339,30 @@ const level = { constraintDescription1: "", //used in pause menu and console constraintDescription2: "", constraint: [ + { + description: "no pause while choosing", + effect() { + level.isNoPause = true + }, + remove() { + level.isNoPause = false + } + }, + { + description: "no health bars", + effect() { + mobs.healthBar = () => { } + level.isHideHealth = true + document.getElementById("health").style.display = "none" + document.getElementById("health-bg").style.display = "none" + }, + remove() { + mobs.healthBar = mobs.defaultHealthBar + level.isHideHealth = false + document.getElementById("health").style.display = "inline" + document.getElementById("health-bg").style.display = "inline" + } + }, { description: "0.5x energy regen", effect() { @@ -561,6 +590,8 @@ const level = { reducedHealthLost: 0, isReducedHealth: false, isReducedRegen: 1, + isHideHealth: false, + isNoPause: false, levelAnnounce() { const cheating = simulation.isCheating ? "(testing)" : "" if (level.levelsCleared === 0) { @@ -2604,7 +2635,6 @@ const level = { //start a conversation based on the number of conversations seen if (localSettings.loreCount > lore.conversation.length - 1) localSettings.loreCount = lore.conversation.length - 1; //repeat final conversation if lore count is too high if (!simulation.isCheating && localSettings.loreCount < lore.conversation.length) { - tech.isNoDraftPause = true //disable pause lore.testSpeechAPI() //see if speech is working lore.chapter = localSettings.loreCount //set the chapter to listen to to be the lore level (you can't use the lore level because it changes during conversations) lore.sentence = 0 //what part of the conversation to start on @@ -3185,7 +3215,7 @@ const level = { train[train.length - 1].stops = { left: -7225, right: -1725 } const stationList = [] //use to randomize station order - for (let i = 1, totalNumberOfStations = 8; i < totalNumberOfStations; ++i) stationList.push(i) //!!!! update station number when you add a new station + for (let i = 1, totalNumberOfStations = 10; i < totalNumberOfStations; ++i) stationList.push(i) //!!!! update station number when you add a new station shuffle(stationList); stationList.splice(0, 3); //remove some stations to keep it to 4 stations stationList.unshift(0) //add index zero to the front of the array @@ -3201,6 +3231,8 @@ const level = { } removeAll(map); map = []; + removeAll(composite); + composite = [] //remove any powerUp that is too far from player for (let i = 0; i < powerUp.length; ++i) { if (Vector.magnitudeSquared(Vector.sub(player.position, powerUp[i].position)) > 9000000) { //remove any powerUp farther then 3000 pixels from player @@ -3244,7 +3276,25 @@ const level = { } } } - gateButton.draw(); + // gateButton.draw(); + if (gateButton.isUp) { + //aura around button + ctx.beginPath(); + ctx.ellipse(gateButton.min.x + gateButton.width * 0.5, gateButton.min.y + 6, 0.75 * gateButton.width, 0.5 * gateButton.width, 0, Math.PI, 0); //ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise) + ctx.fillStyle = `hsla(345, 100%, 80%,${0.1 + 0.4 * Math.random()})` + ctx.fill(); + ctx.fillStyle = "hsl(345, 100%, 75%)" + ctx.fillRect(gateButton.min.x, gateButton.min.y - 10, gateButton.width, 25) + ctx.strokeStyle = "#000"//"rgba(255,255,255,0.2)" + ctx.lineWidth = 2 + ctx.strokeRect(gateButton.min.x, gateButton.min.y - 10, gateButton.width, 25) + } else { + ctx.fillStyle = "hsl(345, 100%, 75%)" + ctx.fillRect(gateButton.min.x, gateButton.min.y, gateButton.width, 10) + ctx.strokeStyle = "#000"//"rgba(255,255,255,0.2)" + ctx.lineWidth = 2 + ctx.strokeRect(gateButton.min.x, gateButton.min.y, gateButton.width, 10) + } } } const stations = [ //update totalNumberOfStations as you add more stations @@ -3940,8 +3990,235 @@ const level = { ctx.fillRect(x + 950, -675, 400, 125); } }, + () => { //angled jumps + const buttonsCoords = [{ x: x + 50, y: -1395 }, { x: x - 625, y: -2945 }, { x: x + 900, y: -2945 }] + const buttonsCoordsIndex = Math.floor(Math.random() * buttonsCoords.length) //pick a random element from the array + + spawn.mapRect(x + -1500, -210, 3000, 400);//station floor + boosts = [] + boosts.push(level.boost(x - 311, -218, 1200, 1.85)) + spawn.mapRect(x + -225, -525, 675, 375); + spawn.mapRect(x + -1350, -1175, 400, 675); + spawn.mapRect(x + -225, -2125, 675, 400); + + // spawn.mapRect(x + -225, -1325, 675, 550); + spawn.mapRect(x + -225, -1400, 675, 650); + + boosts.push(level.boost(x - 1335, -1200, 1800, 1)) + boosts.push(level.boost(x + 1272, -1300, 1550, 2.75)) //far right + //high up walls + boosts.push(level.boost(x + 1455, -2048, 1450, 2.5)) + spawn.mapRect(x + 1500, -3825, 325, 1900); + boosts.push(level.boost(x - 1555, -2048, 1450, 0.64)) + // spawn.mapRect(x + -1625, -3975, 3450, 325); + spawn.mapRect(x + -1825, -4000, 325, 2150); + spawn.mapRect(x + -1825, -4070, 3650, 375);//roof + + spawn.randomMob(x + 100, -2125, 0); + boosts.push(level.boost(x + 75, -2175, 2800)) + spawn.mapRect(x + -100, -3900, 400, 400); + Matter.Body.setAngle(map[map.length - 1], map[map.length - 1].angle - Math.PI / 4); + + spawn.mapRect(x + 225, -2950, 1100, 150); + spawn.mapRect(x + -1325, -2950, 1325, 150); + + if (isExitOpen) { + level.exit.x = buttonsCoords[buttonsCoordsIndex].x; + level.exit.y = buttonsCoords[buttonsCoordsIndex].y - 25; + } else { + var gateButton = level.button(buttonsCoords[buttonsCoordsIndex].x, buttonsCoords[buttonsCoordsIndex].y, 126, false) //x, y, width = 126, isSpawnBase = true + gateButton.isUp = true + if (stationNumber > gatesOpenRight) { + var gate = level.doorMap(x + 1375, -525, 50, 375, 300, 20, false) //x, y, width, height, distance, speed = 20 + } else if (stationNumber < gatesOpenLeft) { + var gate = level.doorMap(x - 1375, -525, 50, 375, 300, 20, false) //x, y, width, height, distance, speed = 20 + } + } + + if (!isExitOpen) { + spawn.randomMob(x + 350, -600, 0); + spawn.randomMob(x + -25, -600, 0); + spawn.randomMob(x + 600, -300, 0); + spawn.randomMob(x + 1050, -300, 0); + spawn.randomMob(x + 350, -1525, 0); + spawn.randomMob(x + -75, -1525, 0); + spawn.randomMob(x + -1075, -1275, 0); + spawn.randomMob(x + -1350, -2050, 0); + spawn.randomMob(x + -50, -2250, 0); + spawn.randomMob(x + -200, -3050, 0); + spawn.randomMob(x + -925, -3150, 0); + spawn.randomMob(x + 450, -3125, 0); + spawn.randomMob(x + 1075, -3025, 0); + spawn.randomMob(x + 750, -3125, 0); + spawn.randomMob(x + -725, -3125, 0); + } + stationCustom = () => { + for (let i = 0; i < boosts.length; i++) { + boosts[i].query() + } + } + stationCustomTopLayer = () => { + checkGate(gate, gateButton) + ctx.fillStyle = "rgba(0,0,0,0.08)" + ctx.fillRect(x - 225, -775, 675, 275); + ctx.fillRect(x - 225, -1750, 675, 375); + } + }, + () => { //people movers + simulation.removeEphemera("zoom")//stop previous zooms + simulation.zoomTransition(2000) + const buttonsCoords = [{ x: x - 65, y: -2045 }] //only one button location? + const buttonsCoordsIndex = Math.floor(Math.random() * buttonsCoords.length) //pick a random element from the array + const moverDirection = stationNumber > 0 ? 1 : -1 + console.log(stationNumber) + if (isExitOpen) { + level.exit.x = buttonsCoords[buttonsCoordsIndex].x; + level.exit.y = buttonsCoords[buttonsCoordsIndex].y - 25; + } else { + var gateButton = level.button(buttonsCoords[buttonsCoordsIndex].x, buttonsCoords[buttonsCoordsIndex].y, 126, false) //x, y, width = 126, isSpawnBase = true + gateButton.isUp = true + if (stationNumber > gatesOpenRight) { + var gate = level.doorMap(x + 1375, -525, 50, 375, 300, 20, false) //x, y, width, height, distance, speed = 20 + } else if (stationNumber < gatesOpenLeft) { + var gate = level.doorMap(x - 1375, -525, 50, 375, 300, 20, false) //x, y, width, height, distance, speed = 20 + } + } + + //floor 0 + spawn.mapRect(x + -1500, -210, 3000, 400);//station floor + const movers = [] + movers.push(level.mover(x + -1200, -220, 900, 50, 3 * moverDirection)) + movers.push(level.mover(x + 300, -220, 900, 50, 3 * moverDirection)) + spawn.mapRect(x + -4700, -7000, 700, 5200);//Left wall + spawn.mapRect(x + 4000, -7000, 500, 5200);//Right wall + const portals = [] + portals.push(level.portal({ x: x - 315, y: -310 }, Math.PI, { x: x - 3985, y: -2110 }, 0)) + spawn.mapRect(x - 1375, -1100, 2750, 300); + spawn.mapRect(x + -300, -525, 600, 550); + + //floor 1 fast with jump in middle + movers.push(level.mover(x - 4000, -2025, 2700, 50, 30 * moverDirection)) + movers.push(level.mover(x + 1300, -2025, 2700, 50, 30 * moverDirection)) + portals.push(level.portal({ x: x + 3985, y: -2110 }, Math.PI, { x: x - 3985, y: -3410 }, 0)) + spawn.mapRect(x + -500, -2050, 1000, 150); + spawn.mapRect(x + -4200, -2300, 1225, 125); + spawn.mapRect(x + 2675, -2350, 1625, 150); + //up mode triggered by player contact + const elevator0 = level.elevator(x - 1300, -1175, 175, 50, -1600, 0.011, { up: 0.01, down: 0.7 }) + const elevator1 = level.elevator(x + 1125, -1175, 175, 50, -1600, 0.011, { up: 0.01, down: 0.7 }) + + //floor 2 slow with some things to jump on and mobs + portals.push(level.portal({ x: x + 3985, y: -3410 }, Math.PI, { x: x - 3985, y: -5110 }, 0)) + movers.push(level.mover(x - 4000, -3325, 8000, 50, 7 * moverDirection)) + if (Math.random() < 0.5) { + spawn.mapRect(x + 1125, -3625, 325, 200); + spawn.mapRect(x - 1350, -3600, 375, 175); + spawn.mapRect(x + 325, -3825, 325, 100); + spawn.mapRect(x - 675, -3800, 450, 75); + spawn.mapRect(x - 1775, -3900, 175, 400); + spawn.mapRect(x - 2100, -4275, 325, 775); + spawn.mapRect(x + 2625, -3700, 450, 125); + spawn.mapRect(x - 3350, -3335, 175, 50); + spawn.mapRect(x - 200, -3335, 500, 50); + spawn.mapRect(x + 3200, -3335, 325, 50); + } else { + spawn.mapRect(x + -325, -3550, 425, 125); + spawn.mapRect(x + -1100, -3750, 425, 75); + spawn.mapRect(x + -2175, -3500, 200, 200); + spawn.mapRect(x + 675, -3700, 175, 75); + spawn.mapRect(x + 2375, -3425, 275, 125); + spawn.mapRect(x + 1750, -3650, 275, 75); + spawn.mapRect(x + 1125, -3850, 175, 550); + spawn.mapRect(x + -3300, -4175, 675, 550); + } + spawn.mapRect(x + 3550, -3625, 550, 100); + spawn.mapRect(x + -4100, -3650, 325, 100); + if (!isExitOpen) { + spawn.randomMob(x + 3900, -3725, 0); + spawn.randomMob(x + 3675, -3700, 0); + spawn.randomMob(x + 2075, -3400, 0); + spawn.randomMob(x + 2500, -3500, 0); + spawn.randomMob(x + 1975, -3700, 0); + spawn.randomMob(x + 1250, -3900, 0); + spawn.randomMob(x + 800, -3750, 0); + spawn.randomMob(x + 2700, -4700, 0); + spawn.randomMob(x + -75, -3650, 0); + spawn.randomMob(x + 575, -3500, 0); + spawn.randomMob(x + -850, -3900, 0); + spawn.randomMob(x + -2725, -4350, 0); + spawn.randomMob(x + -2975, -4300, 0); + spawn.randomMob(x + -3950, -3675, 0); + spawn.randomMob(x + -2950, -3450, 0); + spawn.randomMob(x + -2075, -3575, 0); + spawn.randomMob(x + -1650, -3450, 0); + spawn.randomMob(x + -2825, -4400, 0); + spawn.randomMob(x + -900, -4475, 0); + spawn.randomMob(x + -75, -3575, 0); + spawn.randomMob(x + 3900, -3775, 0); + spawn.randomMob(x + 2825, -3375, 0); + spawn.randomMob(x + 2075, -3425, 0); + spawn.randomMob(x + 1525, -3425, 0); + spawn.randomMob(x + 350, -3500, 0); + spawn.randomMob(x + -1675, -3650, 0); + spawn.randomMob(x + -3025, -3450, 0); + spawn.randomMob(x + -3850, -3750, 0); + } + + //floor 3 fast with bumps + spawn.mapRect(x + -4250, -7000, 8475, 325);//roof + portals.push(level.portal({ x: x + 3985, y: -5110 }, Math.PI, { x: x + 320, y: -310 }, 0)) + movers.push(level.mover(x - 4000, -5025, 8000, 50, 50 * moverDirection)) + if (Math.random() < 0.5) { + spawn.mapVertex(x - 2100, -5050, "-150 0 150 0 5 -150 -5 -150") + spawn.mapVertex(x - 0, -5100, "-500 0 500 0 25 -300 -25 -300") + spawn.mapVertex(x + 2100, -5050, "-300 0 300 0 100 -100 -100 -100") + } else { + spawn.mapVertex(x - 2100, -5050, "-100 0 100 0 25 -100 -25 -100") + spawn.mapVertex(x - 0, -5050, "-400 0 400 0 100 -100 -100 -100") + spawn.mapVertex(x + 2100, -5050, "-400 0 400 0 100 -100 -100 -100") + } + spawn.mapRect(x + 2000, -6700, 200, 1250); + spawn.mapRect(x + -100, -6700, 200, 1075); + spawn.mapRect(x + -2125, -6700, 50, 925); + // spawn.mapRect(x + -4150, -5325, 975, 125); //portal over hang + // spawn.mapRect(x + 3325, -5300, 850, 100);//portal over hang + + stationCustom = () => { + for (let i = 0; i < movers.length; i++) movers[i].push(); + for (let i = 0; i < portals.length; i++) { + portals[i][2].query() + portals[i][3].query() + } + } + stationCustomTopLayer = () => { + for (let i = 0; i < portals.length; i++) { + portals[i][0].draw() + portals[i][1].draw() + portals[i][2].draw() + portals[i][3].draw() + } + elevator0.moveOnTouch() + elevator1.moveOnTouch() + + //custom draw so you can see the mover tracks on subway map with the Line of sight graphics + ctx.strokeStyle = "#000" + ctx.lineWidth = 4; + ctx.setLineDash([40, 40]); + for (let i = 0; i < movers.length; i++) { + ctx.beginPath(); + ctx.moveTo(movers[i].vertices[0].x + 2, movers[i].vertices[0].y - 3); + ctx.lineTo(movers[i].vertices[1].x - 2, movers[i].vertices[1].y - 3); + ctx.lineDashOffset = (-simulation.cycle * movers[i].VxGoal) % 80; + ctx.stroke(); + } + ctx.setLineDash([0, 0]); + checkGate(gate, gateButton) + } + }, ] - // stations[4]() //for testing a specific station + //update totalNumberOfStations to a higher number when adding new maps + simulation.zoomTransition(level.defaultZoom) + // stations[9]() //for testing a specific station stations[stationList[Math.abs(stationNumber % stationList.length)]]() //*************** run this one when uploading //add in standard station map infrastructure spawn.mapRect(x + -8000, 0, 16000, 800);//tunnel floor diff --git a/js/mob.js b/js/mob.js index 01a7f04..71ca03d 100644 --- a/js/mob.js +++ b/js/mob.js @@ -30,6 +30,20 @@ const mobs = { // } } }, + defaultHealthBar() { + for (let i = 0, len = mob.length; i < len; i++) { + if (mob[i].seePlayer.recall && mob[i].showHealthBar) { + const h = mob[i].radius * 0.3; + const w = mob[i].radius * 2; + const x = mob[i].position.x - w / 2; + const y = mob[i].position.y - w * 0.7; + ctx.fillStyle = "rgba(100, 100, 100, 0.3)"; + ctx.fillRect(x, y, w, h); + ctx.fillStyle = "rgba(255,0,0,0.7)"; + ctx.fillRect(x, y, w * mob[i].health, h); + } + } + }, healthBar() { for (let i = 0, len = mob.length; i < len; i++) { if (mob[i].seePlayer.recall && mob[i].showHealthBar) { @@ -1010,8 +1024,9 @@ const mobs = { this.death(); //death with no power up } }, - healthBar() { //draw health by mob //most health bars are drawn in mobs.healthbar(); - if (this.seePlayer.recall) { + //draw health by mob //most health bars are drawn in mobs.healthBar(); , not this + healthBar() { + if (this.seePlayer.recall && !level.isHideHealth) { const h = this.radius * 0.3; const w = this.radius * 2; const x = this.position.x - w / 2; diff --git a/js/player.js b/js/player.js index 9bd7a42..6b0cb91 100644 --- a/js/player.js +++ b/js/player.js @@ -987,6 +987,121 @@ const m = { powerUps.boost.draw() } }, + egg() { + m.isAltSkin = true + m.yOffWhen.stand = 52 + m.yOffWhen.jump = 72 + m.coyoteCycles = 11 + m.hardLandCDScale = 0.5 + m.hardLanding = 160 + m.squirrelFx = 1.4; + m.squirrelJump = 1.16; + m.setMovement() + + m.draw = function () { + if (powerUps.boost.endCycle > simulation.cycle) { + //gel that acts as if the wind is blowing it when player moves + ctx.save(); + ctx.translate(m.pos.x, m.pos.y); + m.velocitySmooth = Vector.add(Vector.mult(m.velocitySmooth, 0.8), Vector.mult(player.velocity, 0.2)) + ctx.rotate(Math.atan2(m.velocitySmooth.y, m.velocitySmooth.x)) + ctx.beginPath(); + const radius = 39 + const mag = 14 * Vector.magnitude(m.velocitySmooth) + radius + ctx.arc(0, 0, radius, -Math.PI / 2, Math.PI / 2); + ctx.bezierCurveTo(-radius, radius, -radius, 0, -mag, 0); // bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) + ctx.bezierCurveTo(-radius, 0, -radius, -radius, 0, -radius); + + // const time = (powerUps.boost.endCycle - m.cycle) / powerUps.boost.duration + const time = Math.min(0.5, (powerUps.boost.endCycle - simulation.cycle) / powerUps.boost.duration) + + ctx.fillStyle = `rgba(0,0,0,${0.04 + 0.3 * time})` + ctx.fill() + // ctx.strokeStyle = "#333" + // ctx.lineWidth = 1 + // ctx.stroke(); + ctx.restore(); + } + + m.walk_cycle += m.flipLegs * m.Vx; + ctx.save(); + ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20) + ctx.translate(m.pos.x, m.pos.y); + m.calcLeg(Math.PI, -1.25); + m.drawLeg("#606060"); + m.calcLeg(0, 0); + m.drawLeg("#444"); + + ctx.rotate(m.angle); + ctx.beginPath(); + // ctx.arc(0, 0, 30, 0, 2 * Math.PI); + ctx.ellipse(0, 0, 0.9 * 31, 1.05 * 31, 0, 0, 2 * Math.PI); + ctx.fillStyle = m.bodyGradient + ctx.fill(); + // ctx.arc(15, 0, 4, 0, 2 * Math.PI); + ctx.ellipse(15, 0, 0.8 * 4, 1.1 * 4, 0, 0, 2 * Math.PI); + + ctx.strokeStyle = "#333"; + ctx.lineWidth = 2; + ctx.stroke(); + ctx.restore(); + m.yOff = m.yOff * 0.75 + m.yOffGoal * 0.25; //smoothly move leg height towards height goal + } + m.drawLeg = function (stroke) { + if (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2) { + m.flipLegs = 1; + } else { + m.flipLegs = -1; + } + const hip = { x: m.hip.x - 5, y: m.hip.y + 5 } + const sub = Vector.sub(m.knee, hip) + const off = Vector.mult(Vector.rotate(Vector.normalise(sub), Math.PI / 2), 8) + const kneeBraceHigh = Vector.add(hip, off) + const kneeBraceLow = Vector.add(kneeBraceHigh, Vector.mult(sub, 0.9)) + const foot = { x: m.foot.x - 10, y: m.foot.y - 15 } + ctx.save(); + ctx.scale(m.flipLegs, 1); //leg lines + ctx.beginPath(); + ctx.moveTo(hip.x, hip.y); + ctx.lineTo(m.knee.x, m.knee.y); + ctx.lineTo(foot.x, foot.y); + //extra upper leg brace + ctx.moveTo(kneeBraceHigh.x, kneeBraceHigh.y); + ctx.lineTo(kneeBraceLow.x, kneeBraceLow.y); + ctx.lineTo(m.knee.x, m.knee.y); + + ctx.strokeStyle = stroke; + ctx.lineWidth = 3; + ctx.stroke(); + //foot + ctx.beginPath(); + ctx.moveTo(foot.x, foot.y); + ctx.quadraticCurveTo(m.foot.x - 30, m.foot.y + 12, m.foot.x + 13, m.foot.y + 3); + ctx.lineWidth = 1.5; + ctx.stroke(); + + //hip joint + ctx.beginPath(); + ctx.arc(m.hip.x, m.hip.y - 2, 11, 0, 2 * Math.PI); + //knee joint + ctx.moveTo(m.knee.x + 3, m.knee.y); + ctx.arc(m.knee.x, m.knee.y, 3, 0, 2 * Math.PI); + //knee brace + // ctx.moveTo(kneeBraceHigh.x + 4, kneeBraceHigh.y); + // ctx.arc(kneeBraceHigh.x, kneeBraceHigh.y, 4, 0, 2 * Math.PI); + ctx.moveTo(kneeBraceLow.x + 2.5, kneeBraceLow.y); + ctx.arc(kneeBraceLow.x, kneeBraceLow.y, 2.5, 0, 2 * Math.PI); + //foot joint + ctx.moveTo(foot.x + 2.5, foot.y); + ctx.arc(foot.x, foot.y, 2.5, 0, 2 * Math.PI); + ctx.fillStyle = "#f6f6f6"//m.fillColor; + ctx.fill(); + ctx.lineWidth = 1; + // ctx.strokeStyle = "#333" + ctx.stroke(); + ctx.restore(); + } + }, mech() { m.isAltSkin = true m.yOffWhen.stand = 52 @@ -1031,6 +1146,7 @@ const m = { m.drawLeg("#606060"); m.calcLeg(0, 0); m.drawLeg("#444"); + ctx.rotate(m.angle); ctx.beginPath(); ctx.arc(0, 0, 30, 0, 2 * Math.PI); diff --git a/js/powerup.js b/js/powerup.js index 4f3af63..6931d74 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -250,7 +250,6 @@ const powerUps = { } else if (type === "field") { m.setField(index) } else if (type === "tech") { - // if (tech.isBanish && tech.tech[index].isBanished) tech.tech[index].isBanished = false simulation.inGameConsole(`
  tech.giveTech("${tech.tech[index].name}")`); tech.giveTech(index) } @@ -261,7 +260,6 @@ const powerUps = { document.getElementById("choose-grid").style.pointerEvents = "none"; document.body.style.cursor = "none"; setTimeout(() => { - // if (!tech.isNoDraftPause) document.body.style.cursor = "auto"; document.getElementById("choose-grid").style.pointerEvents = "auto"; document.getElementById("choose-grid").style.transitionDuration = "0s"; @@ -269,7 +267,7 @@ const powerUps = { simulation.isChoosing = true; //stops p from un pausing on key down if (!simulation.paused) { - if (tech.isNoDraftPause) { + if (tech.isNoDraftPause || level.isNoPause) { document.getElementById("choose-grid").style.opacity = "1" } else { simulation.paused = true; @@ -610,14 +608,6 @@ const powerUps = { tech.addJunkTechToPool(0.01) } powerUps.research.currentRerollCount++ - // if (tech.isBanish && type === 'tech') { // banish researched tech - // const banishLength = tech.isDeterminism ? 1 : 3 + tech.extraChoices * 2 - // for (let i = 0; i < banishLength; i++) { - // const index = powerUps.tech.choiceLog.length - i - 1 - // if (powerUps.tech.choiceLog[index] && tech.tech[powerUps.tech.choiceLog[index]]) tech.tech[powerUps.tech.choiceLog[index]].isBanished = true - // } - // simulation.inGameConsole(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`) - // } if (tech.isResearchReality) { m.switchWorlds() simulation.trails() @@ -769,24 +759,24 @@ const powerUps = { if (tech.isSuperDeterminism) { return `
` } else if (tech.isCancelTech && tech.cancelTechCount === 0) { - return `
randomize
` + return `
randomize
` } else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted && b.inventory.length === 0) { //don't show cancel if on initial level and haven't done tutorial - return `` + return `` } else { - return `
cancel
` + return `
cancel
` } }, researchText(type) { let text = "" if (type === "entanglement") { - text += `
entanglement
` + text += `
entanglement
` } else if (tech.isJunkResearch && powerUps.research.currentRerollCount < 2) { - text += `
` // style = "margin-left: 192px; margin-right: -192px;" + text += `
` // style = "margin-left: 192px; margin-right: -192px;" text += `
` text += `
` text += `
  pseudoscience
` } else if (powerUps.research.count > 0) { - text += `
` // style = "margin-left: 192px; margin-right: -192px;" + text += `
` // style = "margin-left: 192px; margin-right: -192px;" text += `
` for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `
` text += `
  ${tech.isResearchReality ? "alternate reality" : "research"}
` @@ -798,7 +788,7 @@ const powerUps = { researchAndCancelText(type) { let text = `
` if (type === "entanglement") { - text += `entanglement` //‌ + text += `entanglement` } else if (tech.isJunkResearch && powerUps.research.currentRerollCount < 2) { text += `` // style = "margin-left: 192px; margin-right: -192px;" text += `
` @@ -1239,37 +1229,55 @@ const powerUps = { for (let i = 0; i < tech.tech.length; i++) tech.tech[i].isRecentlyShown = false //reset recently shown back to zero if (options.length > 0) { let text = powerUps.buildColumns(totalChoices, "tech") + + addTech = (choose) => { + if (tech.tech[choose].isFieldTech) { + text += powerUps.fieldTechText(choose, `powerUps.choose('tech',${choose})`) + } else if (tech.tech[choose].isGunTech) { + text += powerUps.gunTechText(choose, `powerUps.choose('tech',${choose})`) + } else if (tech.tech[choose].isJunk) { + text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`) + } else if (tech.tech[choose].isSkin) { + text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`) + } else if (tech.tech[choose].isInstant) { + text += powerUps.instantTechText(choose, `powerUps.choose('tech',${choose})`) + } else { //normal tech + text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`) + } + } + if (tech.isRetain) { + for (let i = 0, len = powerUps.retainList.length; i < len; i++) { + //find index from name and add tech to options + for (let j = 0, len = tech.tech.length; j < len; j++) { + if (tech.tech[j].name === powerUps.retainList[i] && tech.tech[j].count < tech.tech[j].maxCount && tech.tech[j].allowed()) { //&& !tech.tech[j].isRecentlyShown + addTech(j) + } + } + } + } for (let i = 0; i < totalChoices; i++) { if (options.length < 1) break - const choose = options[Math.floor(Math.seededRandom(0, options.length))] //pick an element from the array of options - if (tech.isBanish) { - tech.tech[choose].isBanished = true - if (i === 0) simulation.inGameConsole(`options.length = ${optionLengthNoDuplicates} //removed from pool by decoherence`) - } - removeOption(choose) //move from future options pool to avoid repeats on this selection - tech.tech[choose].isRecentlyShown = true //this flag prevents this option from being shown the next time you pick up a tech power up if (Math.random() < tech.junkChance + level.junkAdded) { // choose is set to a random JUNK tech const list = [] for (let i = 0; i < tech.tech.length; i++) { if (tech.tech[i].isJunk) list.push(i) } chooseJUNK = list[Math.floor(Math.random() * list.length)] + if (tech.isRetain) powerUps.retainList.push(tech.tech[chooseJUNK].name) text += powerUps.junkTechText(chooseJUNK, `powerUps.choose('tech',${chooseJUNK})`) } else { - if (tech.tech[choose].isFieldTech) { - text += powerUps.fieldTechText(choose, `powerUps.choose('tech',${choose})`) - } else if (tech.tech[choose].isGunTech) { - text += powerUps.gunTechText(choose, `powerUps.choose('tech',${choose})`) - } else if (tech.tech[choose].isJunk) { - text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`) - } else if (tech.tech[choose].isSkin) { - text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`) - } else if (tech.tech[choose].isInstant) { - text += powerUps.instantTechText(choose, `powerUps.choose('tech',${choose})`) - } else { //normal tech - text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`) + const choose = options[Math.floor(Math.seededRandom(0, options.length))] //pick an element from the array of options + if (tech.isBanish) { + tech.tech[choose].isBanished = true + if (i === 0) simulation.inGameConsole(`options.length = ${optionLengthNoDuplicates} //removed from pool by decoherence`) } - if (options.length < 1) break + removeOption(choose) //remove from future options pool to avoid repeats on this selection + + //this flag prevents this option from being shown the next time you pick up a tech power up + //check if not extra choices from "path integral" + tech.tech[choose].isRecentlyShown = true + if (tech.isRetain) powerUps.retainList.push(tech.tech[choose].name) + addTech(choose) } } if (tech.isExtraBotOption) { @@ -1360,6 +1368,7 @@ const powerUps = { } }, }, + retainList: [], entanglement: { name: "entanglement", color: "#fff", //"hsl(248,100%,65%)", diff --git a/js/tech.js b/js/tech.js index fc7ca79..239e2ee 100644 --- a/js/tech.js +++ b/js/tech.js @@ -1497,7 +1497,7 @@ const tech = { descriptionFunction() { return `${powerUps.orb.boost(1)} also give 0.3x damage taken
for ${(powerUps.boost.duration / 60).toFixed(0)} seconds
` }, - maxCount: 9, + maxCount: 1, count: 1, frequency: 2, frequencyDefault: 2, @@ -3598,7 +3598,7 @@ const tech = { allowed() { return !tech.isSuperDeterminism }, - requires: "not superdeterminism", + requires: "not, superdeterminism", bonusResearch: 7, effect() { tech.isBanish = true @@ -3614,6 +3614,24 @@ const tech = { tech.isBanish = false } }, + { + name: "coherence", + description: `after observing a ${powerUps.orb.tech()} choice
that choice is available for all all future ${powerUps.orb.tech()}`, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return tech.isBanish + }, + requires: "decoherence", + effect() { + tech.isRetain = true + }, + remove() { + tech.isRetain = false + } + }, { name: "peer review", description: `after you research gain 1.05x damage
and +1% JUNK choices`, @@ -3743,9 +3761,9 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return !tech.isSuperDeterminism && !tech.isNoDraftPause + return !tech.isSuperDeterminism }, - requires: "not superdeterminism, eternalism", + requires: "not superdeterminism", effect() { tech.isPauseSwitchField = true; for (let i = 0, len = tech.tech.length; i < len; i++) { @@ -3763,7 +3781,7 @@ const tech = { }, { name: "eternalism", - description: `1.25x damage
time can't be paused (time can still be dilated)`, + description: `1.3x damage, but time doesn't pause
while choosing ${powerUps.orb.field()}, ${powerUps.orb.tech()}, or ${powerUps.orb.gun()}`, maxCount: 1, count: 0, frequency: 1, @@ -3772,7 +3790,7 @@ const tech = { return !tech.isPauseSwitchField && !tech.isPauseEjectTech && !tech.isWormHolePause }, requires: "not unified field theory, paradigm shift, invariant", - damage: 1.25, + damage: 1.3, effect() { tech.damage *= this.damage tech.isNoDraftPause = true @@ -3960,7 +3978,7 @@ const tech = { { name: "dark patterns", description: "1.3x damage
+15% JUNK choices", - maxCount: 9, + maxCount: 3, count: 0, frequency: 1, frequencyDefault: 1, @@ -4604,9 +4622,9 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return !tech.isSuperDeterminism && !tech.isNoDraftPause + return !tech.isSuperDeterminism }, - requires: "not superdeterminism, eternalism", + requires: "not superdeterminism", effect() { tech.isPauseEjectTech = true; }, @@ -6181,7 +6199,7 @@ const tech = { { name: "water shielding", link: `water shielding`, - description: "reduce radioactive effects on you by 0.8x
neutron bomb, drones, explosions, slime", + description: "reduce radioactive effects on you by 0.2x
neutron bomb, drones, explosions, slime", isGunTech: true, maxCount: 1, count: 0, @@ -7735,7 +7753,7 @@ const tech = { // }, name: "electronegativity", descriptionFunction() { - return `1.0023x damage per energy
(${(1 + 0.23 * m.energy).toFixed(2)} at current energy, ${(1 + 0.23 * m.maxEnergy).toFixed(2)}x at maximum energy)` + return `1.0023x damage per energy
(${(1 + 0.23 * m.energy).toFixed(2)}x, ${(1 + 0.23 * m.maxEnergy).toFixed(2)}x at max energy)` }, // description: "+1% damage per 8 stored energy", isFieldTech: true, @@ -11020,7 +11038,7 @@ const tech = { }, { name: "rhythm", - description: "you oscillate up and down", + description: "you oscillate up and down
also you look like an egg", maxCount: 1, count: 0, frequency: 0, @@ -11031,6 +11049,7 @@ const tech = { }, requires: "", effect() { + m.skin.egg(); setInterval(() => { m.yOffWhen.stand = 53 + 28 * Math.sin(simulation.cycle * 0.2) if (m.onGround && !m.crouch) m.yOffGoal = m.yOffWhen.stand @@ -11929,6 +11948,7 @@ const tech = { cancelTechCount: null, isBotDamage: null, isBanish: null, + isRetain: null, isMaxEnergyTech: null, isLowEnergyDamage: null, isRewindBot: null, diff --git a/style.css b/style.css index 965a2fb..f751233 100644 --- a/style.css +++ b/style.css @@ -434,6 +434,15 @@ summary { line-height: 160%; /* background-color: var(--card-color); */ font-size: 1em; + position: sticky; + top: 0px; + z-index: 10; +} + +.sticky { + position: sticky; + top: 0px; + z-index: 10; } /* keeps 5 columns at 1440px */ diff --git a/todo.txt b/todo.txt index e90b56d..3fa073a 100644 --- a/todo.txt +++ b/todo.txt @@ -1,33 +1,21 @@ ******************************************************** NEXT PATCH ************************************************** -tech: hidden-variable theory - after choosing a fieldtech gain 1.15x damage - for pilot wave only -polariton - boosts also give 0.3x damage taken +subway + 2 new subway stations + more visible button graphics on subway -constraints - removed - full damage taken after boss dies - wording is too unclear - new - 0.5x energy regen from all sources - balanced - slow bots - bots have roughly 15% reduction in damage in addition to a slow follow speed - mob death heals mobs - has 1000->700 range and 1->0.33 healing - periodically spawn WIMPs - has a 30s delay and a 15->6s spawn rate - 50->40% JUNK chance +new constraints + no health bars + no pause while choosing - -heuristics gives (1-1.5x)->(1-2x) fire rate and +5% JUNK -autonomous defense harpoon now scale from Bessemer process - but at half the rate since there are 6 harpoons -Bessemer process and rail gun scale at 0.1->0.07 +tech: coherence - past choices are added to all future tech + requires decoherence + research and cancel buttons have a sticky scroll positioning +eternalism: you can't pause while choosing, but you can otherwise pause now + 1.25->1.3 damage bugs - crash with training level "heal" and power ups - set difficulty mode level 2 for training + MIRV missiles now interact with time dilation properly ******************************************************** BUGS ******************************************************** @@ -65,48 +53,44 @@ procedural animation maybe no constraints on final boss and reactor? constraints balance - 50% JUNK chance - 4x shielded mob chance - power ups are sent to next level - +33% chance for mobs to respawn + 40% JUNK chance -1 choice + no health bars + 4x shielded mob chance + +33% chance for mobs to respawn 2x ammo costs - maybe nerf... + too hard 0 duplication + power ups in stasis + 0.1x damage after a power up + 0.5x energy regen 50% max energy 50% max health bots follow slow - 0.1x damage after a power up + periodically spawn WIMPs mob death heals mobs mobs heal for your lost health - periodically spawn WIMPs - 0.5x energy regen -each difficulty setting adds a chance for a random effect - make some effects only possible on certain levels, or with certain bosses? - not implemented random constraint ideas________________________ - mob death spawns something - mob bullets - bosses heals nearby mobs - ammo power ups give 0.7x ammo - 2x research costs - mobs slowly regen health - exit door takes 10x time to open, - and while door is opening (ghosters, suckers) attack? - can't pause while choosing tech, gun, field similar to eternalism - can't have more then 15 bullets - bots do 0.5x damage - remove 2 random tech and return them next level - too niche - player damage is 0.25x while player is invulnerable - all hazards: lasers and slime do 3x damage - player lasers and radiation do 0.5x damage - explosions do 0.5x damage - freeze effects last 0.25x time +not implemented random constraint ideas________________________ + mob death spawns something + mob bullets + bosses heals nearby mobs + ammo power ups give 0.7x ammo + 2x research costs + mobs slowly regen health + exit door takes 10x time to open, + and while door is opening (ghosters, suckers) attack? + can't have more then 15 bullets + how to code? + remove 2 random tech and return them next level + too niche + player damage is 0.25x while player is invulnerable + all hazards: lasers and slime do 3x damage + player lasers and radiation do 0.5x damage + explosions do 0.5x damage + freeze effects last 0.25x time -tech: - lower damage taken over 10s to 0x but after taking damage increase damage taken to 1x - isn't this just CPT skin with less steps? - maybe skin +tech: ice-VII - 1.5x duration for ice-IX tech: - freezing grenades/explosions @@ -117,28 +101,10 @@ tech: - randomize constraints somehow tech: - when you get a bot, get a second bot -tech: - boost power ups also give 0.1x damage taken - -tech: - tech have +3 choices to eject your tech - tech name - no description? - -copy negative-player as a boss? or a JUNK tech? - code is in community map (not sure which) - -harpoon tech: - after firing 4 harpoons your next harpoon has 4x damage - need to track number fired - tech: - after killing a Boss heal to full gain 3x damage for the rest of the level -tech: clicking on this tech in the pause menu will teleport you to the next level - -tech: - instead of reeling in grappling hook teleport to the hook after releasing field button - this might need another buff? - give damage immunity after teleport for 1+ seconds to balance - new level - rework testChamber skin with wheel instead of legs @@ -174,9 +140,6 @@ tech: atomic pile - lose 1 health if you are above the maximum energy do damage? plasma torch tech? -field tech: molecular assembler - every time you spawn a drone/spore/... become immune to damage for time - scales with how much energy was used to spawn drone/... - figure out how to put instructions for controls in background on initial level mouse smooth makes the text position jitter when it moves sub pixels hide the jitter with artificial jitter to make it seem intentional @@ -1392,6 +1355,8 @@ possible names for tech cryocoolers - freezing effects metaphysics - maybe this changes something deep and universal about physics? not sure cork - used as a heat shield for rockets + P = NP - something with speeding up calculation times + transistivity - something where a>b and b>c -> a>c ******************************************************* DESIGN ******************************************************