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)
This commit is contained in:
landgreen
2021-07-12 15:40:43 -07:00
parent b5dd456db0
commit 95adf9fa06
11 changed files with 170 additions and 208 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -2118,8 +2118,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)
// &&(b.inventory.length > 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);
}

View File

@@ -212,11 +212,10 @@ const build = {
<br>damage difficulty scale: ${(b.dmgScale*100).toFixed(2) }%
<br>harm difficulty scale: ${(simulation.dmgScale*100).toFixed(0)}%
<br>heal difficulty scale: ${(simulation.healScale*100).toFixed(1)}%
<br><svg class="SVG-button" onclick="build.shareURL(false)" width="110" height="25" style="padding:2px; margin: 10px;">
<g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif">
<text x="5" y="18">copy build url</text>
</g>
</svg>
<br>
<svg class="SVG-button" onclick="build.shareURL(false)" width="110" height="25" style="padding:2px; margin: 10px;">
<g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif"> <text x="5" y="18">copy build url</text> </g>
</svg>
</div>`;
for (let i = 0, len = b.inventory.length; i < len; i++) {
text += `<div class="pause-grid-module"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[b.inventory[i]].name} - <span style="font-size:100%;font-weight: 100;">${b.guns[b.inventory[i]].ammo}</span></div> ${b.guns[b.inventory[i]].description}</div>`
@@ -257,6 +256,11 @@ const build = {
text += `<div class="pause-grid-module" style="text-decoration: line-through;"><div class="grid-title">${tech.tech[i].name}</div>${tech.tech[i].description}</div></div>`
}
}
// text +=``
el = document.getElementById("pause-grid-right")
el.style.display = "grid"
el.innerHTML = text

View File

@@ -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({

View File

@@ -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(<span style="color:#888; font-size: 70%;">${Date.now()} ms</span>)<span class='color-symbol'>:</span> "<span style="color:${this.color};">${say}</span>"`, 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(<span style="color:#888; font-size: 70%;">${Date.now()} ms</span>)<span class='color-symbol'>:</span> "<span style="color:${this.color};">${say}</span>"`, 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(<span style="color:#888; font-size: 70%;">${Date.now()} ms</span>)<span class='color-symbol'>:</span> "<span style="color:${this.color};">${say}</span>"`, 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(<span style="color:#888; font-size: 70%;">${Date.now()} ms</span>)<span class='color-symbol'>:</span> "<span style="color:${this.color};">${say}</span>"`, 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(`<span class='color-var'>lore</span>.unlockTesting.()`, Infinity);
simulation.makeTextLog(`<span class='color-var'>lore</span>.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);
// }
{
/* <option value="en-GB">GB</option>
<option value="en-US">US</option>
<option value="en-AU">AU</option>
<option value="fr-FR">FR</option>
<option value="de-DE">DE</option>
<option value="en-IN">IN</option>
<option value="zh-CN">CN</option>
<option value="pl">PL</option>
<option value="ru">RU</option>
<option value="sv-SE">SE</option>
<option value="en-ZA">ZA</option> */
}
/* <option value="en-GB">GB</option>
<option value="en-US">US</option>
<option value="en-AU">AU</option>
<option value="fr-FR">FR</option>
<option value="de-DE">DE</option>
<option value="en-IN">IN</option>
<option value="zh-CN">CN</option>
<option value="pl">PL</option>
<option value="ru">RU</option>
<option value="sv-SE">SE</option>
<option value="en-ZA">ZA</option> */
// 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);

View File

@@ -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

View File

@@ -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();

View File

@@ -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,

View File

@@ -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);

View File

@@ -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: "<strong class='color-cloaked'>decloaking</strong> <strong>stuns</strong> nearby mobs<br>drains <strong>30%</strong> of your stored <strong class='color-f'>energy</strong>",
description: "<strong class='color-cloaked'>decloaking</strong> <strong>stuns</strong> nearby mobs<br>drains <strong>25%</strong> of your stored <strong class='color-f'>energy</strong>",
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 <strong class='color-harm'>harmful</strong> particle slowly <strong>chases</strong> you<br>spawn <strong>3-9</strong> <strong class='color-r'>research</strong> at the end of each <strong>level</strong>",
description: "at the end of each <strong>level</strong> spawn <strong>3-9</strong> <strong class='color-r'>research</strong><br> and a <strong class='color-harm'>harmful</strong> particle that slowly <strong>chases</strong> 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 <strong>3</strong> <strong class='color-r'>research</strong> to exploit your <strong>wormhole</strong> for<br><strong>19%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>",
description: "use <strong>3</strong> <strong class='color-r'>research</strong> to exploit your <strong>wormhole</strong> for a<br><strong>19%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>",
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)
}
},
{

View File

@@ -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?