From 95adf9fa062bb7baee383363694dcec9f668047f Mon Sep 17 00:00:00 2001 From: landgreen Date: Mon, 12 Jul 2021 15:40:43 -0700 Subject: [PATCH] shieldingBoss shieldingBoss stops re-shielding after taking damage 25% more health re-shielding Cooldown is 25% shorter you can pick up ammo with laser again it was too annoying to switch guns you have 1/2 second harm immunity after leaving a portal lore conversations are better at recovering from speech API freezes (if the speech API doesn't work after 10 seconds it switches to pure text) --- .DS_Store | Bin 6148 -> 6148 bytes js/bullet.js | 18 ++--- js/index.js | 14 ++-- js/level.js | 35 ++++++--- js/lore.js | 200 ++++++++++++++++++----------------------------- js/mob.js | 1 + js/player.js | 15 ++-- js/simulation.js | 3 +- js/spawn.js | 22 +++--- js/tech.js | 23 ++++-- todo.txt | 47 +++++------ 11 files changed, 170 insertions(+), 208 deletions(-) diff --git a/.DS_Store b/.DS_Store index af8396edf422cdfb0b03ba851b5108f318f11406..95d2850068c096ede5f66a1709d0c748618b986d 100644 GIT binary patch delta 21 ccmZoMXffEJ#muy4(PSNFKgJE4tC>4R08r-#H2?qr delta 21 ccmZoMXffEJ#msb|f3gm 1 || powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { //draw pickup for a single cycle ctx.beginPath(); @@ -2149,8 +2149,8 @@ const b = { for (let i = 0, len = powerUp.length; i < len; ++i) { if ( (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) && - (powerUp[i].name !== "field" || !tech.isDeterminism) && - (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) + (powerUp[i].name !== "field" || !tech.isDeterminism) + // &&(b.inventory.length > 1 || powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) { //draw pickup for a single cycle @@ -2334,8 +2334,8 @@ const b = { if ( Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) && - (powerUp[i].name !== "field" || !tech.isDeterminism) && - (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) + (powerUp[i].name !== "field" || !tech.isDeterminism) + // &&(powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { //draw pickup for a single cycle ctx.beginPath(); @@ -2366,8 +2366,8 @@ const b = { for (let i = 0, len = powerUp.length; i < len; ++i) { if ( (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) && - (powerUp[i].name !== "field" || !tech.isDeterminism) && - (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) + (powerUp[i].name !== "field" || !tech.isDeterminism) + // &&(powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) { //draw pickup for a single cycle @@ -4032,7 +4032,7 @@ const b = { ctx.lineTo(vertices[j].x + vibe * (Math.random() - 0.5), vertices[j].y + vibe * (Math.random() - 0.5)); } ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); - const damage = 1.75 * b.dmgScale * tech.waveBeamDamage * tech.wavePacketDamage / Math.sqrt(who.radius) //damage is lower for large radius mobs, since they feel the waves longer + const damage = 1.9 * b.dmgScale * tech.waveBeamDamage * tech.wavePacketDamage / Math.sqrt(who.radius) //damage is lower for large radius mobs, since they feel the waves longer who.locatePlayer(); who.damage(damage); } diff --git a/js/index.js b/js/index.js index 805ae6b..756573d 100644 --- a/js/index.js +++ b/js/index.js @@ -212,11 +212,10 @@ const build = {
damage difficulty scale: ${(b.dmgScale*100).toFixed(2) }%
harm difficulty scale: ${(simulation.dmgScale*100).toFixed(0)}%
heal difficulty scale: ${(simulation.healScale*100).toFixed(1)}% -
- - copy build url - - +
+ + copy build url + `; for (let i = 0, len = b.inventory.length; i < len; i++) { text += `
  ${b.guns[b.inventory[i]].name} - ${b.guns[b.inventory[i]].ammo}
${b.guns[b.inventory[i]].description}
` @@ -257,6 +256,11 @@ const build = { text += `
${tech.tech[i].name}
${tech.tech[i].description}
` } } + + + // text +=`` + + el = document.getElementById("pause-grid-right") el.style.display = "grid" el.innerHTML = text diff --git a/js/level.js b/js/level.js index 813aaaa..ad4a727 100644 --- a/js/level.js +++ b/js/level.js @@ -25,11 +25,11 @@ const level = { // for (let i = 0; i < 3; i++) tech.giveTech("packet length") level.intro(); //starting level - // level.labs(); // level.testing(); //not in rotation, used for testing // level.template(); //not in rotation, blank start new map development // level.final() //final boss level // level.gauntlet(); //before final boss level + // level.labs(); //always before gauntlet level // level.testChamber() // level.sewers(); // level.satellite(); @@ -113,24 +113,24 @@ const level = { difficultyIncrease(num = 1) { for (let i = 0; i < num; i++) { simulation.difficulty++ - b.dmgScale *= 0.91; //damage done by player decreases each level + b.dmgScale *= 0.915; //damage done by player decreases each level if (simulation.accelScale < 5) simulation.accelScale *= 1.02 //mob acceleration increases each level if (simulation.lookFreqScale > 0.2) simulation.lookFreqScale *= 0.98 //mob cycles between looks decreases each level if (simulation.CDScale > 0.2) simulation.CDScale *= 0.97 //mob CD time decreases each level } - simulation.dmgScale = 0.4 * simulation.difficulty //damage done by mobs increases each level + simulation.dmgScale = 0.39 * simulation.difficulty //damage done by mobs increases each level simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale; }, difficultyDecrease(num = 1) { //used in easy mode for simulation.reset() for (let i = 0; i < num; i++) { simulation.difficulty-- - b.dmgScale /= 0.91; //damage done by player decreases each level + b.dmgScale /= 0.915; //damage done by player decreases each level if (simulation.accelScale > 0.2) simulation.accelScale /= 1.02 //mob acceleration increases each level if (simulation.lookFreqScale < 5) simulation.lookFreqScale /= 0.98 //mob cycles between looks decreases each level if (simulation.CDScale < 5) simulation.CDScale /= 0.97 //mob CD time decreases each level } if (simulation.difficulty < 1) simulation.difficulty = 0; - simulation.dmgScale = 0.4 * simulation.difficulty //damage done by mobs increases each level + simulation.dmgScale = 0.39 * simulation.difficulty //damage done by mobs increases each level if (simulation.dmgScale < 0.1) simulation.dmgScale = 0.1; simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) }, @@ -754,8 +754,10 @@ const level = { player.isInPortal = this.portalPair //teleport if (this.portalPair.angle % (Math.PI / 2)) { //if left, right up or down + if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles Matter.Body.setPosition(player, this.portalPair.portal.position); } else { //if at some odd angle + if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles Matter.Body.setPosition(player, this.portalPair.position); } //rotate velocity @@ -2085,6 +2087,7 @@ const level = { level.levels.pop(); //remove lore level from rotation //start a conversation based on the number of conversations seen if (localSettings.loreCount < lore.conversation.length && !simulation.isCheating) { + 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 lore.conversation[lore.chapter][lore.sentence]() @@ -2248,9 +2251,9 @@ const level = { spawn.mapRect(6700, -1800, 800, 2600); //right wall spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump - spawn.starter(1900, -500, 200) //big boy + // spawn.starter(1900, -500, 200) //big boy // spawn.pulseShooter(1900, -500) - // spawn.pulsarBoss(1900, -500) + spawn.shieldingBoss(1900, -500) // spawn.grenadierBoss(1900, -500) // spawn.shieldingBoss(1900, -500) @@ -4194,13 +4197,11 @@ const level = { spawn.mapRect(425, -20, 100, 25); // spawn.mapRect(-1900, 600, 2700, 100); spawn.mapRect(1100, 0, 150, 1500); - spawn.mapRect(-2850, 1400, 4100, 100); + spawn.mapRect(-3150, 1400, 4400, 100); spawn.mapRect(-2375, 875, 1775, 75); spawn.mapRect(-1450, 865, 75, 435); spawn.mapRect(-1450, 662, 75, 100); spawn.bodyRect(-1418, 773, 11, 102, 1, spawn.propsFriction); //blocking path - spawn.mapRect(-2950, 1250, 175, 250); - spawn.mapRect(-3050, 1100, 150, 400); spawn.mapRect(-3150, 50, 125, 1450); spawn.mapRect(-2350, 600, 3150, 100); spawn.mapRect(-2125, 400, 250, 275); @@ -4212,13 +4213,20 @@ const level = { let elevator1, elevator2, elevator3 if (Math.random() < 0.5) { isElevators = true - elevator1 = level.elevator(-1780, 500, 260, 40, 7, 0.0003) + elevator1 = level.elevator(-1780, 500, 260, 40, 7, 0.0003) // elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { elevator2 = level.elevator(820, 1300, 260, 40, 607, 0.0003) - elevator3 = level.elevator(-2755, 1260, 160, 40, 850, 0.003) + elevator3 = level.elevator(-2850, 1300, 160, 40, 700, 0.007) + if (simulation.isHorizontalFlipped) { + spawn.mapVertex(-2900, 225, "0 0 0 -500 -500 -500") + } else { + spawn.mapVertex(-2900, 225, "0 0 0 -500 500 -500") + } + spawn.mapRect(-3050, 1275, 175, 200); spawn.bodyRect(-2375, 1300, 100, 100); spawn.bodyRect(-2325, 1250, 50, 50); spawn.bodyRect(-2275, 1350, 125, 50); + level.custom = () => { elevator1.move(); elevator1.drawTrack(); @@ -4241,6 +4249,9 @@ const level = { level.enter.draw(); }; } else { + spawn.mapRect(-2950, 1250, 175, 250); + spawn.mapRect(-3050, 1100, 150, 400); + spawn.bodyRect(-1450, -125, 125, 125, 1, spawn.propsSlide); //weight spawn.bodyRect(-1800, 0, 300, 100, 1, spawn.propsHoist); //hoist cons[cons.length] = Constraint.create({ diff --git a/js/lore.js b/js/lore.js index adee782..387b327 100644 --- a/js/lore.js +++ b/js/lore.js @@ -2,70 +2,17 @@ const lore = { techCount: 0, techGoal: 7, talkingColor: "#dff", //set color of graphic on level.null - // anand: { - // color: "#e0c", - // text: function(say, isSpeech = false) { - // 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); - // utterance.lang = "en-IN"; - // utterance.volume = 0.2; // 0 to 1 - // speechSynthesis.speak(utterance); - // } - // }, - // miriamOld: { - // color: "#f20", - // text: function(say, isSpeech = false) { - // 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); - // utterance.lang = "en-AU"; - // utterance.volume = 0.2; // 0 to 1 - // speechSynthesis.speak(utterance); - // } - // }, - - // voices = synth.getVoices(); - - // for(i = 0; i < voices.length ; i++) { - // var option = document.createElement('option'); - // option.textContent = voices[i].name + ' (' + voices[i].lang + ')'; - - // if(voices[i].default) { - // option.textContent += ' -- DEFAULT'; - // } - - // option.setAttribute('data-lang', voices[i].lang); - // option.setAttribute('data-name', voices[i].name); - // voiceSelect.appendChild(option); - // } - // setVoices() { - // window.speechSynthesis.onvoiceschanged = () => { - // const synth = window.speechSynthesis - // console.log(synth.getVoices()) - // const voiceArray = synth.getVoices() - // lore.anand.voice = voiceArray[0] - // lore.miriam.voice = voiceArray[1] - // console.log(voiceArray[0], voiceArray[1]) - // }; - // // console.log('before') - // // if ('speechSynthesis' in window) { - - // // } else { - // // console.log('Text-to-speech not supported.'); - // // } - // }, + isSpeech: false, + testSpeechAPI() { + if ('speechSynthesis' in window) { // Synthesis support. Make your web apps talk! + lore.isSpeech = true + } + }, rate: 1, // //utterance.rate = 1; // 0.1 to 10 + nextSentence() { + lore.sentence++ + if (m.alive) lore.conversation[lore.chapter][lore.sentence]() //go to next sentence in the chapter and play it + }, anand: { color: "#e0c", voice: undefined, @@ -73,25 +20,28 @@ const lore = { 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 - const utterance = new SpeechSynthesisUtterance(say); - // utterance.voice = lore.anand.voice - utterance.lang = "en-GB" //"en-IN"; //de-DE en-GB fr-FR en-US en-AU - utterance.volume = 0.2; // 0 to 1 - // if (lore.rate !== 1) utterance.rate = lore.rate - speechSynthesis.speak(utterance); - utterance.onerror = (event) => { //if speech doesn't work try again without the lang set - console.log("speech error", event.error) + if (lore.isSpeech) { const utterance = new SpeechSynthesisUtterance(say); + // utterance.voice = lore.anand.voice + utterance.lang = "en-GB" //"en-IN"; //de-DE en-GB fr-FR en-US en-AU utterance.volume = 0.2; // 0 to 1 + // if (lore.rate !== 1) utterance.rate = lore.rate speechSynthesis.speak(utterance); - utterance.onend = () => { - lore.sentence++ - if (m.alive) lore.conversation[lore.chapter][lore.sentence]() //go to next sentence in the chapter and play it + utterance.onerror = () => { //if speech doesn't work + lore.isSpeech = false + lore.nextSentence() } - } - utterance.onend = () => { - lore.sentence++ - if (m.alive) lore.conversation[lore.chapter][lore.sentence]() //go to next sentence in the chapter and play it + speechFrozen = setTimeout(function() { // speech frozen after 10 seconds of no end + console.log('speech frozen') + lore.isSpeech = false + lore.nextSentence() + }, 20000); + utterance.onend = () => { + clearTimeout(speechFrozen); + lore.nextSentence() + } + } else { + setTimeout(() => { lore.nextSentence() }, 3000); } } }, @@ -102,54 +52,47 @@ const lore = { 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 - utterance = new SpeechSynthesisUtterance(say); - // utterance.voice = lore.anand.voice - utterance.lang = "en-AU"; - utterance.volume = 0.2; // 0 to 1 - // if (lore.rate !== 1) utterance.rate = lore.rate - speechSynthesis.speak(utterance); - utterance.onerror = (event) => { //if speech doesn't work try again without the lang set - console.log("speech error", event.error) - const utterance = new SpeechSynthesisUtterance(say); + if (lore.isSpeech) { + utterance = new SpeechSynthesisUtterance(say); + // utterance.voice = lore.anand.voice + utterance.lang = "en-AU"; utterance.volume = 0.2; // 0 to 1 + // if (lore.rate !== 1) utterance.rate = lore.rate speechSynthesis.speak(utterance); - utterance.onend = () => { - lore.sentence++ - if (m.alive) lore.conversation[lore.chapter][lore.sentence]() //go to next sentence in the chapter and play it + utterance.onerror = () => { //if speech doesn't work + lore.isSpeech = false + lore.nextSentence() } - } - utterance.onend = () => { - lore.sentence++ - if (m.alive) lore.conversation[lore.chapter][lore.sentence]() //go to next sentence in the chapter and play it + speechFrozen = setTimeout(function() { // speech frozen after 10 seconds of no end + console.log('speech frozen') + lore.isSpeech = false + lore.nextSentence() + }, 20000); + utterance.onend = () => { + clearTimeout(speechFrozen); + lore.nextSentence() + } + } else { + setTimeout(() => { lore.nextSentence() }, 3000); } } }, }, - - // utterance.onerror = (event) => { //if speech is still not working, just do text - // console.log("speech error", event.error) - // lore.sentence++ - // if (m.alive) lore.conversation[lore.chapter][lore.sentence]() //go to next sentence in the chapter and play it - // } - // setTimeout(() => {}, 2000); - // lore.miriam.text("") - // lore.miriam.utterance.addEventListener('end', () => { - // }) chapter: 0, //what part of the conversation is playing sentence: 0, //what part of the conversation is playing conversation: [ [ //first time they meet, and testing gets unlocked - () => { - lore.unlockTesting(); - setTimeout(() => { lore.miriam.text("I've never seen it generate this level before.") }, 5000); - }, + () => { setTimeout(() => { lore.miriam.text("I've never seen it generate this level before.") }, 5000); }, () => { lore.anand.text("Wow. Just a platform.") }, () => { lore.miriam.text("And that thing...") }, () => { lore.anand.text("Weird") }, () => { lore.anand.text("Maybe it's trapped.") }, () => { lore.miriam.text("Looks like testing mode is locked.") }, () => { lore.miriam.text("I'll unlock it with the console command.") }, - () => { setTimeout(() => { lore.miriam.text("Hey little bot! Just press 'T' to enter testing mode and 'U' to go to the next level.") }, 1000); }, + () => { + lore.unlockTesting(); + setTimeout(() => { lore.miriam.text("Hey little bot! Just press 'T' to enter testing mode and 'U' to go to the next level.") }, 1000); + }, () => { lore.anand.text("It can't process what you're saying.") }, () => { lore.miriam.text("ha hahahaha. I know, but it does seem to be getting smarter.") }, () => { @@ -373,7 +316,7 @@ const lore = { localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage document.getElementById("control-testing").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible" document.getElementById("experiment-button").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible" - simulation.makeTextLog(`lore.unlockTesting.()`, Infinity); + simulation.makeTextLog(`lore.unlockTesting()`, Infinity); //setup audio context function tone(frequency, gain = 0.05, end = 1300) { @@ -402,8 +345,6 @@ const lore = { } - - // How to get to the console in chrome: // Press either CTRL + SHIFT + I or F12 or Option + ⌘ + J on a Mac // Press ESC (or click on “Show console” in the bottom right corner) to slide the console up. @@ -430,16 +371,25 @@ const lore = { // utterance.lang = "en-GB"; // speechSynthesis.speak(utterance); // } -{ - /* - - - - - - - - - - */ -} \ No newline at end of file + +/* + + + + + + + + + + */ + + +// The API also allows you to get a list of voice the engine supports: +// speechSynthesis.getVoices().forEach(function(voice) { +// console.log(voice.name, voice.default ? voice.default :''); +// }); +// Then set a different voice, by setting .voice on the utterance object: +// var msg = new SpeechSynthesisUtterance('I see dead people!'); +// msg.voice = speechSynthesis.getVoices().filter(function(voice) { return voice.name == 'Whisper'; })[0]; +// speechSynthesis.speak(msg); \ No newline at end of file diff --git a/js/mob.js b/js/mob.js index 58acfa0..195f36a 100644 --- a/js/mob.js +++ b/js/mob.js @@ -122,6 +122,7 @@ const mobs = { x: who.position.x + 100 * (Math.random() - 0.5), y: who.position.y + 100 * (Math.random() - 0.5) } + // && !who.isBoss if (who.velocity.y < 2) who.force.y += who.mass * 0.0004 //extra gravity //draw health bar diff --git a/js/player.js b/js/player.js index df0d6a7..42d0274 100644 --- a/js/player.js +++ b/js/player.js @@ -497,7 +497,7 @@ const m = { if (tech.healthDrain) dmg *= 1 + 2.667 * tech.healthDrain //tech.healthDrain = 0.03 at one stack //cause more damage if (tech.squirrelFx !== 1) dmg *= 1 + (tech.squirrelFx - 1) / 5 //cause more damage if (tech.isBlockHarm && m.isHolding) dmg *= 0.15 - if (tech.isSpeedHarm) dmg *= 1 - Math.min(player.speed * 0.022, 0.66) + if (tech.isSpeedHarm) dmg *= 1 - Math.min(player.speed * 0.0165, 0.66) if (tech.isSlowFPS) dmg *= 0.8 // if (tech.isPiezo) dmg *= 0.85 if (tech.isHarmReduce && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.4 @@ -1250,8 +1250,7 @@ const m = { if ( //use power up if it is close enough dist2 < 5000 && !simulation.isChoosing && - (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal) && - (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity) + (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal) ) { powerUps.onPickUp(powerUp[i]); Matter.Body.setVelocity(player, { //player knock back, after grabbing power up @@ -2068,15 +2067,15 @@ const m = { } if (tech.isCloakStun) { //stun nearby mobs after exiting cloak let isMobsAround = false - const stunRange = m.fieldDrawRadius * 1.2 - const drain = 0.3 * m.energy + const stunRange = m.fieldDrawRadius * 1.3 + const drain = 0.25 * m.energy for (let i = 0, len = mob.length; i < len; ++i) { if ( Vector.magnitude(Vector.sub(mob[i].position, m.pos)) < stunRange && Matter.Query.ray(map, mob[i].position, m.pos).length === 0 ) { isMobsAround = true - mobs.statusStun(mob[i], 60 + drain * 360) + mobs.statusStun(mob[i], 120 + drain * 360) } } if (isMobsAround && m.energy > drain) { @@ -2385,8 +2384,8 @@ const m = { if ( dist2 < 5000 && !simulation.isChoosing && - (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth) && - (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity) + (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth) + // (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity) ) { //use power up if it is close enough powerUps.onPickUp(powerUp[i]); powerUp[i].effect(); diff --git a/js/simulation.js b/js/simulation.js index 4806749..7537530 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -54,6 +54,7 @@ const simulation = { simulation.camera(); level.custom(); m.draw(); + m.hold(); level.customTopLayer(); simulation.draw.wireFrame(); simulation.draw.cons(); @@ -109,7 +110,7 @@ const simulation = { fpsCapDefault: 72, //use to change fpsCap back to normal after a hit from a mob isCommunityMaps: false, cyclePaused: 0, - fallHeight: 3000, //below this y position the player dies + fallHeight: 5000, //below this y position the player dies lastTimeStamp: 0, //tracks time stamps for measuring delta delta: 1000 / 60, //speed of game engine //looks like it has to be 16 to match player input buttonCD: 0, diff --git a/js/spawn.js b/js/spawn.js index 0ab5db1..0308088 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -3293,7 +3293,7 @@ const spawn = { // me.stroke = "rgb(220,220,255)" me.isBoss = true; me.cycle = 0 - me.maxCycles = 150; + me.maxCycles = 120; me.frictionStatic = 0; me.friction = 0; me.frictionAir = 0.5; @@ -3301,17 +3301,18 @@ const spawn = { spawn.shield(me, x, y, 1); spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random()) - Matter.Body.setDensity(me, 0.003); //extra dense //normal is 0.001 //makes effective life much larger + Matter.Body.setDensity(me, 0.004); //extra dense //normal is 0.001 //makes effective life much larger me.onDeath = function() { powerUps.spawnBossPowerUp(this.position.x, this.position.y) // this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //helps collisions functions work better after vertex have been changed }; - me.onDamage = function() {}; + me.onDamage = function() { + this.cycle = 0 + }; me.do = function() { this.checkStatus(); - //draw cycle timer - ctx.beginPath(); + ctx.beginPath(); //draw cycle timer ctx.moveTo(this.vertices[this.vertices.length - 1].x, this.vertices[this.vertices.length - 1].y) const phase = (this.vertices.length + 1) * this.cycle / this.maxCycles if (phase > 1) ctx.lineTo(this.vertices[0].x, this.vertices[0].y) @@ -3336,13 +3337,8 @@ const spawn = { } if (!this.isShielded && this.alive) spawn.shield(this, this.position.x, this.position.y, 1, true); ctx.lineWidth = 20 - // ctx.lineCap = "round"; - ctx.strokeStyle = "rgba(200,200,255,0.9)" + ctx.strokeStyle = "rgb(200,200,255)" ctx.stroke(); - //return to starting location - // const sub = Vector.sub(this.homePosition, this.position) - // const dist = Vector.magnitude(sub) - // if (dist > 350) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.05) } } }; @@ -3827,8 +3823,8 @@ const spawn = { me.stroke = "transparent"; //used for drawGhost me.seeAtDistance2 = 2000000; me.memory = Infinity; - me.frictionAir = 0.01; - me.accelMag = 0.00003 * simulation.accelScale; + me.frictionAir = 0.02; + me.accelMag = 0.00014 * Math.sqrt(simulation.accelScale) me.collisionFilter.mask = cat.player | cat.bullet //| cat.body spawn.shield(me, x, y, 1); diff --git a/js/tech.js b/js/tech.js index ccf0d07..bfed355 100644 --- a/js/tech.js +++ b/js/tech.js @@ -172,7 +172,7 @@ if (tech.isRerollDamage) dmg *= 1 + 0.042 * powerUps.research.count if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.3 if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2 - if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.66, player.speed * 0.022) + if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.66, player.speed * 0.0165) if (tech.isBotDamage) dmg *= 1 + 0.06 * b.totalBots() return dmg * tech.slowFire * tech.aimDamage }, @@ -528,7 +528,7 @@ }, requires: "not mass-energy equivalence", effect() { - tech.isSpeedHarm = true + tech.isSpeedHarm = true //max at speed = 40 }, remove() { tech.isSpeedHarm = false @@ -546,7 +546,7 @@ }, requires: "", effect() { - tech.isSpeedDamage = true + tech.isSpeedDamage = true //max at speed = 40 }, remove() { tech.isSpeedDamage = false @@ -4929,6 +4929,7 @@ remove() { tech.harmonicEnergy = 0; m.setMaxEnergy() + if (this.count > 0) powerUps.research.changeRerolls(2) } }, { @@ -5071,6 +5072,7 @@ }, remove() { tech.isFieldHarmReduction = false + if (this.count > 0) powerUps.research.changeRerolls(4) } }, { @@ -5274,6 +5276,7 @@ }, remove() { tech.isSporeField = false; + if (this.count > 0) powerUps.research.changeRerolls(3) } }, { @@ -5298,6 +5301,7 @@ }, remove() { tech.isMissileField = false; + if (this.count > 0) powerUps.research.changeRerolls(3) } }, { @@ -5322,6 +5326,7 @@ }, remove() { tech.isIceField = false; + if (this.count > 0) powerUps.research.changeRerolls(3) } }, { @@ -5386,6 +5391,7 @@ tech.plasmaBotCount = 0; b.clearPermanentBots(); b.respawnBots(); + if (this.count > 0) powerUps.research.changeRerolls(1) } }, { @@ -5490,6 +5496,7 @@ tech.isFastTime = false m.setMovement(); b.setFireCD(); + if (this.count > 0) powerUps.research.changeRerolls(3) } }, { @@ -5534,7 +5541,7 @@ }, { name: "dazzler", - description: "decloaking stuns nearby mobs
drains 30% of your stored energy", + description: "decloaking stuns nearby mobs
drains 25% of your stored energy", isFieldTech: true, maxCount: 1, count: 0, @@ -5571,6 +5578,7 @@ }, remove() { tech.isCloakingDamage = false + if (this.count > 0) powerUps.research.changeRerolls(1) } }, { @@ -5615,7 +5623,7 @@ }, { name: "WIMPs", - description: "a harmful particle slowly chases you
spawn 3-9 research at the end of each level", + description: "at the end of each level spawn 3-9 research
and a harmful particle that slowly chases you", isFieldTech: true, maxCount: 9, count: 0, @@ -5627,6 +5635,8 @@ requires: "wormhole", effect: () => { tech.wimpCount++ + spawn.WIMP() + for (let j = 0, len = 1 + 5 * Math.random(); j < len; j++) powerUps.spawn(level.exit.x + 100 * (Math.random() - 0.5), level.exit.y - 100 + 100 * (Math.random() - 0.5), "research", false) }, remove() { tech.wimpCount = 0 @@ -5653,7 +5663,7 @@ }, { name: "virtual particles", - description: "use 3 research to exploit your wormhole for
19% chance to duplicate spawned power ups", + description: "use 3 research to exploit your wormhole for a
19% chance to duplicate spawned power ups", isFieldTech: true, maxCount: 1, count: 0, @@ -5673,6 +5683,7 @@ remove() { tech.wormDuplicate = 0 powerUps.setDo(); //needed after adjusting duplication chance + if (this.count > 0) powerUps.research.changeRerolls(3) } }, { diff --git a/todo.txt b/todo.txt index 3a83850..68eafff 100644 --- a/todo.txt +++ b/todo.txt @@ -1,46 +1,33 @@ ******************************************************** NEXT PATCH ******************************************************** -tech: Noether violation - shotgun and railgun recoil is increased and it's direction is reversed, +60% damage for shot/rail gun +shieldingBoss stops re-shielding after taking damage + 25% more health + re-shielding Cooldown is 25% shorter -each field now has a tech that uses research to give a simple bonus - wormhole: virtual particles - 3 research for 19% duplication chance - cloaking field, pilot wave: dynamical systems - 2 research for 35% damage - standing wave harmonics, pilot wave: zero point energy - 2 research for 74% max energy - perfect diamagnetism or negative mass field: tessellation - 50% harm reduction for 4 research cost - time dilation field - Lorentz transformation now uses 4 research for a 50% speed increase (was 40% for no research) - plasma-bot - now also requires 1 research - nano-scale already has several research deals +you can pick up ammo with laser again + it was too annoying to switch guns -added a research to the intro level -Newton's 1st law reduces harm by up to 66% (was 60%) when moving at up to 30 -Newton's 2nd law increases damage by up to 66% (was 43%) when moving at up to 30 - also they both have no requirements anymore -super ball tech supertemporal now fires with much less delay - and it syncs with frame rate much cleaner -metamaterial cloaking - now gets the damage buff after 3 seconds of no kills (was 4s) - recloaks 1/2 second faster - cloaked vision has a 10% larger radius -6 situational tech can now show up in situations where they are only "OK", but not "great" choices +you have 1/2 second harm immunity after leaving a portal + +lore conversations are better at recovering from speech API freezes + (if the speech API doesn't work after 10 seconds it switches to pure text) ******************************************************** TODO ******************************************************** -undo the research lost when you refund researched tech??? - this only really matters for many worlds type runs, would yield an general research drain? +so JUNK tech in experiment mode? + +new wave tech - reduce range, but make bullets circles, not arcs + +scrolling console history in pause menu? + also make tech, guns scrolling? consider executables: press F to do things ideas: -at the start of the null level use speech API to say something short, - if the on end event runs set the lore.isVoiceWorking flag to be true - if lore.isVoiceWorking is false, skip voice and just move through each sentence with a short delay - make the player get a buff after using wormhole while energy lasts: drain energy and give damage buff -tech pressure wave - reduce range, but make bullets circles, not arcs - tech: quantized shields - harmonic standing wave field can only lose 33 energy per hit draw 1,2,3 levels of the field based on energy? the blocked value only scales up to 2x or 4x (33 energy) blocked @@ -100,7 +87,7 @@ mobile requirements: tap screen regions to move (WASD) reduce font size -add back in gamepad support +add back in gamepad support? but does anyone care? https://github.com/landgreen/landgreen.github.io/search?q=gamepadconnected @@ -207,6 +194,8 @@ n-gon outreach ideas ******************************************************** BUGS ******************************************************** +ants marching outline doesn't sync right on safari anymore. + door to exit in vats does nothing did I do that?