tech: aerostat - +88% damage off the ground, but -22% damage on the ground
  negative mass field required

tetherBoss now has beetle babies, and immunity
skins have a unique orb for their description card
  and some new images
cloaking field has a new graphic for sneak attack on the cross hairs

new community map yingYang by Richard0820

bug fixes
This commit is contained in:
landgreen
2023-02-13 19:48:49 -08:00
parent 9402cf2fe0
commit f8b4b6fde5
23 changed files with 763 additions and 255 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 17 KiB

BIN
img/aerostat.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -102,9 +102,10 @@
<option value="perplex"> <option value="perplex">
<option value="n-gon"> <option value="n-gon">
<option value="vats"> <option value="vats">
<option value="yingYang">
<option value="basement"> <option value="basement">
<option value="stronghold"> <option value="stronghold">
<option value="stereo madness"> <option value="stereoMadness">
<option value="house"> <option value="house">
<option value="dripp"> <option value="dripp">
<option value="crossfire"> <option value="crossfire">

View File

@@ -286,7 +286,7 @@ const b = {
fireCDscale: 1, fireCDscale: 1,
setFireCD() { setFireCD() {
b.fireCDscale = tech.fireRate * tech.slowFire * tech.researchHaste * tech.aimDamage b.fireCDscale = tech.fireRate * tech.slowFire * tech.researchHaste * tech.aimDamage
if (m.fieldMode === 6) b.fireCDscale *= 0.75 if (m.fieldMode === 6) b.fireCDscale *= 0.8
if (tech.isFastTime) b.fireCDscale *= 0.5 if (tech.isFastTime) b.fireCDscale *= 0.5
if (tech.isFireRateForGuns) b.fireCDscale *= Math.pow(0.82, Math.max(0, b.inventory.length - 1)) if (tech.isFireRateForGuns) b.fireCDscale *= Math.pow(0.82, Math.max(0, b.inventory.length - 1))
if (tech.isFireMoveLock) b.fireCDscale *= 0.55 if (tech.isFireMoveLock) b.fireCDscale *= 0.55
@@ -6377,23 +6377,23 @@ const b = {
mob[j].force.x += 0.01 * (Math.random() - 0.5) * mob[j].mass mob[j].force.x += 0.01 * (Math.random() - 0.5) * mob[j].mass
mob[j].force.y += 0.01 * (Math.random() - 0.5) * mob[j].mass mob[j].force.y += 0.01 * (Math.random() - 0.5) * mob[j].mass
} }
if (!mob[j].isShielded) { // if (!mob[j].isShielded) {
Matter.Body.setVelocity(mob[j], { //friction Matter.Body.setVelocity(mob[j], { //friction
x: mob[j].velocity.x * 0.95, x: mob[j].velocity.x * 0.95,
y: mob[j].velocity.y * 0.95 y: mob[j].velocity.y * 0.95
}); });
//draw vibes //draw vibes
let vertices = mob[j].vertices; let vertices = mob[j].vertices;
const vibe = 50 + mob[j].radius * 0.15 const vibe = 50 + mob[j].radius * 0.15
ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
for (let k = 1; k < vertices.length; k++) { for (let k = 1; k < vertices.length; k++) {
ctx.lineTo(vertices[k].x + vibe * (Math.random() - 0.5), vertices[k].y + vibe * (Math.random() - 0.5)); ctx.lineTo(vertices[k].x + vibe * (Math.random() - 0.5), vertices[k].y + vibe * (Math.random() - 0.5));
}
ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
//damage
mob[j].locatePlayer();
mob[j].damage(damage / Math.sqrt(mob[j].radius));
} }
ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
//damage
mob[j].locatePlayer();
mob[j].damage(damage / Math.sqrt(mob[j].radius));
// }
if (tech.isPhononWave && this.phononWaveCD < m.cycle) { if (tech.isPhononWave && this.phononWaveCD < m.cycle) {
this.phononWaveCD = m.cycle + 8 * (1 + this.waves[i].resonanceCount) this.phononWaveCD = m.cycle + 8 * (1 + this.waves[i].resonanceCount)
this.waves.push({ this.waves.push({
@@ -7110,7 +7110,10 @@ const b = {
}, },
doStream() {}, doStream() {},
fireStream() { fireStream() {
const spread = (input.down ? 0.04 : 0.3) * (Math.random() - 0.5) const spread = (input.down ?
0.04 * (Math.random() - 0.5) + 0.09 * Math.sin(m.cycle * 0.12) :
0.23 * (Math.random() - 0.5) + 0.15 * Math.sin(m.cycle * 0.12)
)
const radius = 5 + 8 * Math.random() + (tech.isAmmoFoamSize && this.ammo < 300) * 12 const radius = 5 + 8 * Math.random() + (tech.isAmmoFoamSize && this.ammo < 300) * 12
const SPEED = (input.down ? 1.2 : 1) * Math.max(2, 14 - radius * 0.25) const SPEED = (input.down ? 1.2 : 1) * Math.max(2, 14 - radius * 0.25)
const dir = m.angle + 0.15 * (Math.random() - 0.5) const dir = m.angle + 0.15 * (Math.random() - 0.5)
@@ -7162,7 +7165,10 @@ const b = {
} }
}, },
fireCharges() { fireCharges() {
const spread = (input.down ? 0.04 : 0.3) * (Math.random() - 0.5) const spread = (input.down ?
0.04 * (Math.random() - 0.5) + 0.09 * Math.sin(m.cycle * 0.12) :
0.23 * (Math.random() - 0.5) + 0.15 * Math.sin(m.cycle * 0.12)
)
const radius = 5 + 8 * Math.random() + (tech.isAmmoFoamSize && this.ammo < 300) * 12 const radius = 5 + 8 * Math.random() + (tech.isAmmoFoamSize && this.ammo < 300) * 12
const SPEED = (input.down ? 1.2 : 1) * Math.max(2, 14 - radius * 0.25) const SPEED = (input.down ? 1.2 : 1) * Math.max(2, 14 - radius * 0.25)
const dir = m.angle + 0.15 * (Math.random() - 0.5) const dir = m.angle + 0.15 * (Math.random() - 0.5)

View File

@@ -109,7 +109,7 @@ function collisionChecks(event) {
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0 let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0
if (m.isCloak) dmg *= 0.75 if (m.isCloak) dmg *= 0.75
mob[k].foundPlayer(); mob[k].foundPlayer();
if (tech.isRewindAvoidDeath && (m.energy + 0.05) > Math.min(1, m.maxEnergy) && dmg > 0.01) { //CPT reversal runs in m.damage, but it stops the rest of the collision code here too if (tech.isRewindAvoidDeath && (m.energy + 0.05) > Math.min(0.95, m.maxEnergy) && dmg > 0.01) { //CPT reversal runs in m.damage, but it stops the rest of the collision code here too
m.damage(dmg); m.damage(dmg);
return return
} }

View File

@@ -54,7 +54,7 @@ const cat = {
phased: 0x100000000, phased: 0x100000000,
} }
const color = { //light let color = { //light
// background: "#ddd", // used instead: document.body.style.backgroundColor // background: "#ddd", // used instead: document.body.style.backgroundColor
block: "rgba(140,140,140,0.85)", block: "rgba(140,140,140,0.85)",
blockS: "#222", blockS: "#222",
@@ -335,7 +335,7 @@ const build = {
<span style="float: right;">press ${input.key.pause} to resume</span> <span style="float: right;">press ${input.key.pause} to resume</span>
<br> <br>
<br><strong class='color-d'>damage</strong>: ${((tech.damageFromTech())).toPrecision(4)} &nbsp; &nbsp; difficulty: ${((m.dmgScale)).toPrecision(4)} <br><strong class='color-d'>damage</strong>: ${((tech.damageFromTech())).toPrecision(4)} &nbsp; &nbsp; difficulty: ${((m.dmgScale)).toPrecision(4)}
<br><strong class='color-defense'>defense</strong>: ${tech.isEnergyHealth ? (1-Math.pow(m.harmReduction(), 0.12)).toPrecision(5) : (1-m.harmReduction()).toPrecision(5) } &nbsp; &nbsp; difficulty: ${(1/simulation.dmgScale).toPrecision(4)} <br><strong class='color-defense'>defense</strong>: ${tech.isEnergyHealth ? (1-Math.pow(m.harmReduction(), 0.13)).toPrecision(5) : (1-m.harmReduction()).toPrecision(5) } &nbsp; &nbsp; difficulty: ${(1/simulation.dmgScale).toPrecision(4)}
<br><strong><em>fire rate</em></strong>: ${((1-b.fireCDscale)*100).toFixed(b.fireCDscale < 0.1 ? 2 : 0)}% <br><strong><em>fire rate</em></strong>: ${((1-b.fireCDscale)*100).toFixed(b.fireCDscale < 0.1 ? 2 : 0)}%
${tech.duplicationChance() ? `<br><strong class='color-dup'>duplication</strong>: ${(tech.duplicationChance()*100).toFixed(0)}%`: ""} ${tech.duplicationChance() ? `<br><strong class='color-dup'>duplication</strong>: ${(tech.duplicationChance()*100).toFixed(0)}%`: ""}
${m.coupling ? `<br><strong class='color-coupling'>coupling</strong>: ${(m.coupling).toFixed(2)} &nbsp; <span style = 'font-size:90%;'>`+m.couplingDescription()+"</span>": ""} ${m.coupling ? `<br><strong class='color-coupling'>coupling</strong>: ${(m.coupling).toFixed(2)} &nbsp; <span style = 'font-size:90%;'>`+m.couplingDescription()+"</span>": ""}
@@ -424,6 +424,9 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
} else if (tech.tech[i].isGunTech) { } else if (tech.tech[i].isGunTech) {
text += `<div id="${i}-pause-tech" class="pause-grid-module card-background ${ejectClass}" onclick="powerUps.pauseEjectTech(${i})" ${style}>` text += `<div id="${i}-pause-tech" class="pause-grid-module card-background ${ejectClass}" onclick="powerUps.pauseEjectTech(${i})" ${style}>`
text += build.gunTechText(i) + "</div>" text += build.gunTechText(i) + "</div>"
} else if (tech.tech[i].isSkin) {
text += `<div id="${i}-pause-tech" class="pause-grid-module card-background ${ejectClass}" onclick="powerUps.pauseEjectTech(${i})" ${style}>`
text += build.skinTechText(i) + "</div>"
} else { } else {
text += `<div id="${i}-pause-tech" class="pause-grid-module card-background ${ejectClass}" onclick="powerUps.pauseEjectTech(${i})" ${style}>` text += `<div id="${i}-pause-tech" class="pause-grid-module card-background ${ejectClass}" onclick="powerUps.pauseEjectTech(${i})" ${style}>`
text += build.techText(i) + "</div>" text += build.techText(i) + "</div>"
@@ -472,6 +475,14 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
<div class="grid-title" ><div class="circle-grid tech"></div> &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div> <div class="grid-title" ><div class="circle-grid tech"></div> &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>` ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
}, },
skinTechText(i) {
return `<div class="card-text"> <div class="grid-title">
<span style="position:relative;">
<div class="circle-grid-skin"></div>
<div class="circle-grid-skin-eye"></div>
</span> &nbsp; &nbsp; &nbsp;&nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
},
gunTechText(i) { gunTechText(i) {
return `<div class="card-text"> <div class="grid-title"> return `<div class="card-text"> <div class="grid-title">
<span style="position:relative;"> <span style="position:relative;">
@@ -565,6 +576,9 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
} else if (tech.tech[i].isJunk) { } else if (tech.tech[i].isJunk) {
techID.innerHTML = build.junkTechText(i) techID.innerHTML = build.junkTechText(i)
// `<div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>` // `<div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
} else if (tech.tech[i].isSkin) {
techID.classList.remove('experiment-grid-hide');
techID.innerHTML = build.skinTechText(i)
} else { } else {
techID.innerHTML = build.techText(i) techID.innerHTML = build.techText(i)
} }
@@ -588,6 +602,8 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
techID.innerHTML = build.gunTechText(i) techID.innerHTML = build.gunTechText(i)
} else if (tech.tech[i].isJunk) { } else if (tech.tech[i].isJunk) {
techID.innerHTML = build.junkTechText(i) techID.innerHTML = build.junkTechText(i)
} else if (tech.tech[i].isSkin) {
techID.innerHTML = build.skinTechText(i)
} else { } else {
techID.innerHTML = build.techText(i) techID.innerHTML = build.techText(i)
} }
@@ -661,12 +677,15 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
text += `<div id="tech-${i}" class="experiment-grid-module card-background experiment-grid-disabled" ${style}>` text += `<div id="tech-${i}" class="experiment-grid-module card-background experiment-grid-disabled" ${style}>`
// text += `<div id="tech-${i}" class="experiment-grid-module card-background experiment-grid-disabled" onclick="build.choosePowerUp(${i},'tech')" ${style}>` // text += `<div id="tech-${i}" class="experiment-grid-module card-background experiment-grid-disabled" onclick="build.choosePowerUp(${i},'tech')" ${style}>`
} }
if (tech.tech[i].isJunk) {
text += build.junkTechText(i) if (tech.tech[i].isFieldTech) {
text += build.fieldTechText(i)
} else if (tech.tech[i].isGunTech) { } else if (tech.tech[i].isGunTech) {
text += build.gunTechText(i) text += build.gunTechText(i)
} else if (tech.tech[i].isFieldTech) { } else if (tech.tech[i].isSkin) {
text += build.fieldTechText(i) text += build.skinTechText(i)
} else if (tech.tech[i].isJunk) {
text += build.junkTechText(i)
} else { } else {
text += build.techText(i) text += build.techText(i)
} }

View File

@@ -10,7 +10,7 @@ const level = {
// playableLevels: ["pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion"], // playableLevels: ["pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion"],
//see level.populateLevels: (intro, ... , reservoir, reactor, ... , gauntlet, final) added later //see level.populateLevels: (intro, ... , reservoir, reactor, ... , gauntlet, final) added later
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock"], playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock"],
communityLevels: ["stronghold", "basement", "crossfire", "vats", "run", "n-gon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness"], communityLevels: ["stronghold", "basement", "crossfire", "vats", "run", "n-gon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang"],
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"], trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"],
levels: [], levels: [],
start() { start() {
@@ -18,23 +18,23 @@ const level = {
// simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode // simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// tech.giveTech("performance") // tech.giveTech("performance")
// level.difficultyIncrease(10 * 4) //30 is near max on hard //60 is near max on why // level.difficultyIncrease(3 * 4) //30 is near max on hard //60 is near max on why
// spawn.setSpawnList(); // spawn.setSpawnList();
// spawn.setSpawnList(); // spawn.setSpawnList();
// m.maxHealth = m.health = 100 // m.maxHealth = m.health = 100
// tech.isRerollDamage = true // tech.isRerollDamage = true
// powerUps.research.changeRerolls(6) // powerUps.research.changeRerolls(50)
// m.immuneCycle = Infinity //you can't take damage // m.immuneCycle = Infinity //you can't take damage
// tech.tech[297].frequency = 100 // tech.tech[297].frequency = 100
// m.couplingChange(5) // m.couplingChange(5)
// m.setField("perfect diamagnetism") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass pilot wave plasma torch // m.setField("metamaterial cloaking") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass pilot wave plasma torch
// simulation.molecularMode = 2 // simulation.molecularMode = 2
// m.damage(0.1); // m.damage(0.1);
// b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("foam") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.guns[0].ammo = 10000 // b.guns[8].ammo = 10000
// tech.giveTech("aperture") // tech.giveTech("aperture")
// tech.giveTech("diaphragm") // tech.giveTech("CPT symmetry")
// for (let i = 0; i < 1; ++i) tech.giveTech("mass-energy equivalence") // for (let i = 0; i < 1; ++i) tech.giveTech("mass-energy equivalence")
// for (let i = 0; i < 1; ++i) tech.giveTech("tungsten carbide") // for (let i = 0; i < 1; ++i) tech.giveTech("tungsten carbide")
// for (let i = 0; i < 1; i++) tech.giveTech("CPT symmetry") // for (let i = 0; i < 1; i++) tech.giveTech("CPT symmetry")
@@ -42,7 +42,7 @@ const level = {
// for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling");
// level.testChamber(); // level.yingYang();
// spawn.nodeGroup(1200, 0, "slasher") // spawn.nodeGroup(1200, 0, "slasher")
// spawn.blinkBoss(1900, -500) // spawn.blinkBoss(1900, -500)
// spawn.sneakBoss(1900, -500) // spawn.sneakBoss(1900, -500)
@@ -57,10 +57,6 @@ const level = {
// for (let i = 0; i < 40; ++i) tech.giveTech() // for (let i = 0; i < 40; ++i) tech.giveTech()
// for (let i = 0; i < 13; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research"); // for (let i = 0; i < 13; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research");
//a for loop that produces Fibinochi numbers
level[simulation.isTraining ? "walk" : "intro"]() //normal starting level ************************************************ level[simulation.isTraining ? "walk" : "intro"]() //normal starting level ************************************************
// simulation.isAutoZoom = false; //look in close // simulation.isAutoZoom = false; //look in close
@@ -4400,7 +4396,7 @@ const level = {
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20);
level.defaultZoom = 2200 level.defaultZoom = 2200
simulation.zoomTransition(level.defaultZoom) simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "hsl(138, 3%, 74%)"; document.body.style.backgroundColor = "hsl(138, 5%, 82%)";
color.map = "#444" color.map = "#444"
powerUps.spawnStartingPowerUps(1768, 870); //on left side powerUps.spawnStartingPowerUps(1768, 870); //on left side
const portal = level.portal({ x: 1070, y: -1485 }, -0.9, { x: 475, y: 50 }, -Math.PI / 2) const portal = level.portal({ x: 1070, y: -1485 }, -0.9, { x: 475, y: 50 }, -Math.PI / 2)
@@ -4471,6 +4467,9 @@ const level = {
ctx.fillStyle = "rgba(0,0,0,0.1)" //shadows ctx.fillStyle = "rgba(0,0,0,0.1)" //shadows
ctx.fillRect(-250, -1550, 1250, 1575); ctx.fillRect(-250, -1550, 1250, 1575);
ctx.fillRect(2537, -350, 275, 2425); ctx.fillRect(2537, -350, 275, 2425);
ctx.fillStyle = "rgba(0,0,0,0.05)" //exit
ctx.fillRect(-175, -300, 375, 300)
ctx.fillRect(4460, 950, 350, 325);
ctx.fillStyle = "#233" //balances center dot ctx.fillStyle = "#233" //balances center dot
ctx.beginPath(); ctx.beginPath();
for (let i = 0; i < balance.length; i++) { for (let i = 0; i < balance.length; i++) {
@@ -5559,7 +5558,7 @@ const level = {
// const button1 = level.button(-500, -200) // const button1 = level.button(-500, -200)
const toggle1 = level.toggle(-300, -200) //(x,y,isOn,isLockOn = true/false) const toggle1 = level.toggle(-300, -200) //(x,y,isOn,isLockOn = true/false)
const elevator2 = level.elevator(-3630, -1000, 180, 25, -1740) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { const elevator2 = level.elevator(-3630, -970, 180, 25, -1740, 0.004) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) {
elevator2.addConstraint(); elevator2.addConstraint();
// const button2 = level.button(-3100, -1330) // const button2 = level.button(-3100, -1330)
const toggle2 = level.toggle(-3100, -1330) //(x,y,isOn, isLockOn = true/false) const toggle2 = level.toggle(-3100, -1330) //(x,y,isOn, isLockOn = true/false)
@@ -5620,7 +5619,7 @@ const level = {
} else { } else {
ctx.fillStyle = "#aaa" ctx.fillStyle = "#aaa"
} }
ctx.fillRect(-3540, -1720, 1, 740) ctx.fillRect(-3540, -1720, 1, 770)
ctx.fillStyle = "rgba(64,64,64,0.97)" //hidden section ctx.fillStyle = "rgba(64,64,64,0.97)" //hidden section
ctx.fillRect(-4450, -750, 800, 200) ctx.fillRect(-4450, -750, 800, 200)
@@ -6157,14 +6156,14 @@ const level = {
let isReverse = false let isReverse = false
if (Math.random() < 0.75) { //normal direction start in top left if (Math.random() < 0.75) { //normal direction start in top left
button = level.button(525, 0) button = level.button(525, 0)
door = level.door(1362, -200, 25, 200, 195) door = level.door(1362, -400, 25, 400, 355, 1.5) //door(x, y, width, height, distance, speed = 1) {
level.setPosToSpawn(1375, -1550); //normal spawn level.setPosToSpawn(1375, -1550); //normal spawn
level.exit.x = 3088; level.exit.x = 3088;
level.exit.y = -630; level.exit.y = -630;
} else { //reverse direction, start in bottom right } else { //reverse direction, start in bottom right
isReverse = true isReverse = true
button = level.button(3800, 0) button = level.button(3800, 0)
door = level.door(3012, -200, 25, 200, 195) door = level.door(3012, -400, 25, 400, 355, 1.5)
level.setPosToSpawn(3137, -650); //normal spawn level.setPosToSpawn(3137, -650); //normal spawn
level.exit.x = 1375; level.exit.x = 1375;
level.exit.y = -1530; level.exit.y = -1530;
@@ -6219,7 +6218,8 @@ const level = {
spawn.bodyRect(-298, -1580, 40, 40); //center block under wall spawn.bodyRect(-298, -1580, 40, 40); //center block under wall
spawn.bodyRect(1500, -1540, 30, 30); //left of entrance spawn.bodyRect(1500, -1540, 30, 30); //left of entrance
spawn.mapRect(1550, -2000, 50, 550); //right wall spawn.mapRect(1550, -2000, 50, 550); //right wall
spawn.mapRect(1350, -2000 + 505, 50, 1295); //right wall // spawn.mapRect(1350, -2000 + 505, 50, 1295);
spawn.mapRect(1350, -1500, 50, 1125); //right wall
spawn.mapRect(-600, -2000 + 250, 2000 - 700, 50); //roof left spawn.mapRect(-600, -2000 + 250, 2000 - 700, 50); //roof left
spawn.mapRect(-600 + 1300, -2000, 50, 300); //right roof wall spawn.mapRect(-600 + 1300, -2000, 50, 300); //right roof wall
spawn.mapRect(-600 + 1300, -2000, 900, 50); //center wall spawn.mapRect(-600 + 1300, -2000, 900, 50); //center wall
@@ -6238,6 +6238,9 @@ const level = {
stiffness: 1 stiffness: 1
}); });
Composite.add(engine.world, consBB[consBB.length - 1]); Composite.add(engine.world, consBB[consBB.length - 1]);
spawn.mapRect(-600 + 300, -2000 * 0.75, 1900, 50); //3rd floor spawn.mapRect(-600 + 300, -2000 * 0.75, 1900, 50); //3rd floor
spawn.mapRect(-600 + 2000 * 0.7, -2000 * 0.74, 50, 375); //center wall spawn.mapRect(-600 + 2000 * 0.7, -2000 * 0.74, 50, 375); //center wall
spawn.bodyRect(-600 + 2000 * 0.7, -2000 * 0.5 - 106, 50, 106); //center block under wall spawn.bodyRect(-600 + 2000 * 0.7, -2000 * 0.5 - 106, 50, 106); //center block under wall
@@ -6254,7 +6257,7 @@ const level = {
spawn.mapRect(1390, 13, 30, 20); //step left spawn.mapRect(1390, 13, 30, 20); //step left
spawn.mapRect(2980, 13, 30, 20); //step right spawn.mapRect(2980, 13, 30, 20); //step right
spawn.bodyRect(4250, -700, 50, 100); spawn.bodyRect(4250, -700, 50, 100);
spawn.mapRect(3000, -1000, 50, 800); //left wall spawn.mapRect(3000, -1000, 50, 625); //left wall
spawn.mapRect(3000 + 2000 - 50, -1300, 50, 1100); //right wall spawn.mapRect(3000 + 2000 - 50, -1300, 50, 1100); //right wall
spawn.mapRect(4150, -600, 350, 150); //table spawn.mapRect(4150, -600, 350, 150); //table
spawn.mapRect(3650, -1300, 50, 700); //exit wall spawn.mapRect(3650, -1300, 50, 700); //exit wall
@@ -6285,12 +6288,7 @@ const level = {
spawn.randomGroup(4150, -1000, 0.6); spawn.randomGroup(4150, -1000, 0.6);
if (simulation.difficulty > 1) { if (simulation.difficulty > 1) {
if (Math.random() < 0.5) { if (Math.random() < 0.5) {
spawn.tetherBoss(2850, -80, { spawn.tetherBoss(2850, -80, { x: 2500, y: -500 })
x: 2500,
y: -500
})
//chance to spawn a ring of exploding mobs around this boss
if (simulation.difficulty > 6) spawn.nodeGroup(2850, -80, "spawns", 8, 20, 105);
} else { } else {
spawn.randomLevelBoss(2200, -450) spawn.randomLevelBoss(2200, -450)
} }
@@ -6727,12 +6725,7 @@ const level = {
if (isLevelReversed === false) { ///Normal spawn if (isLevelReversed === false) { ///Normal spawn
if (simulation.difficulty > 1) { if (simulation.difficulty > 1) {
if (Math.random() < 0.2) { if (Math.random() < 0.2) {
// tether ball spawn.tetherBoss(7000, -3300, { x: 7300, y: -3300 }) // tether ball
spawn.tetherBoss(7000, -3300, {
x: 7300,
y: -3300
})
if (simulation.difficulty > 4) spawn.nodeGroup(7000, -3300, "spawns", 8, 20, 105);
} else { } else {
spawn.randomLevelBoss(6100, -3600, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "pulsarBoss"]); spawn.randomLevelBoss(6100, -3600, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "pulsarBoss"]);
} }
@@ -6740,12 +6733,7 @@ const level = {
} else { /// Reversed spawn } else { /// Reversed spawn
if (simulation.difficulty > 1) { if (simulation.difficulty > 1) {
if (Math.random() < 0.2) { if (Math.random() < 0.2) {
// tether ball spawn.tetherBoss(2300, -1300, { x: 2300, y: -1750 }) // tether ball
spawn.tetherBoss(2300, -1300, {
x: 2300,
y: -1750
})
if (simulation.difficulty > 4) spawn.nodeGroup(2350, -1300, "spawns", 8, 20, 105);
} else { } else {
spawn.randomLevelBoss(2300, -1400, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "dragonFlyBoss", "pulsarBoss"]); spawn.randomLevelBoss(2300, -1400, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "dragonFlyBoss", "pulsarBoss"]);
} }
@@ -6803,13 +6791,8 @@ const level = {
spawn.mapRect(3075, 1075, 375, 150); //Plafond salle trésor spawn.mapRect(3075, 1075, 375, 150); //Plafond salle trésor
spawn.mapRect(3300, 1075, 1500, 1800); //Mur droite salle trésor spawn.mapRect(3300, 1075, 1500, 1800); //Mur droite salle trésor
// tether ball // tether ball
spawn.tetherBoss(2330, 1850, { spawn.tetherBoss(2330, 1850, { x: 2330, y: 1425 })
x: 2330,
y: 1425
})
spawn.secondaryBossChance(2330, 1850) spawn.secondaryBossChance(2330, 1850)
//chance to spawn a ring of exploding mobs around this boss
if (simulation.difficulty > 1) spawn.nodeGroup(2330, 1850, "spawns", 8, 20, 105);
powerUps.chooseRandomPowerUp(3100, 1630); powerUps.chooseRandomPowerUp(3100, 1630);
}, },
// detours() { //by Francois from discord // detours() { //by Francois from discord
@@ -7595,11 +7578,7 @@ const level = {
if (simulation.difficulty > 3) { if (simulation.difficulty > 3) {
spawn.secondaryBossChance(3380, -1775) spawn.secondaryBossChance(3380, -1775)
if (Math.random() < 0.16) { if (Math.random() < 0.16) {
spawn.tetherBoss(3380, -1775, { spawn.tetherBoss(3380, -1775, { x: 3775, y: -1775 })
x: 3775,
y: -1775
})
if (simulation.difficulty > 4) spawn.nodeGroup(3380, -1775, "spawns", 8, 20, 105); //chance to spawn a ring of exploding mobs around this boss
} else { } else {
spawn.randomLevelBoss(3100, -1850, ["shooterBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "dragonFlyBoss", "laserBoss"]); spawn.randomLevelBoss(3100, -1850, ["shooterBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "dragonFlyBoss", "laserBoss"]);
} }
@@ -13138,7 +13117,7 @@ const level = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.stroke = "transparent"; me.stroke = "transparent";
me.collisionFilter.mask = cat.player | cat.bullet; me.collisionFilter.mask = cat.player | cat.bullet;
me.accelMag = 0.0006 * Math.min(simulation.difficulty + 1, 6); me.accelMag = 0.0006 * Math.min(simulation.difficulty + 1, 4);
me.showHealthBar = false; me.showHealthBar = false;
me.isUnblockable = true; me.isUnblockable = true;
me.isShielded = true; me.isShielded = true;
@@ -14713,6 +14692,359 @@ const level = {
coin(103830.0, -1473) coin(103830.0, -1473)
hunter(0, -1000) hunter(0, -1000)
}, },
yingYang() {
simulation.makeTextLog(`<strong>yingYang</strong> by <span class='color-var'>Richard0820</span>`);
let destroyed = false;
const lock = level.door(425, -1400, 50, 300, 300);
const core = function(x, y, radius = 100 + Math.ceil(Math.random() * 25)) {
radius = 9 + radius / 8; //extra small
mobs.spawn(x, y, 6, radius, "transparent");
let me = mob[mob.length - 1];
me.constraint = Constraint.create({
pointA: {
x: me.position.x,
y: me.position.y
},
bodyB: me,
stiffness: 1,
damping: 1
});
Composite.add(engine.world, me.constraint);
me.stroke = "transparent"; //used for drawSneaker
me.eventHorizon = radius * 40;
me.seeAtDistance2 = (me.eventHorizon + 400) * (me.eventHorizon + 400); //vision limit is event horizon
me.accelMag = 0.00012 * simulation.accelScale;
me.frictionAir = 0.025;
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body
me.showHealthBar = false;
me.memory = Infinity;
me.isBoss = true;
Matter.Body.setDensity(me, 1); //extra dense //normal is 0.001 //makes effective life much larger
me.onDeath = function() {
destroyed = true;
powerUps.spawnBossPowerUp(this.position.x, this.position.y);
}
me.do = function() {
if (this.health < 1) {
this.health += 0.001; //regen
simulation.drawList.push({
x: this.position.x,
y: this.position.y,
radius: this.radius / 1.5,
color: `rgba(0, 255, 20, ${Math.random() * 0.1})`,
time: simulation.drawTime
});
}
this.curl()
this.repelBullets()
this.seePlayerCheckByDistance()
this.checkStatus();
const eventHorizon = this.eventHorizon * (0.93 + 0.17 * Math.sin(simulation.cycle * 0.011))
//draw darkness
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, eventHorizon * 0.25, 0, 2 * Math.PI);
ctx.fillStyle = "rgba(250,250,250,0.9)";
ctx.fill();
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, eventHorizon * 0.55, 0, 2 * Math.PI);
ctx.fillStyle = "rgba(250,250,250,0.5)";
ctx.fill();
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, eventHorizon, 0, 2 * Math.PI);
ctx.fillStyle = "rgba(250,250,250,0.1)";
ctx.fill();
//when player is inside event horizon
if (Vector.magnitude(Vector.sub(this.position, player.position)) < eventHorizon) {
if (m.immuneCycle < m.cycle) {
if (m.energy > 0) m.energy -= 0.005
if (m.energy < 0.1) m.damage(0.0001 * simulation.dmgScale);
}
const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x);
player.force.x += 0.00125 * player.mass * Math.cos(angle) * (m.onGround ? 1.8 : 1);
player.force.y += 0.0001 * player.mass * Math.sin(angle);
//draw line to player
ctx.beginPath();
ctx.moveTo(this.position.x, this.position.y);
ctx.lineTo(m.pos.x, m.pos.y);
ctx.lineWidth = Math.min(60, this.radius * 2);
ctx.strokeStyle = "rgba(250,250,250,0.5)";
ctx.stroke();
ctx.beginPath();
ctx.arc(m.pos.x, m.pos.y, 40, 0, 2 * Math.PI);
ctx.fillStyle = "rgba(250,250,250,0.3)";
ctx.fill();
}
}
}
const sniper = function(x, y, radius = 35 + Math.ceil(Math.random() * 30)) { //same, just white so that we can seen
mobs.spawn(x, y, 3, radius, "transparent"); //"rgb(25,0,50)")
let me = mob[mob.length - 1];
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
me.isVerticesChange = true
// Matter.Body.rotate(me, Math.PI)
me.stroke = "transparent"; //used for drawSneaker
me.alpha = 1; //used in drawSneaker
me.showHealthBar = false;
me.frictionStatic = 0;
me.friction = 0;
me.canTouchPlayer = false; //used in drawSneaker
me.isBadTarget = true;
me.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player
me.memory = 30 //140;
me.fireFreq = 0.005 + Math.random() * 0.002 + 0.0005 * simulation.difficulty; //larger = fire more often
me.noseLength = 0;
me.fireAngle = 0;
me.accelMag = 0.0005 * simulation.accelScale;
me.frictionAir = 0.05;
me.torque = 0.0001 * me.inertia;
me.fireDir = {
x: 0,
y: 0
};
me.onDeath = function() { //helps collisions functions work better after vertex have been changed
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices))
}
// spawn.shield(me, x, y);
me.do = function() {
// this.seePlayerByLookingAt();
this.seePlayerCheck();
this.checkStatus();
const setNoseShape = () => {
const mag = this.radius + this.radius * this.noseLength;
this.vertices[1].x = this.position.x + Math.cos(this.angle) * mag;
this.vertices[1].y = this.position.y + Math.sin(this.angle) * mag;
};
//throw a mob/bullet at player
if (this.seePlayer.recall) {
//set direction to turn to fire
if (!(simulation.cycle % this.seePlayerFreq)) {
this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position));
// this.fireDir.y -= Math.abs(this.seePlayer.position.x - this.position.x) / 1600; //gives the bullet an arc
}
//rotate towards fireAngle
const angle = this.angle + Math.PI / 2;
// c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
//rotate towards fireAngle
const dot = Vector.dot({
x: Math.cos(angle),
y: Math.sin(angle)
}, this.fireDir)
const threshold = 0.03;
if (dot > threshold) {
this.torque += 0.000004 * this.inertia;
} else if (dot < -threshold) {
this.torque -= 0.000004 * this.inertia;
} else if (this.noseLength > 1.5 && dot > -0.2 && dot < 0.2) {
//fire
spawn.sniperBullet(this.vertices[1].x, this.vertices[1].y, 7 + Math.ceil(this.radius / 15), 5);
const v = 10 + 8 * simulation.accelScale;
Matter.Body.setVelocity(mob[mob.length - 1], {
x: this.velocity.x + this.fireDir.x * v + Math.random(),
y: this.velocity.y + this.fireDir.y * v + Math.random()
});
this.noseLength = 0;
// recoil
this.force.x -= 0.005 * this.fireDir.x * this.mass;
this.force.y -= 0.005 * this.fireDir.y * this.mass;
}
if (this.noseLength < 1.5) this.noseLength += this.fireFreq;
setNoseShape();
} else if (this.noseLength > 0.1) {
this.noseLength -= this.fireFreq / 2;
setNoseShape();
}
// else if (this.noseLength < -0.1) {
// this.noseLength += this.fireFreq / 4;
// setNoseShape();
// }
if (this.seePlayer.recall) {
if (this.alpha < 1) this.alpha += 0.01;
} else {
if (this.alpha > 0) this.alpha -= 0.03;
}
//draw
if (this.alpha > 0) {
if (this.alpha > 0.95) {
this.healthBar();
if (!this.canTouchPlayer) {
this.canTouchPlayer = true;
this.isBadTarget = false;
this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob; //can touch player
}
}
//draw body
ctx.beginPath();
const vertices = this.vertices;
ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1, len = vertices.length; j < len; ++j) {
ctx.lineTo(vertices[j].x, vertices[j].y);
}
ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.fillStyle = `rgba(250,250,250,${this.alpha * this.alpha})`;
ctx.fill();
} else if (this.canTouchPlayer) {
this.canTouchPlayer = false;
this.isBadTarget = true
this.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player
}
};
}
const portal = level.portal({
x: 650,
y: -1000
}, Math.PI * 1.5, {
x: 525,
y: 2625
}, -Math.PI)
document.body.style.transition = '0ms'
document.body.style.backgroundColor = "#313d54" //"#061026";
var yy = new Image();
yy.src = 'https://raw.githubusercontent.com/Whyisthisnotavalable/image-yy/main/Hotpot6.png';
color.map = "#FFFFFF11";
color.bullet = "#FFFFFF";
level.custom = () => {
level.enter.draw();
level.exit.drawAndCheck();
ctx.drawImage(yy, 0 - 500, 0 - 500, 1000, 1000)
portal[0].draw();
portal[1].draw();
portal[2].query();
portal[3].query();
if (destroyed == false) {
lock.isClosing = true;
} else {
lock.isClosing = false;
}
lock.openClose();
};
level.customTopLayer = () => {
lock.draw()
/*
ctx.beginPath()
ctx.strokeStyle = "transparent";
ctx.fillStyle = "#FFFFFF22"
ctx.arc(m.pos.x, m.pos.y, 500, 0, Math.PI * 2)
ctx.fill()
ctx.fillStyle = "#FFFFFF55"
ctx.arc(m.pos.x, m.pos.y, 1000, 0, Math.PI * 2)
ctx.fill();
ctx.stroke(); */
ctx.beginPath();
ctx.moveTo(m.pos.x, m.pos.y)
const arc = Math.PI / 4
ctx.arc(m.pos.x, m.pos.y, 100, m.angle + arc, m.angle - arc)
ctx.arc(m.pos.x, m.pos.y, 4000, m.angle - arc, m.angle + arc)
ctx.fillStyle = "rgba(255,255,255,0.7)";
ctx.globalCompositeOperation = "destination-in";
ctx.fill();
ctx.globalCompositeOperation = "source-over";
ctx.clip();
};
level.setPosToSpawn(0, -50);
level.exit.x = -275;
level.exit.y = 2900;
level.defaultZoom = 1800
simulation.zoomTransition(level.defaultZoom)
//map
spawn.mapRect(-125, -325, 225, 25);
spawn.mapRect(300, -150, 25, 325);
spawn.mapRect(-325, -125, 25, 300);
spawn.mapRect(-150, 300, 275, 25);
spawn.mapRect(125, -300, 25, 25);
spawn.mapRect(175, -275, 25, 25);
spawn.mapRect(225, -250, 25, 25);
spawn.mapRect(250, -200, 25, 25);
spawn.mapRect(-175, -300, 25, 25);
spawn.mapRect(-225, -275, 25, 25);
spawn.mapRect(-300, -200, 25, 25);
spawn.mapRect(150, 275, 25, 25);
spawn.mapRect(200, 225, 25, 25);
spawn.mapRect(250, 200, 25, 25);
spawn.mapRect(250, -225, 25, 25);
spawn.mapRect(275, -175, 25, 25);
spawn.mapRect(200, -275, 25, 25);
spawn.mapRect(150, -300, 25, 25);
spawn.mapRect(100, -325, 25, 25);
spawn.mapRect(-150, -300, 25, 25);
spawn.mapRect(-200, -300, 25, 25);
spawn.mapRect(-250, -250, 25, 25);
spawn.mapRect(-275, -225, 25, 25);
spawn.mapRect(-300, -175, 25, 50);
spawn.mapRect(275, 175, 25, 25);
spawn.mapRect(250, 200, 25, 25);
spawn.mapRect(225, 225, 25, 25);
spawn.mapRect(175, 250, 25, 25);
spawn.mapRect(125, 300, 25, 25);
spawn.mapRect(-300, 325, 200, 150);
spawn.mapRect(-400, 425, 225, 150);
spawn.mapRect(-4450, 2900, 1550, 150);
spawn.mapRect(-4500, 2525, 150, 525);
spawn.mapRect(-4800, 2150, 150, 400);
spawn.mapRect(-4400, 2025, 650, 150);
spawn.mapRect(-2425, 50, 2125, 150);
spawn.mapRect(-2425, 50, 150, 1300);
spawn.mapRect(-4600, 1175, 2325, 175);
spawn.mapRect(-5075, 1650, 450, 150);
spawn.mapRect(-4650, 1225, 75, 125);
spawn.mapRect(-4700, 1275, 75, 75);
spawn.mapRect(-425, 2925, 425, 125);
spawn.mapRect(-450, 2375, 450, 100);
spawn.mapRect(-3050, 550, 150, 450);
spawn.mapRect(-2925, 825, 100, 175);
spawn.mapRect(-2650, 375, 275, 125);
spawn.mapRect(-75, 2950, 300, 100);
spawn.mapRect(-625, -500, 125, 575);
spawn.mapRect(-1050, -325, 275, 100);
spawn.mapRect(-1075, -775, 100, 550);
spawn.mapRect(-1075, -775, 300, 100);
spawn.mapRect(-525, -1100, 1025, 625);
spawn.mapRect(450, -1000, 450, 1500);
spawn.mapRect(-300, 500, 1200, 75);
spawn.mapRect(-200, 425, 725, 100);
spawn.mapRect(525, 2450, 275, 600);
spawn.mapRect(-25, 2375, 825, 125);
spawn.mapRect(400, -1500, 500, 100);
spawn.mapRect(800, -1500, 100, 525);
spawn.mapRect(-400, 500, 1250, 1900);
spawn.mapRect(-300, 2910, 150, 25);
spawn.mapRect(-625, -1000, 125, 175);
spawn.spawnStairs(-400, 3000, 25, 2500, 2500, 250);
spawn.spawnStairs(500, 3000, 5, 250, 250, 250);
spawn.debris(-1550, -250, 100);
spawn.debris(-1100, 850, 100);
spawn.debris(-3700, 1025, 100);
spawn.debris(-3525, 2725, 100);
spawn.debris(-4750, 2050, 100);
spawn.debris(-4000, 1900, 100);
spawn.debris(225, -1225, 100);
//mobs
spawn.sneaker(-1350, 1350);
spawn.sneaker(-2275, 2275);
sniper(-3050 + Math.floor(Math.random() * 100) - Math.floor(Math.random() * 100), 1475 + Math.floor(Math.random() * 100) - Math.floor(Math.random() * 100));
sniper(-2925 + Math.floor(Math.random() * 100) - Math.floor(Math.random() * 100), 1775 + Math.floor(Math.random() * 100) - Math.floor(Math.random() * 100));
sniper(-3075 + Math.floor(Math.random() * 100) - Math.floor(Math.random() * 100), 1600 + Math.floor(Math.random() * 100) - Math.floor(Math.random() * 100));
sniper(-3100 + Math.floor(Math.random() * 100) - Math.floor(Math.random() * 100), 1975 + Math.floor(Math.random() * 100) - Math.floor(Math.random() * 100));
sniper(-3075 + Math.floor(Math.random() * 100) - Math.floor(Math.random() * 100), 1750 + Math.floor(Math.random() * 100) - Math.floor(Math.random() * 100));
sniper(-3350, 425);
sniper(-3550, 600);
sniper(-3325, 775);
sniper(-5525, 1975);
sniper(-50, -1300);
for (let i = 0; i < 10 + simulation.difficulty; i++) {
spawn.ghoster(0 + Math.floor(Math.random() * 5000) - Math.floor(Math.random() * 5000), 0 + Math.floor(Math.random() * 5000) - Math.floor(Math.random() * 5000))
}
core(-2000, -1000);
powerUps.spawnStartingPowerUps(0, 0)
powerUps.addResearchToLevel()
},
// ******************************************************************************************************** // ********************************************************************************************************
// ******************************************************************************************************** // ********************************************************************************************************
// ***************************************** training levels ********************************************** // ***************************************** training levels **********************************************

View File

@@ -820,25 +820,25 @@ const mobs = {
} }
}, },
repelBullets() { repelBullets() {
if (this.seePlayer.yes) { // if (this.seePlayer.yes) {
ctx.lineWidth = "8"; // ctx.lineWidth = "8";
ctx.strokeStyle = this.fill; // ctx.strokeStyle = this.fill;
ctx.beginPath(); // ctx.beginPath();
for (let i = 0, len = bullet.length; i < len; ++i) { for (let i = 0, len = bullet.length; i < len; ++i) {
const dx = bullet[i].position.x - this.position.x; const dx = bullet[i].position.x - this.position.x;
const dy = bullet[i].position.y - this.position.y; const dy = bullet[i].position.y - this.position.y;
const dist = Math.sqrt(dx * dx + dy * dy); const dist = Math.max(300, Math.sqrt(dx * dx + dy * dy))
if (dist < 500) { if (dist < 700) {
ctx.moveTo(this.position.x, this.position.y); ctx.moveTo(this.position.x, this.position.y);
ctx.lineTo(bullet[i].position.x, bullet[i].position.y); ctx.lineTo(bullet[i].position.x, bullet[i].position.y);
const angle = Math.atan2(dy, dx); const angle = Math.atan2(dy, dx);
const mag = (1500 * bullet[i].mass * simulation.g) / dist; const mag = (500 * bullet[i].mass * simulation.g) / dist;
bullet[i].force.x += mag * Math.cos(angle); bullet[i].force.x += mag * Math.cos(angle);
bullet[i].force.y += mag * Math.sin(angle); bullet[i].force.y += mag * Math.sin(angle);
}
} }
ctx.stroke();
} }
// ctx.stroke();
// }
}, },
attraction() { attraction() {
//accelerate towards the player //accelerate towards the player
@@ -1279,6 +1279,9 @@ const mobs = {
powerUps.spawn(this.position.x - 20, this.position.y, "ammo", false) powerUps.spawn(this.position.x - 20, this.position.y, "ammo", false)
powerUps.spawn(this.position.x, this.position.y + 20, "research", false) powerUps.spawn(this.position.x, this.position.y + 20, "research", false)
powerUps.spawn(this.position.x, this.position.y - 20, "heal", false) powerUps.spawn(this.position.x, this.position.y - 20, "heal", false)
powerUps.spawn(this.position.x - 40, this.position.y, "ammo", false)
powerUps.spawn(this.position.x, this.position.y + 40, "research", false)
powerUps.spawn(this.position.x, this.position.y - 40, "heal", false)
} else { } else {
const amount = 0.005 const amount = 0.005
if (tech.isEnergyHealth) { if (tech.isEnergyHealth) {

View File

@@ -547,7 +547,7 @@ const m = {
dmg *= m.fieldHarmReduction dmg *= m.fieldHarmReduction
// if (!tech.isFlipFlopOn && tech.isFlipFlopHealth) dmg *= 0.5 // if (!tech.isFlipFlopOn && tech.isFlipFlopHealth) dmg *= 0.5
// 1.25 + Math.sin(m.cycle * 0.01) // 1.25 + Math.sin(m.cycle * 0.01)
if (tech.isDiaphragm) dmg *= 0.66 + 0.66 * Math.sin(m.cycle * 0.01); if (tech.isDiaphragm) dmg *= 0.66 + 0.66 * Math.sin(m.cycle * 0.0075);
if (tech.isZeno) dmg *= 0.15 if (tech.isZeno) dmg *= 0.15
if (tech.isFieldHarmReduction) dmg *= 0.5 if (tech.isFieldHarmReduction) dmg *= 0.5
if (tech.isHarmMACHO) dmg *= 0.4 if (tech.isHarmMACHO) dmg *= 0.4
@@ -640,7 +640,7 @@ const m = {
}); });
} }
} }
m.energy = Math.max(m.energy - steps / 200, 0.01) m.energy = Math.max(m.energy - steps / 250, 0.01)
if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles
let isDrawPlayer = true let isDrawPlayer = true
@@ -691,7 +691,7 @@ const m = {
}, },
collisionImmuneCycles: 30, collisionImmuneCycles: 30,
damage(dmg) { damage(dmg) {
if (tech.isRewindAvoidDeath && (m.energy + 0.05) > Math.min(1, m.maxEnergy) && dmg > 0.01) { if (tech.isRewindAvoidDeath && (m.energy + 0.05) > Math.min(0.95, m.maxEnergy) && dmg > 0.01) {
const steps = Math.floor(Math.min(299, 150 * m.energy)) const steps = Math.floor(Math.min(299, 150 * m.energy))
simulation.makeTextLog(`<span class='color-var'>m</span>.rewind(${steps})`) simulation.makeTextLog(`<span class='color-var'>m</span>.rewind(${steps})`)
m.rewind(steps) m.rewind(steps)
@@ -708,7 +708,7 @@ const m = {
} }
} }
if (tech.isEnergyHealth) { if (tech.isEnergyHealth) {
dmg *= Math.pow(m.harmReduction(), 0.12) //defense has less effect dmg *= Math.pow(m.harmReduction(), 0.13) //defense has less effect
m.energy -= 0.9 * dmg / Math.sqrt(simulation.healScale) //scale damage with heal reduction difficulty m.energy -= 0.9 * dmg / Math.sqrt(simulation.healScale) //scale damage with heal reduction difficulty
if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage
if (tech.isDeathAvoid && powerUps.research.count && !tech.isDeathAvoidedThisLevel) { if (tech.isDeathAvoid && powerUps.research.count && !tech.isDeathAvoidedThisLevel) {
@@ -1020,9 +1020,9 @@ const m = {
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20) ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.translate(m.pos.x, m.pos.y); ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3); m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a"); m.drawLeg("#456");
m.calcLeg(0, 0); m.calcLeg(0, 0);
m.drawLeg("#333"); m.drawLeg("#345");
ctx.rotate(m.angle); ctx.rotate(m.angle);
ctx.beginPath(); ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI); ctx.arc(0, 0, 30, 0, 2 * Math.PI);
@@ -1034,13 +1034,9 @@ const m = {
ctx.beginPath(); ctx.beginPath();
ctx.arc(17, 0, 5.5, 0, 2 * Math.PI); ctx.arc(17, 0, 5.5, 0, 2 * Math.PI);
ctx.fillStyle = "#333" ctx.fillStyle = "#357"
ctx.fill(); ctx.fill();
ctx.beginPath();
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore(); ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw() powerUps.boost.draw()
@@ -1099,14 +1095,14 @@ const m = {
m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)` m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)`
m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 50}%)` m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 50}%)`
const grd = ctx.createLinearGradient(-30, -5, 30, 10); const grd = ctx.createLinearGradient(-30, -5, 30, 10);
grd.addColorStop(0, `#eee`); grd.addColorStop(0, `#e0e0e0`);
grd.addColorStop(0.3, `#bbb`); grd.addColorStop(0.3, `#bbb`);
grd.addColorStop(0.4, `#aaa`); grd.addColorStop(0.4, `#b3b3b3`);
grd.addColorStop(0.5, `#ccc`); grd.addColorStop(0.5, `#c5c5c5`);
grd.addColorStop(0.65, `#bbb`); grd.addColorStop(0.65, `#bbb`);
grd.addColorStop(0.7, `#aaa`); grd.addColorStop(0.7, `#b3b3b3`);
grd.addColorStop(0.75, `#bbb`); grd.addColorStop(0.75, `#bbb`);
grd.addColorStop(1, `#eee`); grd.addColorStop(1, `#e0e0e0`);
// const grdRad = ctx.createRadialGradient(0, 0, 0, 0, 0, 30); // const grdRad = ctx.createRadialGradient(0, 0, 0, 0, 0, 30);
// grdRad.addColorStop(0, `rgba(0,0,0,0.3)`); // grdRad.addColorStop(0, `rgba(0,0,0,0.3)`);
// grdRad.addColorStop(0.5, `rgba(210,210,210,0)`); // grdRad.addColorStop(0.5, `rgba(210,210,210,0)`);
@@ -1308,28 +1304,29 @@ const m = {
dilate() { dilate() {
m.isAltSkin = true m.isAltSkin = true
m.draw = function() { m.draw = function() {
const amplitude = 8 + 4 * Math.sin(m.cycle * 0.0075)
ctx.fillStyle = m.fillColor; ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx; m.walk_cycle += m.flipLegs * m.Vx;
ctx.save(); ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20) ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.translate(m.pos.x, m.pos.y); ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3); m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a"); m.drawLeg("#456");
m.calcLeg(0, 0); m.calcLeg(0, 0);
m.drawLeg("#333"); m.drawLeg("#345");
ctx.rotate(m.angle); ctx.rotate(m.angle);
ctx.beginPath(); ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI); ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient ctx.fillStyle = m.bodyGradient
ctx.fill(); ctx.fill();
ctx.strokeStyle = "#333"; ctx.strokeStyle = "#345";
ctx.lineWidth = 2; ctx.lineWidth = 2;
ctx.arc(12, 0, 8 + 4 * Math.sin(m.cycle * 0.01), 0, 2 * Math.PI); //big eye ctx.arc(12, 0, amplitude, 0, 2 * Math.PI); //big eye
ctx.stroke(); ctx.stroke();
ctx.beginPath(); ctx.beginPath();
ctx.arc(12, 0, 8 + 4 * Math.sin(m.cycle * 0.01), 0, 2 * Math.PI); //big eye ctx.arc(12, 0, amplitude, 0, 2 * Math.PI); //big eye
ctx.fillStyle = `hsl(${150+100*Math.sin(m.cycle * 0.01)},100%,50%)` // ctx.fillStyle = `hsl(0,0%,${50+50*Math.sin(m.cycle * 0.0075+Math.PI)}%)` //`hsl(${150+50*Math.sin(m.cycle * 0.0075)},100%,50%)`
ctx.fill(); // ctx.fill();
ctx.stroke(); ctx.stroke();
ctx.restore(); ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
@@ -1339,29 +1336,33 @@ const m = {
dilate2() { dilate2() {
m.isAltSkin = true m.isAltSkin = true
m.draw = function() { m.draw = function() {
const amplitude = Math.sin(m.cycle * 0.0075)
ctx.fillStyle = m.fillColor; ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx; m.walk_cycle += m.flipLegs * m.Vx;
ctx.save(); ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20) ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.translate(m.pos.x, m.pos.y); ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3); m.calcLeg(Math.PI, -3);
m.drawLeg("#5f5f5f"); m.drawLeg("#456");
m.calcLeg(0, 0); m.calcLeg(0, 0);
m.drawLeg("#444"); m.drawLeg("#345");
ctx.rotate(m.angle); ctx.rotate(m.angle);
ctx.beginPath(); ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI); ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient ctx.fillStyle = m.bodyGradient
ctx.fill(); ctx.fill();
ctx.strokeStyle = "#444"; ctx.strokeStyle = "#345";
ctx.lineWidth = 3 + 3 * Math.sin(m.cycle * 0.01 + Math.PI); ctx.lineWidth = 3 + 3 * Math.sin(m.cycle * 0.0075 + Math.PI);
ctx.arc(12, 0, 6 + 3 * Math.sin(m.cycle * 0.01), 0, 2 * Math.PI); //big eye
ctx.stroke(); ctx.stroke();
// ctx.arc(12, 0, 8 + 4 * amplitude, 0, 2 * Math.PI); //big eye
ctx.beginPath(); ctx.beginPath();
ctx.arc(12, 0, 6 + 3 * Math.sin(m.cycle * 0.01), 0, 2 * Math.PI); //big eye ctx.arc(12, 0, 8 + 4 * amplitude, 0, 2 * Math.PI); //big eye
ctx.fillStyle = `hsl(${150+100*Math.sin(m.cycle * 0.01)},100%,50%)` ctx.fillStyle = "#345"
// ctx.fillStyle = //`hsl(0,0%,${50+50*Math.sin(m.cycle * 0.0075+Math.PI)}%)` //`hsl(${150+50*Math.sin(m.cycle * 0.0075)},100%,50%)`
// ctx.fillStyle = `hsl(${150 + 100 * amplitude},100%,50%)`
ctx.fill(); ctx.fill();
ctx.stroke(); // ctx.stroke();
ctx.restore(); ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw() powerUps.boost.draw()
@@ -1380,7 +1381,7 @@ const m = {
ctx.lineTo(m.knee.x, m.knee.y); ctx.lineTo(m.knee.x, m.knee.y);
ctx.lineTo(m.foot.x, m.foot.y); ctx.lineTo(m.foot.x, m.foot.y);
ctx.strokeStyle = stroke; ctx.strokeStyle = stroke;
ctx.lineWidth = 7; ctx.lineWidth = 6 + 2 * Math.sin(m.cycle * 0.0075 + Math.PI);
ctx.stroke(); ctx.stroke();
//toe lines //toe lines
@@ -1401,9 +1402,9 @@ const m = {
//foot joint //foot joint
ctx.moveTo(m.foot.x + 6, m.foot.y); ctx.moveTo(m.foot.x + 6, m.foot.y);
ctx.arc(m.foot.x, m.foot.y, 6, 0, 2 * Math.PI); ctx.arc(m.foot.x, m.foot.y, 6, 0, 2 * Math.PI);
ctx.fillStyle = m.fillColor; ctx.fillStyle = "#345";
ctx.fill(); ctx.fill();
ctx.lineWidth = 3 + 3 * Math.sin(m.cycle * 0.01 + Math.PI); ctx.lineWidth = 3 + 3 * Math.sin(m.cycle * 0.0075 + Math.PI);
ctx.stroke(); ctx.stroke();
ctx.restore(); ctx.restore();
} }
@@ -1417,10 +1418,11 @@ const m = {
} }
// m.setFillColors(); // m.setFillColors();
m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)` m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)`
m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 45}%)` m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 35}%)`
let grd = ctx.createLinearGradient(-30, 0, 30, 0); let grd = ctx.createLinearGradient(-30, 0, 30, 0);
grd.addColorStop(0, m.fillColorDark); grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor); grd.addColorStop(0.7, m.fillColor);
// grd.addColorStop(1, m.fillColor);
m.bodyGradient = grd m.bodyGradient = grd
m.draw = function() { m.draw = function() {
@@ -1430,10 +1432,10 @@ const m = {
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20) ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.translate(m.pos.x, m.pos.y); ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3); m.calcLeg(Math.PI, -3);
m.drawLeg("#3a3a3a"); m.drawLeg("#eee");
m.calcLeg(0, 0); m.calcLeg(0, 0);
m.drawLeg("#222"); m.drawLeg("#fff");
ctx.rotate(0.013 * simulation.cycle); ctx.rotate(0.017 * simulation.cycle);
ctx.beginPath(); ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI); ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient ctx.fillStyle = m.bodyGradient
@@ -1442,7 +1444,7 @@ const m = {
ctx.beginPath(); ctx.beginPath();
ctx.arc(m.pos.x + 15 * Math.cos(m.angle), m.pos.y + 15 * Math.sin(m.angle), 5, 0, 2 * Math.PI); ctx.arc(m.pos.x + 15 * Math.cos(m.angle), m.pos.y + 15 * Math.sin(m.angle), 5, 0, 2 * Math.PI);
ctx.fillStyle = "#222" ctx.fillStyle = "#000"
ctx.fill(); ctx.fill();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw() powerUps.boost.draw()
@@ -1461,7 +1463,7 @@ const m = {
ctx.lineTo(m.knee.x, m.knee.y); ctx.lineTo(m.knee.x, m.knee.y);
ctx.lineTo(m.foot.x, m.foot.y); ctx.lineTo(m.foot.x, m.foot.y);
ctx.strokeStyle = stroke; ctx.strokeStyle = stroke;
ctx.lineWidth = 7; ctx.lineWidth = 6;
ctx.stroke(); ctx.stroke();
//toe lines //toe lines
@@ -1470,19 +1472,19 @@ const m = {
ctx.lineTo(m.foot.x - 15, m.foot.y + 5); ctx.lineTo(m.foot.x - 15, m.foot.y + 5);
ctx.moveTo(m.foot.x, m.foot.y); ctx.moveTo(m.foot.x, m.foot.y);
ctx.lineTo(m.foot.x + 15, m.foot.y + 5); ctx.lineTo(m.foot.x + 15, m.foot.y + 5);
ctx.lineWidth = 4; ctx.lineWidth = 3;
ctx.stroke(); ctx.stroke();
//hip joint //hip joint
ctx.beginPath(); ctx.beginPath();
ctx.arc(m.hip.x, m.hip.y, 11, 0, 2 * Math.PI); ctx.arc(m.hip.x, m.hip.y, 11, 0, 2 * Math.PI);
//knee joint //knee joint
ctx.moveTo(m.knee.x + 7, m.knee.y); ctx.moveTo(m.knee.x + 5, m.knee.y);
ctx.arc(m.knee.x, m.knee.y, 7, 0, 2 * Math.PI); ctx.arc(m.knee.x, m.knee.y, 5, 0, 2 * Math.PI);
//foot joint //foot joint
ctx.moveTo(m.foot.x + 6, m.foot.y); ctx.moveTo(m.foot.x + 5, m.foot.y);
ctx.arc(m.foot.x, m.foot.y, 6, 0, 2 * Math.PI); ctx.arc(m.foot.x, m.foot.y, 5, 0, 2 * Math.PI);
ctx.fillStyle = m.fillColor; ctx.fillStyle = "#000";
ctx.fill(); ctx.fill();
// ctx.lineWidth = 2; // ctx.lineWidth = 2;
// ctx.stroke(); // ctx.stroke();
@@ -2438,7 +2440,7 @@ const m = {
case 5: //plasma case 5: //plasma
return `<strong>+${(15*couple).toFixed(0)}%</strong> <strong class='color-d'>damage</strong>` return `<strong>+${(15*couple).toFixed(0)}%</strong> <strong class='color-d'>damage</strong>`
case 6: //time dilation case 6: //time dilation
return `<strong>+${(30*couple).toFixed(0)}%</strong> longer <strong style='letter-spacing: 2px;'>stopped time</strong>` //<strong>movement</strong>, <strong>jumping</strong>, and return `<strong>+${(50*couple).toFixed(0)}%</strong> longer <strong style='letter-spacing: 2px;'>stopped time</strong>` //<strong>movement</strong>, <strong>jumping</strong>, and
case 7: //cloaking case 7: //cloaking
return `<strong>+${(33*couple).toFixed(0)}%</strong> ambush <strong class='color-d'>damage</strong>` return `<strong>+${(33*couple).toFixed(0)}%</strong> ambush <strong class='color-d'>damage</strong>`
case 8: //pilot wave case 8: //pilot wave
@@ -2517,7 +2519,7 @@ const m = {
}, },
fieldUpgrades: [{ fieldUpgrades: [{
name: "field emitter", name: "field emitter",
imageNumber: Math.floor(Math.random() * 17), imageNumber: Math.floor(Math.random() * 20),
description: `use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs description: `use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs
<br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second`, // <br><strong>100</strong> max <strong class='color-f'>energy</strong> <br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second`, // <br><strong>100</strong> max <strong class='color-f'>energy</strong>
effect: () => { effect: () => {
@@ -2811,7 +2813,7 @@ const m = {
} else if (input.field) { //not hold but field button is pressed } else if (input.field) { //not hold but field button is pressed
//float while field is on //float while field is on
const angleReduction = 0.5 + 0.7 * (Math.PI / 2 - Math.min(Math.PI / 2, Math.abs(m.angle + Math.PI / 2))) const angleReduction = 0.5 + 0.7 * (Math.PI / 2 - Math.min(Math.PI / 2, Math.abs(m.angle + Math.PI / 2)))
console.log(angleReduction) // console.log(angleReduction)
if (player.velocity.y > 1) { if (player.velocity.y > 1) {
player.force.y -= angleReduction * (tech.isBigField ? 0.95 : 0.5) * player.mass * simulation.g; player.force.y -= angleReduction * (tech.isBigField ? 0.95 : 0.5) * player.mass * simulation.g;
Matter.Body.setVelocity(player, { Matter.Body.setVelocity(player, {
@@ -3606,16 +3608,16 @@ const m = {
}, },
{ {
name: "time dilation", name: "time dilation",
description: "use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 2px;'>stop time</strong><br><strong>+25%</strong> movement and <strong><em>fire rate</em></strong><br>generate <strong>14</strong> <strong class='color-f'>energy</strong> per second", description: "use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 2px;'>stop time</strong><br><strong>+20%</strong> movement and <strong><em>fire rate</em></strong><br>generate <strong>14</strong> <strong class='color-f'>energy</strong> per second",
set() { set() {
// m.fieldMeterColor = "#0fc" // m.fieldMeterColor = "#0fc"
// m.fieldMeterColor = "#ff0" // m.fieldMeterColor = "#ff0"
m.fieldMeterColor = "#3fe" m.fieldMeterColor = "#3fe"
m.eyeFillColor = m.fieldMeterColor m.eyeFillColor = m.fieldMeterColor
m.fieldFx = 1.3 m.fieldFx = 1.25
// m.fieldJump = 1.09 // m.fieldJump = 1.09
m.setMovement(); m.setMovement();
b.setFireCD()
const timeStop = () => { const timeStop = () => {
m.immuneCycle = m.cycle + 10; //immune to harm while time is stopped, this also disables regen m.immuneCycle = m.cycle + 10; //immune to harm while time is stopped, this also disables regen
//draw field everywhere //draw field everywhere
@@ -3666,7 +3668,7 @@ const m = {
m.throwBlock(); m.throwBlock();
m.wakeCheck(); m.wakeCheck();
} else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
const drain = 0.002 / (1 + 0.3 * m.coupling) const drain = 0.002 / (1 + 0.5 * m.coupling)
if (m.energy > drain) m.energy -= drain if (m.energy > drain) m.energy -= drain
m.grabPowerUp(); m.grabPowerUp();
@@ -3814,7 +3816,7 @@ const m = {
ctx.fillStyle = "#fff" ctx.fillStyle = "#fff"
ctx.lineWidth = 2; ctx.lineWidth = 2;
ctx.strokeStyle = "#000" ctx.strokeStyle = "#000"
ctx.stroke() // ctx.stroke()
ctx.globalCompositeOperation = "destination-in"; ctx.globalCompositeOperation = "destination-in";
ctx.fill(); ctx.fill();
ctx.globalCompositeOperation = "source-over"; ctx.globalCompositeOperation = "source-over";
@@ -3925,11 +3927,36 @@ const m = {
// if (m.cycle > m.lastKillCycle + 240) { // if (m.cycle > m.lastKillCycle + 240) {
// if (m.sneakAttackCharge > 0) { // if (m.sneakAttackCharge > 0) {
if (m.sneakAttackCycle + Math.min(120, 0.7 * (m.cycle - m.enterCloakCycle)) > m.cycle) { if (m.sneakAttackCycle + Math.min(120, 0.7 * (m.cycle - m.enterCloakCycle)) > m.cycle) {
// ctx.strokeStyle = "rgba(0,0,0,0.2)"
// ctx.lineWidth = 1
// ctx.fillStyle = "rgba(0,0,0,0.02)"
// for (let i = 0; i < 4; i++) {
// ctx.beginPath();
// ctx.ellipse(m.pos.x, m.pos.y, 50, 30, 0.2 * m.cycle + i * Math.PI / 4, 0, 2 * Math.PI);
// ctx.stroke()
// // ctx.fill();
// }
ctx.strokeStyle = "rgba(0,0,0,0.5)" //m.fieldMeterColor; //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})` ctx.strokeStyle = "rgba(0,0,0,0.5)" //m.fieldMeterColor; //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})`
ctx.beginPath(); ctx.beginPath();
ctx.arc(m.pos.x, m.pos.y, 28, 0, 2 * Math.PI); ctx.arc(simulation.mouseInGame.x, simulation.mouseInGame.y, 16, 0, 2 * Math.PI);
ctx.lineWidth = 3 // ctx.lineWidth = 3
ctx.stroke(); ctx.fillStyle = "rgba(0,0,0,0.2)"
ctx.fill();
// const unit = Vector.add(m.pos, Vector.rotate({ x: 45, y: 0 }, 2 * Math.PI * Math.random()))
// simulation.drawList.push({ //add dmg to draw queue
// x: unit.x,
// y: unit.y,
// radius: 4 + 10 * Math.random(),
// color: 'rgba(0, 0, 0, 0.1)',
// time: 15
// });
} }
} }
} }
@@ -4388,10 +4415,7 @@ const m = {
m.fieldRange *= 0.8 m.fieldRange *= 0.8
if ((m.fieldMode === 0 || m.fieldMode === 9) && m.immuneCycle < m.cycle) m.energy += 0.2 * m.coupling if ((m.fieldMode === 0 || m.fieldMode === 9) && m.immuneCycle < m.cycle) m.energy += 0.2 * m.coupling
if (tech.isWormholeWorms) { //pandimensional spermia if (tech.isWormholeWorms) { //pandimensional spermia
b.worm(Vector.add(m.hole.pos2, Vector.rotate({ b.worm(Vector.add(m.hole.pos2, Vector.rotate({ x: m.fieldRange * 0.4, y: 0 }, 2 * Math.PI * Math.random())))
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -10)); Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -10));
// for (let i = 0, len = Math.ceil(1.25 * Math.random()); i < len; i++) { // for (let i = 0, len = Math.ceil(1.25 * Math.random()); i < len; i++) {
// } // }
@@ -4467,7 +4491,7 @@ const m = {
if (input.field) { if (input.field) {
if (tech.isWormHolePause) { if (tech.isWormHolePause) {
const drain = m.fieldRegen + 0.0004 const drain = m.fieldRegen + 0.0002
if (m.energy > drain) { if (m.energy > drain) {
m.energy -= drain m.energy -= drain
if (m.immuneCycle < m.cycle + 1) m.immuneCycle = m.cycle + 1; //player is immune to damage for 1 cycle if (m.immuneCycle < m.cycle + 1) m.immuneCycle = m.cycle + 1; //player is immune to damage for 1 cycle
@@ -5067,7 +5091,7 @@ const m = {
) { ) {
mob[k].foundPlayer(); mob[k].foundPlayer();
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0 let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0
if (tech.isRewindAvoidDeath && (m.energy + 0.05) > Math.min(1, m.maxEnergy) && dmg > 0.01) { //CPT reversal runs in m.damage, but it stops the rest of the collision code here too if (tech.isRewindAvoidDeath && (m.energy + 0.05) > Math.min(0.95, m.maxEnergy) && dmg > 0.01) { //CPT reversal runs in m.damage, but it stops the rest of the collision code here too
m.damage(dmg); m.damage(dmg);
return return
} }

View File

@@ -39,43 +39,43 @@ const powerUps = {
return `<div class="research-circle"></div> ` return `<div class="research-circle"></div> `
case 2: case 2:
return `<span style="position:relative;"> return `<span style="position:relative;">
<div class="research-circle" style="position:absolute; top:0; left:0;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:0;"></div>
<div class="research-circle" style="position:absolute; top:0; left:7px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:7px;"></div>
</span> &nbsp; &nbsp; &nbsp; &nbsp;` </span> &nbsp; &nbsp; &nbsp; &nbsp;`
case 3: case 3:
return `<span style="position:relative;"> return `<span style="position:relative;">
<div class="research-circle" style="position:absolute; top:0; left:0;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:0;"></div>
<div class="research-circle" style="position:absolute; top:0; left:8px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:8px;"></div>
<div class="research-circle" style="position:absolute; top:0; left:16px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:16px;"></div>
</span> &nbsp; &nbsp; &nbsp; &nbsp; &thinsp; ` </span> &nbsp; &nbsp; &nbsp; &nbsp; &thinsp; `
case 4: case 4:
return `<span style="position:relative;"> return `<span style="position:relative;">
<div class="research-circle" style="position:absolute; top:0; left:0;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:0;"></div>
<div class="research-circle" style="position:absolute; top:0; left:8px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:8px;"></div>
<div class="research-circle" style="position:absolute; top:0; left:16px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:16px;"></div>
<div class="research-circle" style="position:absolute; top:0; left:24px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:24px;"></div>
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ` </span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; `
case 5: case 5:
return `<span style="position:relative;"> return `<span style="position:relative;">
<div class="research-circle" style="position:absolute; top:0; left:0;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:0;"></div>
<div class="research-circle" style="position:absolute; top:0; left:8px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:8px;"></div>
<div class="research-circle" style="position:absolute; top:0; left:16px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:16px;"></div>
<div class="research-circle" style="position:absolute; top:0; left:24px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:24px;"></div>
<div class="research-circle" style="position:absolute; top:0; left:32px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:32px;"></div>
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ` </span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; `
case 6: case 6:
return `<span style="position:relative;"> return `<span style="position:relative;">
<div class="research-circle" style="position:absolute; top:0; left:0;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:0;"></div>
<div class="research-circle" style="position:absolute; top:0; left:8px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:8px;"></div>
<div class="research-circle" style="position:absolute; top:0; left:16px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:16px;"></div>
<div class="research-circle" style="position:absolute; top:0; left:24px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:24px;"></div>
<div class="research-circle" style="position:absolute; top:0; left:32px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:32px;"></div>
<div class="research-circle" style="position:absolute; top:0; left:40px;"></div> <div class="research-circle" style="position:absolute; top:1.5px; left:40px;"></div>
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ` </span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; `
} }
let text = '<span style="position:relative;">' let text = '<span style="position:relative;">'
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
text += `<div class="research-circle" style="position:absolute; top:0; left:${i*8}px;"></div>` text += `<div class="research-circle" style="position:absolute; top:1.5px; left:${i*8}px;"></div>`
} }
text += '</span> &nbsp; &nbsp; ' text += '</span> &nbsp; &nbsp; '
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
@@ -720,7 +720,19 @@ const powerUps = {
<div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[choose].name} ${techCountText}</div> <div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>` ${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
}, },
skinTechText(choose, click) {
const techCountText = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : "";
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/${tech.tech[choose].name}.webp');"`
return `<div class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}"${style}>
<div class="card-text">
<div class="grid-title">
<span style="position:relative;">
<div class="circle-grid-skin"></div>
<div class="circle-grid-skin-eye"></div>
</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
},
fieldTechText(choose, click) { fieldTechText(choose, click) {
const techCountText = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : ""; const techCountText = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : "";
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/${tech.tech[choose].name}.webp');"` const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/${tech.tech[choose].name}.webp');"`
@@ -993,10 +1005,10 @@ const powerUps = {
text += powerUps.fieldTechText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.fieldTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isGunTech) { } else if (tech.tech[choose].isGunTech) {
text += powerUps.gunTechText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.gunTechText(choose, `powerUps.choose('tech',${choose})`)
// } else if (tech.tech[choose].isLore) {
// text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
} else if (tech.tech[choose].isJunk) { } else if (tech.tech[choose].isJunk) {
text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isSkin) {
text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`)
} else { //normal tech } else { //normal tech
text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`)
} }
@@ -1127,6 +1139,8 @@ const powerUps = {
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>` text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
} else if (tech.tech[choose].isJunk) { } else if (tech.tech[choose].isJunk) {
text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isSkin) {
text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`)
} else { //normal tech } else { //normal tech
text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`)
} }

View File

@@ -930,8 +930,15 @@ const simulation = {
tech.deathSpawnsFromBoss = 0; tech.deathSpawnsFromBoss = 0;
simulation.fallHeight = 3000; simulation.fallHeight = 3000;
document.body.style.backgroundColor = "#eee" //"#d8dadf"; document.body.style.backgroundColor = "#eee" //"#d8dadf";
color.map = "#444"; // color.map = "#444";
// color.bullet = "#FFFFFF";
color = { //light
// background: "#ddd", // used instead: document.body.style.backgroundColor
block: "rgba(140,140,140,0.85)",
blockS: "#222",
map: "#444",
bullet: "#000"
}
m.fireCDcycle = 0 m.fireCDcycle = 0
m.drop(); m.drop();
m.hole.isOn = false; m.hole.isOn = false;

View File

@@ -3764,18 +3764,6 @@ const spawn = {
this.pushAway(Math.sqrt(this.flapRate) * 0.13, Math.sqrt(this.flapRate) * 0.06) //this.flapRate = 0.2, +0.13x3 -> 0.6 this.pushAway(Math.sqrt(this.flapRate) * 0.13, Math.sqrt(this.flapRate) * 0.06) //this.flapRate = 0.2, +0.13x3 -> 0.6
me.babies(0.05 * simulation.difficulty + 1) me.babies(0.05 * simulation.difficulty + 1)
} }
// //draw wings as if they are protecting
// const wingShield = (a, size) => {
// ctx.beginPath();
// const perp = { x: Math.cos(a), y: Math.sin(a) } //
// const where = Vector.add(this.position, Vector.mult(perp, 0.2 * this.radius))
// ctx.ellipse(where.x, where.y, size, size * 0.8, a, 0, 2 * Math.PI)
// ctx.fillStyle = this.fill = `hsla(${160+40*Math.random()}, 100%, ${25 + 25*Math.random()*Math.random()}%, 0.9)`; //"rgba(0,235,255,0.3)"; // ctx.fillStyle = `hsla(44, 79%, 31%,0.4)`; //"rgba(0,235,255,0.3)";
// ctx.fill();
// }
// wingShield(this.angle + Math.PI / 2, radius * 1.3)
// wingShield(this.angle - Math.PI / 2, radius * 1.3)
//draw invulnerable //draw invulnerable
ctx.beginPath(); ctx.beginPath();
let vertices = this.vertices; let vertices = this.vertices;
@@ -5943,7 +5931,7 @@ const spawn = {
ctx.lineTo(vertices[j].x, vertices[j].y); ctx.lineTo(vertices[j].x, vertices[j].y);
} }
ctx.lineTo(vertices[0].x, vertices[0].y); ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 1; // ctx.lineWidth = 1;
ctx.fillStyle = `rgba(255,255,255,${this.alpha * this.alpha})`; ctx.fillStyle = `rgba(255,255,255,${this.alpha * this.alpha})`;
ctx.fill(); ctx.fill();
} else if (this.isNotCloaked) { } else if (this.isNotCloaked) {
@@ -7460,17 +7448,19 @@ const spawn = {
mobs.spawn(x, y, 8, radius, "rgb(0,60,80)"); mobs.spawn(x, y, 8, radius, "rgb(0,60,80)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.g = 0.0001; //required if using this.gravity
me.accelMag = 0.002 * simulation.accelScale;
me.memory = 20;
Matter.Body.setDensity(me, 0.0005 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.0005 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.nextHealthThreshold = 0.75
me.invulnerableCount = 0
me.g = 0.0001; //required if using this.gravity
me.accelMag = 0.0012 + 0.0013 * simulation.accelScale;
me.memory = 20;
me.repulsionRange = 1800 * 1800
cons[cons.length] = Constraint.create({ cons[cons.length] = Constraint.create({
pointA: { pointA: { x: constraint.x, y: constraint.y },
x: constraint.x,
y: constraint.y
},
bodyB: me, bodyB: me,
stiffness: 0.00012 stiffness: 0.00012
}); });
@@ -7481,42 +7471,74 @@ const spawn = {
me.onDeath = function() { me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
this.removeCons(); //remove constraint this.removeCons(); //remove constraint
//spawn seekers me.babies(0.05 * simulation.difficulty + 1)
// for (let i = 0, len = 100; i < len; i++) { };
// const unit = Vector.rotate({ x: 10 + i, y: 0 }, Math.random() * 6.28) me.babies = function(len) {
// const where = Vector.add(this.position, unit) const delay = Math.max(3, Math.floor(15 - len / 2))
// spawn.seeker(where.x, where.y); //(x, y, radius = 8, sides = 6)
// }
const delay = 4
let i = 0 let i = 0
const len = 3 * simulation.difficulty
let spawnFlutters = () => { let spawnFlutters = () => {
if (i < len) { if (i < len) {
if (!(simulation.cycle % delay) && !simulation.paused && !simulation.isChoosing && m.alive) { if (!(simulation.cycle % delay) && !simulation.paused && !simulation.isChoosing && m.alive) {
const unit = Vector.rotate({ x: radius * Math.random(), y: 0 }, Math.random() * 6.28) // const phase = i / len * 2 * Math.PI
const where = Vector.add(this.position, unit) // const where = Vector.add(this.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5))
spawn.seeker(where.x, where.y); //(x, y, radius = 8, sides = 6) const unit = Vector.normalise(Vector.sub(player.position, this.position))
const velocity = Vector.mult(unit, 10 + 10 * Math.random())
const where = Vector.add(this.position, Vector.mult(unit, radius * 1.2))
spawn.allowShields = false
spawn.flutter(where.x, where.y, Math.floor(9 + 8 * Math.random()))
const who = mob[mob.length - 1]
Matter.Body.setDensity(who, 0.01); //extra dense //normal is 0.001 //makes effective life much larger
Matter.Body.setVelocity(who, velocity);
Matter.Body.setAngle(who, Math.atan2(velocity.y, velocity.x))
this.alertNearByMobs();
spawn.allowShields = true
i++ i++
} }
requestAnimationFrame(spawnFlutters); requestAnimationFrame(spawnFlutters);
} }
} }
requestAnimationFrame(spawnFlutters); requestAnimationFrame(spawnFlutters);
simulation.drawList.push({ //add dmg to draw queue }
x: this.position.x, me.onDamage = function() {
y: this.position.y, if (this.health < this.nextHealthThreshold && this.alive) {
radius: radius * 0.9, this.health = this.nextHealthThreshold - 0.01
color: "rgba(255,0,255,0.2)", this.nextHealthThreshold = Math.floor(this.health * 4) / 4
time: len * (delay - 1) this.invulnerableCount = 90 + Math.floor(30 * Math.random())
}); this.isInvulnerable = true
this.damageReduction = 0
}
}; };
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.do = function() { me.do = function() {
// this.armor();
this.gravity(); this.gravity();
this.seePlayerCheck(); if (this.isInvulnerable) {
this.checkStatus(); this.repulsion();
this.attraction(); this.invulnerableCount--
if (this.invulnerableCount < 0) {
this.isInvulnerable = false
this.damageReduction = this.startingDamageReduction
this.frictionAir = 0.05
me.babies(0.07 * simulation.difficulty + 2)
if (this.radius > 15) {
const scale = 0.88;
Matter.Body.scale(this, scale, scale);
this.radius *= scale;
}
}
//draw invulnerable
ctx.beginPath();
let vertices = this.vertices;
ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 13 + 5 * Math.random();
ctx.strokeStyle = `rgba(255,255,255,${0.5+0.2*Math.random()})`;
ctx.stroke();
} else {
this.seePlayerCheck();
this.checkStatus();
this.attraction();
}
}; };
}, },
shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance(), isExtraShield = false) { shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance(), isExtraShield = false) {

View File

@@ -220,13 +220,14 @@ const tech = {
damage: 1, //used for tech changes to player damage that don't have complex conditions damage: 1, //used for tech changes to player damage that don't have complex conditions
damageFromTech() { damageFromTech() {
let dmg = tech.damage //m.fieldDamage let dmg = tech.damage //m.fieldDamage
if (tech.isDilate) dmg *= 1.25 + Math.sin(m.cycle * 0.01) if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.78 : 1.88
if (tech.isDilate) dmg *= 1.5 + Math.sin(m.cycle * 0.0075)
if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.31 * b.inventory.length if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.31 * b.inventory.length
if (powerUps.boost.endCycle > m.cycle) dmg *= 1 + powerUps.boost.damage if (powerUps.boost.endCycle > m.cycle) dmg *= 1 + powerUps.boost.damage
if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.15 * m.coupling if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.15 * m.coupling
if (m.isSneakAttack && m.sneakAttackCycle + Math.min(120, 0.5 * (m.cycle - m.enterCloakCycle)) > m.cycle) dmg *= 4.33 * (1 + 0.33 * m.coupling) if (m.isSneakAttack && m.sneakAttackCycle + Math.min(120, 0.5 * (m.cycle - m.enterCloakCycle)) > m.cycle) dmg *= 4.33 * (1 + 0.33 * m.coupling)
if (tech.deathSkipTime) dmg *= 1 + 0.6 * tech.deathSkipTime if (tech.deathSkipTime) dmg *= 1 + 0.6 * tech.deathSkipTime
if (tech.isTechDebt) dmg *= Math.max(41 / (tech.totalCount + 21), 4 - 0.15 * tech.totalCount) if (tech.isTechDebt) dmg *= Math.max(Math.pow(0.85, tech.totalCount - 20), 4 - 0.15 * tech.totalCount)
if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555 if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555
if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599 if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance()) if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
@@ -331,6 +332,7 @@ const tech = {
count: 0, count: 0,
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
isSkin: true,
allowed() { allowed() {
return !m.isAltSkin return !m.isAltSkin
}, },
@@ -352,7 +354,7 @@ const tech = {
}, },
{ {
name: "aperture", name: "aperture",
description: "your <strong class='color-d'>damage</strong> cycles every <strong>6</strong> seconds<br>between <strong>-75%</strong> and <strong>+125%</strong> <strong class='color-d'>damage</strong>", description: "every <strong>6</strong> seconds your <strong class='color-d'>damage</strong> cycles<br>between <strong>-50%</strong> and <strong>+150%</strong> <strong class='color-d'>damage</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -373,7 +375,7 @@ const tech = {
}, },
{ {
name: "diaphragm", name: "diaphragm",
description: "your <strong class='color-defense'>defense</strong> cycles every <strong>6</strong> seconds<br>between <strong>+100%</strong> and <strong>-33%</strong> <strong class='color-defense'>defense</strong>", description: "every <strong>6</strong> seconds your <strong class='color-defense'>defense</strong> cycles<br>between <strong>+100%</strong> and <strong>-33%</strong> <strong class='color-defense'>defense</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
@@ -396,7 +398,7 @@ const tech = {
{ {
name: "mass-energy equivalence", name: "mass-energy equivalence",
// description: "<strong class='color-f'>energy</strong> protects you instead of <strong class='color-h'>health</strong><br>√ of <strong class='color-defense'>defense</strong> <strong>reduction</strong> reduces max <strong class='color-f'>energy</strong>", // description: "<strong class='color-f'>energy</strong> protects you instead of <strong class='color-h'>health</strong><br>√ of <strong class='color-defense'>defense</strong> <strong>reduction</strong> reduces max <strong class='color-f'>energy</strong>",
description: "<strong class='color-f'>energy</strong> protects you instead of <strong class='color-h'>health</strong><br>exponentially <strong>reduced</strong> <strong class='color-defense'>defense</strong> <em>(~ x^0.12)</em>", description: "<strong class='color-f'>energy</strong> protects you instead of <strong class='color-h'>health</strong><br>exponentially <strong>reduced</strong> <strong class='color-defense'>defense</strong> <em>(~ x^0.13)</em>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2104,7 +2106,6 @@ const tech = {
count: 0, count: 0,
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
isSkin: true,
allowed() { allowed() {
return !tech.isRelay return !tech.isRelay
}, },
@@ -2257,7 +2258,6 @@ const tech = {
count: 0, count: 0,
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
isSkin: true,
allowed() { allowed() {
return !tech.isFlipFlop return !tech.isFlipFlop
}, },
@@ -3482,9 +3482,9 @@ const tech = {
} }
}, },
{ {
name: "technical debt", // overengineering name: "technical debt",
descriptionFunction() { descriptionFunction() {
return `<strong>+300%</strong> <strong class='color-d'>damage</strong> <strong>15%</strong> <strong class='color-d'>damage</strong><br>for each <strong class='color-m'>tech</strong> you have learned <em>(-${Math.floor(100*(Math.max(41 / (tech.totalCount + 21), 4 - 0.15 * tech.totalCount) ))-100}%)</em>` return `<strong>+300%</strong> <strong class='color-d'>damage</strong> <strong>15%</strong> <strong class='color-d'>damage</strong><br>for each <strong class='color-m'>tech</strong> you have learned <em>(${(Math.floor(100*(Math.min(Math.pow(0.85, tech.totalCount-20), 4 - 0.15 * tech.totalCount)))-100)}%)</em>`
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -4274,7 +4274,7 @@ const tech = {
allowed() { allowed() {
return ((tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.nailRecoil && !tech.isRicochet) || (tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isFoamShot && !tech.isSporeWorm && !tech.isSporeFlea)) && !tech.isRivets && !tech.isIncendiary && !tech.isIceCrystals && !tech.isIceShot return ((tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.nailRecoil && !tech.isRicochet) || (tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isFoamShot && !tech.isSporeWorm && !tech.isSporeFlea)) && !tech.isRivets && !tech.isIncendiary && !tech.isIceCrystals && !tech.isIceShot
}, },
requires: "nail gun, shotgun, not ice crystal, rivets, rotary cannon, or pneumatic, incendiary, nail-shot, rivets, foam-shot, worm-shot, ice-shot", requires: "nail gun, shotgun, not ice crystal, rivets, rotary cannon, pneumatic, incendiary, nail-shot, foam-shot, worm-shot, ice-shot",
effect() { effect() {
tech.isNeedles = true tech.isNeedles = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -7396,6 +7396,25 @@ const tech = {
} }
} }
}, },
{
name: "aerostat",
description: `<strong>+88%</strong> <strong class='color-d'>damage</strong> while <strong>off</strong> the <strong>ground</strong><br><strong>-22%</strong> <strong class='color-d'>damage</strong> while <strong>on</strong> the <strong>ground</strong>`,
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "negative mass"
},
requires: "negative mass",
effect() {
tech.isNoGroundDamage = true
},
remove() {
tech.isNoGroundDamage = false
}
},
{ {
name: "annihilation", name: "annihilation",
description: "after <strong>colliding</strong> with non-boss mobs<br>they are <strong>annihilated</strong> and <strong>33%</strong> <strong class='color-f'>energy</strong>", description: "after <strong>colliding</strong> with non-boss mobs<br>they are <strong>annihilated</strong> and <strong>33%</strong> <strong class='color-f'>energy</strong>",
@@ -8025,7 +8044,7 @@ const tech = {
{ {
name: "symbiosis", name: "symbiosis",
descriptionFunction() { descriptionFunction() {
return `after a <strong>boss</strong> <strong>dies</strong> spawn a <strong class='color-m'>tech</strong>, ${powerUps.orb.ammo(1)}, ${powerUps.orb.research(1)}, and ${powerUps.orb.heal(1)}<br>after a <strong>mob</strong> <strong>dies</strong> <strong>0.5</strong> maximum ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"}` return `after a <strong>boss</strong> <strong>dies</strong> spawn ${powerUps.orb.research(3)}${powerUps.orb.heal(3)} and a <strong class='color-m'>tech</strong><br>after a <strong>mob</strong> <strong>dies</strong> <strong>0.5</strong> maximum ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"}`
}, },
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
@@ -8176,28 +8195,28 @@ const tech = {
}, },
{ {
name: "vacuum fluctuation", name: "vacuum fluctuation",
description: `use ${powerUps.orb.research(5)}to exploit your <strong class='color-f'>field</strong> for a<br><strong>+11%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>`, description: `use ${powerUps.orb.research(4)}to exploit your <strong class='color-f'>field</strong> for a<br><strong>+11%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>`,
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 3, frequency: 3,
frequencyDefault: 3, frequencyDefault: 3,
allowed() { allowed() {
return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "negative mass" || m.fieldUpgrades[m.fieldMode].name === "time dilation" || m.fieldUpgrades[m.fieldMode].name === "wormhole") && (build.isExperimentSelection || powerUps.research.count > 4) return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "negative mass" || m.fieldUpgrades[m.fieldMode].name === "time dilation" || m.fieldUpgrades[m.fieldMode].name === "wormhole") && (build.isExperimentSelection || powerUps.research.count > 3)
}, },
requires: "wormhole, time dilation, negative mass, pilot wave", requires: "wormhole, time dilation, negative mass, pilot wave",
effect() { effect() {
tech.fieldDuplicate = 0.11 tech.fieldDuplicate = 0.11
powerUps.setDupChance(); //needed after adjusting duplication chance powerUps.setDupChance(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.11); if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.11);
for (let i = 0; i < 5; i++) { for (let i = 0; i < 4; i++) {
if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
} }
}, },
remove() { remove() {
tech.fieldDuplicate = 0 tech.fieldDuplicate = 0
powerUps.setDupChance(); //needed after adjusting duplication chance powerUps.setDupChance(); //needed after adjusting duplication chance
if (this.count > 0) powerUps.research.changeRerolls(5) if (this.count > 0) powerUps.research.changeRerolls(4)
} }
}, },
// { // {
@@ -11325,4 +11344,5 @@ const tech = {
isDilate: null, isDilate: null,
isDiaphragm: null, isDiaphragm: null,
hardLanding: null, hardLanding: null,
isNoGroundDamage: null,
} }

View File

@@ -812,7 +812,31 @@ summary {
display: inline-block; display: inline-block;
margin-bottom: -0.3em; margin-bottom: -0.3em;
} }
.circle-grid-skin {
width: 1.25em;
height: 1.25em;
border-radius: 50%;
display: inline-block;
background-color: #fff;
opacity: 0.8;
border: 0.08em solid #222;
position: absolute;
top:-0.05em;
left:0em;
margin-bottom: -0.3em;
}
.circle-grid-skin-eye {
width: 0.18em;
height: 0.18em;
border-radius: 50%;
display: inline-block;
background-color: #fff;
border: 0.08em solid #222;
position: absolute;
top: 0.45em;
left: 0.9em;
margin-bottom: -0.3em;
}
.junk { .junk {
background-color: hsl(254, 44%, 75%); background-color: hsl(254, 44%, 75%);
border-radius: 25%; border-radius: 25%;

View File

@@ -1,25 +1,61 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
tech: elasticity - skin, does "crouch landings" a tiny bit more tech: aerostat - +88% damage off the ground, but -22% damage on the ground
jump and move faster, +15% defense negative mass field required
(replaces squirrel cage rotor)
tech: diaphragm - skin, defense cycles between -33% and +100% tetherBoss now has beetle babies, and immunity
requires aperture skins have a unique orb for their description card
and some new images
cloaking field has a new graphic for sneak attack on the cross hairs
tungsten carbide 150->200 maximum health new community map yingYang by Richard0820
but now does "crouch landings" a more
Zectron damage 80->100% and it does a bit less harm to player
flip-flop, relay switch are no longer skins
pause brings up the most recent in game console message
in game console no longer fades out it just instantly goes on and off
bug fixes bug fixes
*********************************************************** TODO ***************************************************** *********************************************************** TODO *****************************************************
live updating defense and damage HUD?
makes more sense for defense
for damage many effects only apply to one type of damage so it would show up
update frequency
per s
every cycle? (only if canvas)
don't include difficulty effects
draw in canvas or html?
add border for readability
a number
bars
horizontal
vertical
circles
defense
color: grey, white
scales from 0-1
wrapped around health bar like armor
what about mass-energy which has no health bar
at defense = 1 outlines health bar fully
health bar
color: keep red (green?)
red is the same as mob health bars
damage
color: red if not used for health
scales from 1-infinity maps to 0->1
1-1/(1+damage)
map element - conveyor belt
for blocks, player, power ups touching map element apply vector force
perfect diamagnatism could bounce on mobs, or even map elements?
could work like a rocket jump?
field tech: negative mass, wormhole?
tech: do 60% damage when not touching ground
tech: 50% defense when not touching ground
Tech: Von Neuman probes - Drones will consume blocks to replicate themselves Tech: Von Neuman probes - Drones will consume blocks to replicate themselves
it's a little too similar to the drone repair tech, but I kinda like it better. drones that eat blocks and spit out more drones is cool it's a little too similar to the drone repair tech, but I kinda like it better. drones that eat blocks and spit out more drones is cool