diff --git a/js/bullet.js b/js/bullet.js index 752a589..0f32794 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -397,7 +397,7 @@ const b = { //player damage if (Vector.magnitude(Vector.sub(where, player.position)) < radius) { - const DRAIN = (tech.isExplosionHarm ? 0.63 : 0.45) * (tech.isRadioactiveResistance ? 0.25 : 1) + const DRAIN = (tech.isExplosionHarm ? 0.6 : 0.45) * (tech.isRadioactiveResistance ? 0.25 : 1) if (m.immuneCycle < m.cycle) m.energy -= DRAIN if (m.energy < 0) { m.energy = 0 @@ -446,7 +446,7 @@ const b = { if (dist < radius) { if (simulation.dmgScale) { - const harm = tech.isExplosionHarm ? 0.07 : 0.05 + const harm = tech.isExplosionHarm ? 0.067 : 0.05 if (tech.isImmuneExplosion && m.energy > 0.25) { // const mitigate = Math.min(1, Math.max(1 - m.energy * 0.5, 0)) m.energy -= 0.25 @@ -3534,7 +3534,7 @@ const b = { restitution: 0, density: 0.0005, // 0.001 is normal density lookFrequency: 19 + Math.floor(7 * Math.random()), - endCycle: simulation.cycle + Math.floor((900 * tech.isBulletsLastLonger + 360 * Math.random()) + Math.max(0, 150 - bullet.length)), // 13 - 19s + endCycle: simulation.cycle + Math.floor((900 * tech.isBulletsLastLonger + 420 * Math.random()) + Math.max(0, 150 - bullet.length)), // 13 - 19s classType: "bullet", collisionFilter: { category: cat.bullet, @@ -3550,7 +3550,7 @@ const b = { }, beforeDmg(who) { Matter.Body.setVelocity(this, Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), 10 + 10 * Math.random())); //push away from target - this.endCycle -= 180 + this.endCycle -= 130 this.cd = simulation.cycle + this.delay; if (tech.isSporeFreeze) mobs.statusSlow(who, 90) if (tech.isSpawnBulletsOnDeath && who.alive && who.isDropPowerUp) { diff --git a/js/index.js b/js/index.js index 58adc99..24aad57 100644 --- a/js/index.js +++ b/js/index.js @@ -108,7 +108,7 @@ function getUrlVars() { window.addEventListener('load', () => { const set = getUrlVars() if (Object.keys(set).length !== 0) { - build.populateGrid() //trying to solve a bug with this, but maybe it doesn't help + // build.populateGrid() //trying to solve a bug with this, but maybe it doesn't help openExperimentMenu(); //add experimental selections based on url for (const property in set) { @@ -166,6 +166,8 @@ window.addEventListener('load', () => { // Math.seed = Math.abs(Math.hash(Math.initialSeed)) // level.populateLevels() // } + requestAnimationFrame(() => { build.sortTech('have', true) }); + } } else if (localSettings.isTrainingNotAttempted && localSettings.runCount < 30) { //make training button more obvious for new players // document.getElementById("training-button").style.border = "0px #333 solid"; @@ -457,7 +459,7 @@ ${simulation.isCheating ? "

lore disabled" : ""} - + `; // const style = (tech.isPauseEjectTech && !simulation.isChoosing) ? 'style="animation: techColorCycle 1s linear infinite alternate;"' : '' @@ -513,7 +515,7 @@ ${simulation.isCheating ? "

lore disabled" : ""} el.style.display = "grid" el.innerHTML = text }, - sortTech(find) { + sortTech(find, isExperiment = false) { const sortKeyword = (a, b) => { let aHasKeyword = (a.descriptionFunction ? a.descriptionFunction() : a.description).includes(find) || a.name.includes(find) let bHasKeyword = (b.descriptionFunction ? b.descriptionFunction() : b.description).includes(find) || b.name.includes(find) @@ -524,39 +526,89 @@ ${simulation.isCheating ? "

lore disabled" : ""} if (find === 'guntech') { tech.tech.sort((a, b) => { + if (a.isGunTech && b.isGunTech) { + if (a.allowed() > b.allowed()) return -1; //sort to the top + if (!a.allowed() < b.allowed()) return 1; //sort to the bottom + } if (a.isGunTech && !b.isGunTech) return -1; //sort to the top if (!a.isGunTech && b.isGunTech) return 1; //sort to the bottom return 0; }); } else if (find === 'fieldtech') { tech.tech.sort((a, b) => { + if (a.isFieldTech && b.isFieldTech) { + if (a.allowed() > b.allowed()) return -1; //sort to the top + if (!a.allowed() < b.allowed()) return 1; //sort to the bottom + } if (a.isFieldTech && !b.isFieldTech) return -1; //sort to the top if (!a.isFieldTech && b.isFieldTech) return 1; //sort to the bottom return 0; }); + } else if (find === 'allowed') { + tech.tech.sort((a, b) => { + if (a.allowed() > b.allowed()) return -1; //sort to the top + if (!a.allowed() < b.allowed()) return 1; //sort to the bottom + return 0; + }); + } else if (find === 'have') { + tech.tech.sort((a, b) => { + if (a.count > b.count) return -1; //sort to the top + if (!a.count < b.count) return 1; //sort to the bottom + return 0; + }); + } else if (find === 'heal') { + tech.tech.sort((a, b) => { + if (a.isHealTech && b.isHealTech) { + if (a.allowed() > b.allowed()) return -1; //sort to the top + if (!a.allowed() < b.allowed()) return 1; //sort to the bottom + } + if (a.isHealTech && !b.isHealTech) return -1; //sort to the top + if (!a.isHealTech && b.isHealTech) return 1; //sort to the bottom + return 0; + }); + } else if (find === 'bot') { + tech.tech.sort((a, b) => { + if (a.isBotTech && b.isBotTech) { + if (a.allowed() > b.allowed()) return -1; //sort to the top + if (!a.allowed() < b.allowed()) return 1; //sort to the bottom + } + if (a.isBotTech && !b.isBotTech) return -1; //sort to the top + if (!a.isBotTech && b.isBotTech) return 1; //sort to the bottom + return 0; + }); + } else if (document.getElementById("sort-input").value === 'skin') { + tech.tech.sort((a, b) => { + if (a.isSkin && b.isSkin) { + if (a.allowed() > b.allowed()) return -1; //sort to the top + if (!a.allowed() < b.allowed()) return 1; //sort to the bottom + } + if (a.isSkin && !b.isSkin) return -1; //sort to the top + if (!a.isSkin && b.isSkin) return 1; //sort to the bottom + return 0; + }); + } else if (document.getElementById("sort-input").value === 'junk') { + tech.tech.sort((a, b) => { + if (a.isJunk && !b.isJunk) return -1; //sort to the top + if (!a.isJunk && b.isJunk) return 1; //sort to the bottom + return 0; + }); } else if (find === 'damage') { tech.tech.sort(sortKeyword); } else if (find === 'defense') { tech.tech.sort(sortKeyword); } else if (find === 'energy') { tech.tech.sort(sortKeyword); - } else if (find === 'heal') { - tech.tech.sort((a, b) => { - if (a.isHealTech && !b.isHealTech) return -1; //sort to the top - if (!a.isHealTech && b.isHealTech) return 1; //sort to the bottom - return 0; - }); - } else if (find === 'bot') { - tech.tech.sort((a, b) => { - if (a.isBotTech && !b.isBotTech) return -1; //sort to the top - if (!a.isBotTech && b.isBotTech) return 1; //sort to the bottom - return 0; - }); } else if (find === 'input') { find = document.getElementById("sort-input").value; tech.tech.sort(sortKeyword); } - build.generatePauseRight() //makes the right side of the pause menu with the tech + if (isExperiment) { + build.populateGrid() + // build.updateExperimentText() + document.getElementById("tech-0").scrollIntoView(); //scroll to the first tech after sorting + } else { + build.generatePauseRight() //makes the right side of the pause menu with the tech + } document.getElementById("sort-input").value = find; //make the sorted string display in the keyword search input field }, unPauseGrid() { @@ -675,7 +727,9 @@ ${simulation.isCheating ? "

lore disabled" : ""} }, 50); } } - //update tech text + build.updateExperimentText(isAllowed) + }, + updateExperimentText(isAllowed = false) { for (let i = 0, len = tech.tech.length; i < len; i++) { const techID = document.getElementById("tech-" + i) if ((!tech.tech[i].isJunk || localSettings.isJunkExperiment) && !tech.tech[i].isLore) { @@ -726,69 +780,76 @@ ${simulation.isCheating ? "

lore disabled" : ""} }, populateGrid() { //background-color:var(--build-bg-color); let text = ` -
-
- - -
+
+
+ + + + + + + + +
- - -
+ +     + + +
- - - reset - - -     - - - share - - -
-
- - - start - - +
+
+ + + start + + +
+
+ + + reset + + +
+
+ + + share + + +
+
` const hideStyle = `style="height:auto; border: none; background-color: transparent;"` for (let i = 0, len = m.fieldUpgrades.length; i < len; i++) { const style = localSettings.isHideImages ? hideStyle : `style="background-image: url('img/field/${m.fieldUpgrades[i].name}${i === 0 ? m.fieldUpgrades[0].imageNumber : ""}.webp');"` - //original - // text += powerUps.fieldText(i, `build.choosePowerUp(this,${i},'field')`) - // text += `
  ${build.nameLink(m.fieldUpgrades[i].name)}
${m.fieldUpgrades[i].description}
` - text += `
+ text += `
  ${build.nameLink(m.fieldUpgrades[i].name)}
${m.fieldUpgrades[i].description}
` } for (let i = 0, len = b.guns.length; i < len; i++) { const style = localSettings.isHideImages ? hideStyle : `style="background-image: url('img/gun/${b.guns[i].name}.webp');"` - text += `
+ text += `
  ${build.nameLink(b.guns[i].name)}
${b.guns[i].description}
` - //original - // text += `
  ${build.nameLink(b.guns[i].name)}
${b.guns[i].description}
` } for (let i = 0, len = tech.tech.length; i < len; i++) { if ((!tech.tech[i].isJunk || localSettings.isJunkExperiment) && !tech.tech[i].isLore) { const style = (localSettings.isHideImages || tech.tech[i].isJunk) ? hideStyle : `style="background-image: url('img/${tech.tech[i].name}.webp');"` - if (tech.tech[i].allowed() && (!tech.tech[i].isNonRefundable || localSettings.isJunkExperiment)) { // || tech.tech[i].name === "+1 cardinality") { //|| tech.tech[i].name === "leveraged investment" - text += `
` + if ((tech.tech[i].allowed() || tech.tech[i].count > 0) && (!tech.tech[i].isNonRefundable || localSettings.isJunkExperiment)) { // || tech.tech[i].name === "+1 cardinality") { //|| tech.tech[i].name === "leveraged investment" + text += `
` } else { //disabled text += `
` - // text += `
` } if (tech.tech[i].isFieldTech) { @@ -806,6 +867,11 @@ ${simulation.isCheating ? "

lore disabled" : ""} } } document.getElementById("experiment-grid").innerHTML = text + // for (let i = 0, len = tech.tech.length; i < len; i++) { + // if (tech.tech[i].count) + // document.getElementById("tech-" + i).classList.add("build-tech-selected") + // } + document.getElementById("difficulty-select-experiment").value = document.getElementById("difficulty-select").value document.getElementById("difficulty-select-experiment").addEventListener("input", () => { simulation.difficultyMode = Number(document.getElementById("difficulty-select-experiment").value) @@ -821,6 +887,8 @@ ${simulation.isCheating ? "

lore disabled" : ""} // document.getElementById(`tech-${i}`).setAttribute('title', tech.tech[i].requires); //add tooltip } } + //highlight selected + }, nameLink(text) { //converts text into a clickable wikipedia search return `${text}` diff --git a/js/level.js b/js/level.js index 8188210..4d7bd77 100644 --- a/js/level.js +++ b/js/level.js @@ -10,7 +10,7 @@ const level = { // playableLevels: ["pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion"], //see level.populateLevels: (intro, ... , reservoir or factory, reactor, ... , gauntlet, final) added later playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock"], - communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass"], + communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass", "cantilever"], trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"], levels: [], start() { @@ -46,12 +46,7 @@ const level = { // for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); - // level.testing(); - // spawn.nodeGroup(3200, -300, "sniper") - // spawn.nodeGroup(2200, -300, "sniper") - // spawn.nodeGroup(2200, -300, "sniper") - // spawn.shareBoss(1900, -500) - // spawn.cellBoss(1900, -500) + // level.subway(); // for (let i = 0; i < 2; ++i) spawn.starter(1900, -500, 50) // spawn.sneaker(1900, -500, 25) // spawn.sniper(2000, -450) @@ -25187,6 +25182,70 @@ const level = { // spawn.secondaryBossChance(100, -1500) powerUps.addResearchToLevel() //needs to run after mobs are spawned }, + cantilever() { // made by Eclipse#7932 on discord, (TheSpudguy)(@PurpleSunsetGames on github) + // simulation.enableConstructMode(); + simulation.makeTextLog(`underpass by Eclipse#7932`); + + level.setPosToSpawn(0, -50); //normal spawn + level.exit.x = 5500; + level.exit.y = 950; + spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance + spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit + spawn.mapRect(level.exit.x - 50, level.exit.y + 30, 200, 100); // exit platform + spawn.mapRect(level.exit.x - 50, level.exit.y - 300, 200, 100); // exit platform roof + const endElevator = level.elevator(level.exit.x - 150, level.exit.y - 300, 100, 425, level.exit.y - 300); // end access door + + spawn.randomMob(-200, 350, Infinity); // random mob at the beginning + + spawn.mapRect(-100, 0, 600, 100); // main platform at start + spawn.bodyRect(0, 300, 50, 50); // little squares at start (one of these should be taken while crossing the cantilever to complete the level more easily) + spawn.bodyRect(100, 200, 50, 50); + spawn.bodyRect(50, 250, 50, 50); + spawn.mapRect(450, -20, 50, 20); // main platform ledge + spawn.mapRect(-200, 500, 2200, 100); // lower platform + spawn.mapRect(1850, 380, 100, 50); // cantilever block + spawn.bodyRect(80, -1300, 70, 1300, 1, { friction: .03, frictionAir: .001 }); // cantilever + + spawn.mapRect(3400, 500, 300, 100); // lever platform + spawn.mapRect(3650, 500, 100, 800); // pit + spawn.mapRect(3650, 1300, 2600, 100); + spawn.mapRect(6150, 600, 100, 800); + spawn.mapRect(5650, 600, 100, 650); + spawn.randomMob(4700, 550, Infinity); + spawn.randomMob(4700, 450, Infinity); + spawn.randomMob(4600, 550, Infinity); + + const toggle = level.toggle(3500, 500, false); // first lever + const button = level.button(5900, 1300); + const slidingWall = level.elevator(3750, -1200, 100, 1800, -1200); // first sliding wall + + level.defaultZoom = 1500; + simulation.zoomTransition(level.defaultZoom); + document.body.style.backgroundColor = "#d8badf"; + // color.map = "#444" //custom map color + + level.custom = () => { + level.exit.drawAndCheck(); + + level.enter.draw(); + }; + + level.customTopLayer = () => { + toggle.query(); + button.query(); + button.draw(); + + if (toggle.isOn) { + slidingWall.force.y -= 400; + } + if (!button.isUp) { + endElevator.force.y -= 100; + } + slidingWall.move(); + endElevator.move() + }; + powerUps.addResearchToLevel(); //needs to run after mobs are spawned + }, // ******************************************************************************************************** // ******************************************************************************************************** // ***************************************** training levels ********************************************** diff --git a/js/tech.js b/js/tech.js index c1d7aa8..b45c964 100644 --- a/js/tech.js +++ b/js/tech.js @@ -5432,7 +5432,7 @@ const tech = { }, { name: "acetone peroxide", - description: "+70% explosive radius
–40% explosive defense", + description: "+70% explosive radius
–33% explosive defense", isGunTech: true, maxCount: 1, count: 0, @@ -10413,7 +10413,6 @@ const tech = { maxCount: 1, count: 0, frequency: 0, - isSkin: true, isJunk: true, isNonRefundable: true, allowed() { @@ -10434,7 +10433,6 @@ const tech = { maxCount: 1, count: 0, frequency: 0, - isSkin: true, isJunk: true, allowed() { return !m.isShipMode @@ -10453,7 +10451,6 @@ const tech = { maxCount: 1, count: 0, frequency: 0, - isSkin: true, isJunk: true, allowed() { return !m.isShipMode @@ -10472,7 +10469,6 @@ const tech = { maxCount: 1, count: 0, frequency: 0, - isSkin: true, isJunk: true, allowed() { return !m.isShipMode @@ -10491,7 +10487,6 @@ const tech = { maxCount: 1, count: 0, frequency: 0, - isSkin: true, isJunk: true, allowed() { return true @@ -10510,7 +10505,6 @@ const tech = { maxCount: 1, count: 0, frequency: 0, - isSkin: true, isNonRefundable: true, isJunk: true, allowed() { diff --git a/style.css b/style.css index f21783e..3971c41 100644 --- a/style.css +++ b/style.css @@ -376,8 +376,8 @@ summary { top: 0; z-index: 10; align-self: start; - width: 195px; - line-height: 170%; + width: 276px; + line-height: 200%; display: flex; flex-direction: column; justify-content: center; @@ -389,7 +389,7 @@ summary { /* border-bottom-left-radius: 0px; */ border-top-right-radius: 0px; padding: 0.2em 0px; - height: 190px; + /* height: 210px; */ box-shadow: 8px 8px 7px rgba(0, 0, 50, 0.15); } diff --git a/todo.txt b/todo.txt index dd34c36..f6d76c9 100644 --- a/todo.txt +++ b/todo.txt @@ -1,17 +1,17 @@ ******************************************************** NEXT PATCH ************************************************** -pause menu can sort tech by keywords +new community level cantilever -tech: mechatronics - randomly add +(7 to 13)% damage - -a few new images -bug fixes - cherenkov radiation damage bug fixed it does much more damage and matches the description +extended tech sorting to experiment +acetone peroxide does 40->33% more explosion harm to player +fleas can do up to 30% more damage before they despawn *********************************************************** TODO ***************************************************** -extend sort to experiments +maybe reduce the fps on the line of sight graphics to make it look more like a sensor? +make a bot the follows the player the pov for line of sight levels, not the player + also need to make the vision a slice of a circle, not a full circle aperture also increases and decreases vision range I think messing with vision range causes problems with the start of level vision code @@ -31,10 +31,9 @@ mob non-combat behaviors, like Rain World play fight other mobs -maybe reduce the fps on the line of sight graphics to make it look more like a sensor? - consider increasing the base player horizontal movement maybe only increase ground movement, air control seems fine + would this unbalance any maps? level: subway - a map that uses the train level element and line of sight graphics stations