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="n-gon">
<option value="vats">
<option value="yingYang">
<option value="basement">
<option value="stronghold">
<option value="stereo madness">
<option value="stereoMadness">
<option value="house">
<option value="dripp">
<option value="crossfire">

View File

@@ -286,7 +286,7 @@ const b = {
fireCDscale: 1,
setFireCD() {
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.isFireRateForGuns) b.fireCDscale *= Math.pow(0.82, Math.max(0, b.inventory.length - 1))
if (tech.isFireMoveLock) b.fireCDscale *= 0.55
@@ -6377,7 +6377,7 @@ const b = {
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
}
if (!mob[j].isShielded) {
// if (!mob[j].isShielded) {
Matter.Body.setVelocity(mob[j], { //friction
x: mob[j].velocity.x * 0.95,
y: mob[j].velocity.y * 0.95
@@ -6393,7 +6393,7 @@ const b = {
//damage
mob[j].locatePlayer();
mob[j].damage(damage / Math.sqrt(mob[j].radius));
}
// }
if (tech.isPhononWave && this.phononWaveCD < m.cycle) {
this.phononWaveCD = m.cycle + 8 * (1 + this.waves[i].resonanceCount)
this.waves.push({
@@ -7110,7 +7110,10 @@ const b = {
},
doStream() {},
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 SPEED = (input.down ? 1.2 : 1) * Math.max(2, 14 - radius * 0.25)
const dir = m.angle + 0.15 * (Math.random() - 0.5)
@@ -7162,7 +7165,10 @@ const b = {
}
},
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 SPEED = (input.down ? 1.2 : 1) * Math.max(2, 14 - radius * 0.25)
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
if (m.isCloak) dmg *= 0.75
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);
return
}

View File

@@ -54,7 +54,7 @@ const cat = {
phased: 0x100000000,
}
const color = { //light
let color = { //light
// background: "#ddd", // used instead: document.body.style.backgroundColor
block: "rgba(140,140,140,0.85)",
blockS: "#222",
@@ -335,7 +335,7 @@ const build = {
<span style="float: right;">press ${input.key.pause} to resume</span>
<br>
<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)}%
${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>": ""}
@@ -424,6 +424,9 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
} 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 += 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 {
text += `<div id="${i}-pause-tech" class="pause-grid-module card-background ${ejectClass}" onclick="powerUps.pauseEjectTech(${i})" ${style}>`
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>
${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) {
return `<div class="card-text"> <div class="grid-title">
<span style="position:relative;">
@@ -565,6 +576,9 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
} else if (tech.tech[i].isJunk) {
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>`
} else if (tech.tech[i].isSkin) {
techID.classList.remove('experiment-grid-hide');
techID.innerHTML = build.skinTechText(i)
} else {
techID.innerHTML = build.techText(i)
}
@@ -588,6 +602,8 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
techID.innerHTML = build.gunTechText(i)
} else if (tech.tech[i].isJunk) {
techID.innerHTML = build.junkTechText(i)
} else if (tech.tech[i].isSkin) {
techID.innerHTML = build.skinTechText(i)
} else {
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" 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) {
text += build.gunTechText(i)
} else if (tech.tech[i].isFieldTech) {
text += build.fieldTechText(i)
} else if (tech.tech[i].isSkin) {
text += build.skinTechText(i)
} else if (tech.tech[i].isJunk) {
text += build.junkTechText(i)
} else {
text += build.techText(i)
}

View File

@@ -10,7 +10,7 @@ const level = {
// playableLevels: ["pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion"],
//see level.populateLevels: (intro, ... , reservoir, reactor, ... , gauntlet, final) added later
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"],
levels: [],
start() {
@@ -18,23 +18,23 @@ const level = {
// simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode
// simulation.isHorizontalFlipped = true
// 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();
// m.maxHealth = m.health = 100
// tech.isRerollDamage = true
// powerUps.research.changeRerolls(6)
// powerUps.research.changeRerolls(50)
// m.immuneCycle = Infinity //you can't take damage
// tech.tech[297].frequency = 100
// 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
// 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.guns[0].ammo = 10000
// b.guns[8].ammo = 10000
// 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("tungsten carbide")
// 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 < 10; i++) powerUps.directSpawn(1750, -500, "boost");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling");
// level.testChamber();
// level.yingYang();
// spawn.nodeGroup(1200, 0, "slasher")
// spawn.blinkBoss(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 < 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 ************************************************
// simulation.isAutoZoom = false; //look in close
@@ -4400,7 +4396,7 @@ const level = {
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20);
level.defaultZoom = 2200
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "hsl(138, 3%, 74%)";
document.body.style.backgroundColor = "hsl(138, 5%, 82%)";
color.map = "#444"
powerUps.spawnStartingPowerUps(1768, 870); //on left side
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.fillRect(-250, -1550, 1250, 1575);
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.beginPath();
for (let i = 0; i < balance.length; i++) {
@@ -5559,7 +5558,7 @@ const level = {
// const button1 = level.button(-500, -200)
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();
// const button2 = level.button(-3100, -1330)
const toggle2 = level.toggle(-3100, -1330) //(x,y,isOn, isLockOn = true/false)
@@ -5620,7 +5619,7 @@ const level = {
} else {
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.fillRect(-4450, -750, 800, 200)
@@ -6157,14 +6156,14 @@ const level = {
let isReverse = false
if (Math.random() < 0.75) { //normal direction start in top left
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.exit.x = 3088;
level.exit.y = -630;
} else { //reverse direction, start in bottom right
isReverse = true
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.exit.x = 1375;
level.exit.y = -1530;
@@ -6219,7 +6218,8 @@ const level = {
spawn.bodyRect(-298, -1580, 40, 40); //center block under wall
spawn.bodyRect(1500, -1540, 30, 30); //left of entrance
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 + 1300, -2000, 50, 300); //right roof wall
spawn.mapRect(-600 + 1300, -2000, 900, 50); //center wall
@@ -6238,6 +6238,9 @@ const level = {
stiffness: 1
});
Composite.add(engine.world, consBB[consBB.length - 1]);
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.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(2980, 13, 30, 20); //step right
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(4150, -600, 350, 150); //table
spawn.mapRect(3650, -1300, 50, 700); //exit wall
@@ -6285,12 +6288,7 @@ const level = {
spawn.randomGroup(4150, -1000, 0.6);
if (simulation.difficulty > 1) {
if (Math.random() < 0.5) {
spawn.tetherBoss(2850, -80, {
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);
spawn.tetherBoss(2850, -80, { x: 2500, y: -500 })
} else {
spawn.randomLevelBoss(2200, -450)
}
@@ -6727,12 +6725,7 @@ const level = {
if (isLevelReversed === false) { ///Normal spawn
if (simulation.difficulty > 1) {
if (Math.random() < 0.2) {
// tether ball
spawn.tetherBoss(7000, -3300, {
x: 7300,
y: -3300
})
if (simulation.difficulty > 4) spawn.nodeGroup(7000, -3300, "spawns", 8, 20, 105);
spawn.tetherBoss(7000, -3300, { x: 7300, y: -3300 }) // tether ball
} else {
spawn.randomLevelBoss(6100, -3600, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "pulsarBoss"]);
}
@@ -6740,12 +6733,7 @@ const level = {
} else { /// Reversed spawn
if (simulation.difficulty > 1) {
if (Math.random() < 0.2) {
// tether ball
spawn.tetherBoss(2300, -1300, {
x: 2300,
y: -1750
})
if (simulation.difficulty > 4) spawn.nodeGroup(2350, -1300, "spawns", 8, 20, 105);
spawn.tetherBoss(2300, -1300, { x: 2300, y: -1750 }) // tether ball
} else {
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(3300, 1075, 1500, 1800); //Mur droite salle trésor
// tether ball
spawn.tetherBoss(2330, 1850, {
x: 2330,
y: 1425
})
spawn.tetherBoss(2330, 1850, { x: 2330, y: 1425 })
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);
},
// detours() { //by Francois from discord
@@ -7595,11 +7578,7 @@ const level = {
if (simulation.difficulty > 3) {
spawn.secondaryBossChance(3380, -1775)
if (Math.random() < 0.16) {
spawn.tetherBoss(3380, -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
spawn.tetherBoss(3380, -1775, { x: 3775, y: -1775 })
} else {
spawn.randomLevelBoss(3100, -1850, ["shooterBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "dragonFlyBoss", "laserBoss"]);
}
@@ -13138,7 +13117,7 @@ const level = {
let me = mob[mob.length - 1];
me.stroke = "transparent";
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.isUnblockable = true;
me.isShielded = true;
@@ -14713,6 +14692,359 @@ const level = {
coin(103830.0, -1473)
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 **********************************************

View File

@@ -820,25 +820,25 @@ const mobs = {
}
},
repelBullets() {
if (this.seePlayer.yes) {
ctx.lineWidth = "8";
ctx.strokeStyle = this.fill;
ctx.beginPath();
// if (this.seePlayer.yes) {
// ctx.lineWidth = "8";
// ctx.strokeStyle = this.fill;
// ctx.beginPath();
for (let i = 0, len = bullet.length; i < len; ++i) {
const dx = bullet[i].position.x - this.position.x;
const dy = bullet[i].position.y - this.position.y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 500) {
const dist = Math.max(300, Math.sqrt(dx * dx + dy * dy))
if (dist < 700) {
ctx.moveTo(this.position.x, this.position.y);
ctx.lineTo(bullet[i].position.x, bullet[i].position.y);
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.y += mag * Math.sin(angle);
}
}
ctx.stroke();
}
// ctx.stroke();
// }
},
attraction() {
//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, this.position.y + 20, "research", 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 {
const amount = 0.005
if (tech.isEnergyHealth) {

View File

@@ -547,7 +547,7 @@ const m = {
dmg *= m.fieldHarmReduction
// if (!tech.isFlipFlopOn && tech.isFlipFlopHealth) dmg *= 0.5
// 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.isFieldHarmReduction) dmg *= 0.5
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
let isDrawPlayer = true
@@ -691,7 +691,7 @@ const m = {
},
collisionImmuneCycles: 30,
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))
simulation.makeTextLog(`<span class='color-var'>m</span>.rewind(${steps})`)
m.rewind(steps)
@@ -708,7 +708,7 @@ const m = {
}
}
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
if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage
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.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a");
m.drawLeg("#456");
m.calcLeg(0, 0);
m.drawLeg("#333");
m.drawLeg("#345");
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
@@ -1034,13 +1034,9 @@ const m = {
ctx.beginPath();
ctx.arc(17, 0, 5.5, 0, 2 * Math.PI);
ctx.fillStyle = "#333"
ctx.fillStyle = "#357"
ctx.fill();
ctx.beginPath();
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
@@ -1099,14 +1095,14 @@ const m = {
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}%)`
const grd = ctx.createLinearGradient(-30, -5, 30, 10);
grd.addColorStop(0, `#eee`);
grd.addColorStop(0, `#e0e0e0`);
grd.addColorStop(0.3, `#bbb`);
grd.addColorStop(0.4, `#aaa`);
grd.addColorStop(0.5, `#ccc`);
grd.addColorStop(0.4, `#b3b3b3`);
grd.addColorStop(0.5, `#c5c5c5`);
grd.addColorStop(0.65, `#bbb`);
grd.addColorStop(0.7, `#aaa`);
grd.addColorStop(0.7, `#b3b3b3`);
grd.addColorStop(0.75, `#bbb`);
grd.addColorStop(1, `#eee`);
grd.addColorStop(1, `#e0e0e0`);
// const grdRad = ctx.createRadialGradient(0, 0, 0, 0, 0, 30);
// grdRad.addColorStop(0, `rgba(0,0,0,0.3)`);
// grdRad.addColorStop(0.5, `rgba(210,210,210,0)`);
@@ -1308,28 +1304,29 @@ const m = {
dilate() {
m.isAltSkin = true
m.draw = function() {
const amplitude = 8 + 4 * Math.sin(m.cycle * 0.0075)
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a");
m.drawLeg("#456");
m.calcLeg(0, 0);
m.drawLeg("#333");
m.drawLeg("#345");
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.strokeStyle = "#333";
ctx.strokeStyle = "#345";
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.beginPath();
ctx.arc(12, 0, 8 + 4 * Math.sin(m.cycle * 0.01), 0, 2 * Math.PI); //big eye
ctx.fillStyle = `hsl(${150+100*Math.sin(m.cycle * 0.01)},100%,50%)`
ctx.fill();
ctx.arc(12, 0, amplitude, 0, 2 * Math.PI); //big eye
// 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.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
@@ -1339,29 +1336,33 @@ const m = {
dilate2() {
m.isAltSkin = true
m.draw = function() {
const amplitude = Math.sin(m.cycle * 0.0075)
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#5f5f5f");
m.drawLeg("#456");
m.calcLeg(0, 0);
m.drawLeg("#444");
m.drawLeg("#345");
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.strokeStyle = "#444";
ctx.lineWidth = 3 + 3 * Math.sin(m.cycle * 0.01 + Math.PI);
ctx.arc(12, 0, 6 + 3 * Math.sin(m.cycle * 0.01), 0, 2 * Math.PI); //big eye
ctx.strokeStyle = "#345";
ctx.lineWidth = 3 + 3 * Math.sin(m.cycle * 0.0075 + Math.PI);
ctx.stroke();
// ctx.arc(12, 0, 8 + 4 * amplitude, 0, 2 * Math.PI); //big eye
ctx.beginPath();
ctx.arc(12, 0, 6 + 3 * Math.sin(m.cycle * 0.01), 0, 2 * Math.PI); //big eye
ctx.fillStyle = `hsl(${150+100*Math.sin(m.cycle * 0.01)},100%,50%)`
ctx.arc(12, 0, 8 + 4 * amplitude, 0, 2 * Math.PI); //big eye
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.stroke();
// ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
@@ -1380,7 +1381,7 @@ const m = {
ctx.lineTo(m.knee.x, m.knee.y);
ctx.lineTo(m.foot.x, m.foot.y);
ctx.strokeStyle = stroke;
ctx.lineWidth = 7;
ctx.lineWidth = 6 + 2 * Math.sin(m.cycle * 0.0075 + Math.PI);
ctx.stroke();
//toe lines
@@ -1401,9 +1402,9 @@ const m = {
//foot joint
ctx.moveTo(m.foot.x + 6, m.foot.y);
ctx.arc(m.foot.x, m.foot.y, 6, 0, 2 * Math.PI);
ctx.fillStyle = m.fillColor;
ctx.fillStyle = "#345";
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.restore();
}
@@ -1417,10 +1418,11 @@ const m = {
}
// m.setFillColors();
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);
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.draw = function() {
@@ -1430,10 +1432,10 @@ const m = {
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#3a3a3a");
m.drawLeg("#eee");
m.calcLeg(0, 0);
m.drawLeg("#222");
ctx.rotate(0.013 * simulation.cycle);
m.drawLeg("#fff");
ctx.rotate(0.017 * simulation.cycle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
@@ -1442,7 +1444,7 @@ const m = {
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.fillStyle = "#222"
ctx.fillStyle = "#000"
ctx.fill();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
@@ -1461,7 +1463,7 @@ const m = {
ctx.lineTo(m.knee.x, m.knee.y);
ctx.lineTo(m.foot.x, m.foot.y);
ctx.strokeStyle = stroke;
ctx.lineWidth = 7;
ctx.lineWidth = 6;
ctx.stroke();
//toe lines
@@ -1470,19 +1472,19 @@ const m = {
ctx.lineTo(m.foot.x - 15, m.foot.y + 5);
ctx.moveTo(m.foot.x, m.foot.y);
ctx.lineTo(m.foot.x + 15, m.foot.y + 5);
ctx.lineWidth = 4;
ctx.lineWidth = 3;
ctx.stroke();
//hip joint
ctx.beginPath();
ctx.arc(m.hip.x, m.hip.y, 11, 0, 2 * Math.PI);
//knee joint
ctx.moveTo(m.knee.x + 7, m.knee.y);
ctx.arc(m.knee.x, m.knee.y, 7, 0, 2 * Math.PI);
ctx.moveTo(m.knee.x + 5, m.knee.y);
ctx.arc(m.knee.x, m.knee.y, 5, 0, 2 * Math.PI);
//foot joint
ctx.moveTo(m.foot.x + 6, m.foot.y);
ctx.arc(m.foot.x, m.foot.y, 6, 0, 2 * Math.PI);
ctx.fillStyle = m.fillColor;
ctx.moveTo(m.foot.x + 5, m.foot.y);
ctx.arc(m.foot.x, m.foot.y, 5, 0, 2 * Math.PI);
ctx.fillStyle = "#000";
ctx.fill();
// ctx.lineWidth = 2;
// ctx.stroke();
@@ -2438,7 +2440,7 @@ const m = {
case 5: //plasma
return `<strong>+${(15*couple).toFixed(0)}%</strong> <strong class='color-d'>damage</strong>`
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
return `<strong>+${(33*couple).toFixed(0)}%</strong> ambush <strong class='color-d'>damage</strong>`
case 8: //pilot wave
@@ -2517,7 +2519,7 @@ const m = {
},
fieldUpgrades: [{
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
<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: () => {
@@ -2811,7 +2813,7 @@ const m = {
} else if (input.field) { //not hold but field button is pressed
//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)))
console.log(angleReduction)
// console.log(angleReduction)
if (player.velocity.y > 1) {
player.force.y -= angleReduction * (tech.isBigField ? 0.95 : 0.5) * player.mass * simulation.g;
Matter.Body.setVelocity(player, {
@@ -3606,16 +3608,16 @@ const m = {
},
{
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() {
// m.fieldMeterColor = "#0fc"
// m.fieldMeterColor = "#ff0"
m.fieldMeterColor = "#3fe"
m.eyeFillColor = m.fieldMeterColor
m.fieldFx = 1.3
m.fieldFx = 1.25
// m.fieldJump = 1.09
m.setMovement();
b.setFireCD()
const timeStop = () => {
m.immuneCycle = m.cycle + 10; //immune to harm while time is stopped, this also disables regen
//draw field everywhere
@@ -3666,7 +3668,7 @@ const m = {
m.throwBlock();
m.wakeCheck();
} 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
m.grabPowerUp();
@@ -3814,7 +3816,7 @@ const m = {
ctx.fillStyle = "#fff"
ctx.lineWidth = 2;
ctx.strokeStyle = "#000"
ctx.stroke()
// ctx.stroke()
ctx.globalCompositeOperation = "destination-in";
ctx.fill();
ctx.globalCompositeOperation = "source-over";
@@ -3925,11 +3927,36 @@ const m = {
// if (m.cycle > m.lastKillCycle + 240) {
// if (m.sneakAttackCharge > 0) {
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.beginPath();
ctx.arc(m.pos.x, m.pos.y, 28, 0, 2 * Math.PI);
ctx.lineWidth = 3
ctx.stroke();
ctx.arc(simulation.mouseInGame.x, simulation.mouseInGame.y, 16, 0, 2 * Math.PI);
// ctx.lineWidth = 3
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
if ((m.fieldMode === 0 || m.fieldMode === 9) && m.immuneCycle < m.cycle) m.energy += 0.2 * m.coupling
if (tech.isWormholeWorms) { //pandimensional spermia
b.worm(Vector.add(m.hole.pos2, Vector.rotate({
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
b.worm(Vector.add(m.hole.pos2, Vector.rotate({ 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));
// for (let i = 0, len = Math.ceil(1.25 * Math.random()); i < len; i++) {
// }
@@ -4467,7 +4491,7 @@ const m = {
if (input.field) {
if (tech.isWormHolePause) {
const drain = m.fieldRegen + 0.0004
const drain = m.fieldRegen + 0.0002
if (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
@@ -5067,7 +5091,7 @@ const m = {
) {
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
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);
return
}

View File

@@ -39,43 +39,43 @@ const powerUps = {
return `<div class="research-circle"></div> `
case 2:
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:0; left:7px;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:0;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:7px;"></div>
</span> &nbsp; &nbsp; &nbsp; &nbsp;`
case 3:
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:0; 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:0;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:8px;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:16px;"></div>
</span> &nbsp; &nbsp; &nbsp; &nbsp; &thinsp; `
case 4:
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:0; left:8px;"></div>
<div class="research-circle" style="position:absolute; top:0; 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:0;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:8px;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:16px;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:24px;"></div>
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; `
case 5:
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:0; left:8px;"></div>
<div class="research-circle" style="position:absolute; top:0; left:16px;"></div>
<div class="research-circle" style="position:absolute; top:0; 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:0;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:8px;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:16px;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:24px;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:32px;"></div>
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; `
case 6:
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:0; left:8px;"></div>
<div class="research-circle" style="position:absolute; top:0; left:16px;"></div>
<div class="research-circle" style="position:absolute; top:0; left:24px;"></div>
<div class="research-circle" style="position:absolute; top:0; 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:0;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:8px;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:16px;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:24px;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:32px;"></div>
<div class="research-circle" style="position:absolute; top:1.5px; left:40px;"></div>
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; `
}
let text = '<span style="position:relative;">'
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; '
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>
${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) {
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');"`
@@ -993,10 +1005,10 @@ const powerUps = {
text += powerUps.fieldTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isGunTech) {
text += powerUps.gunTechText(choose, `powerUps.choose('tech',${choose})`)
// } else if (tech.tech[choose].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) {
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
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>`
} else if (tech.tech[choose].isJunk) {
text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isSkin) {
text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`)
} else { //normal tech
text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`)
}

View File

@@ -930,8 +930,15 @@ const simulation = {
tech.deathSpawnsFromBoss = 0;
simulation.fallHeight = 3000;
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.drop();
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
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
ctx.beginPath();
let vertices = this.vertices;
@@ -5943,7 +5931,7 @@ const spawn = {
ctx.lineTo(vertices[j].x, vertices[j].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.fill();
} else if (this.isNotCloaked) {
@@ -7460,17 +7448,19 @@ const spawn = {
mobs.spawn(x, y, 8, radius, "rgb(0,60,80)");
let me = mob[mob.length - 1];
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
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({
pointA: {
x: constraint.x,
y: constraint.y
},
pointA: { x: constraint.x, y: constraint.y },
bodyB: me,
stiffness: 0.00012
});
@@ -7481,42 +7471,74 @@ const spawn = {
me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
this.removeCons(); //remove constraint
//spawn seekers
// for (let i = 0, len = 100; i < len; i++) {
// const unit = Vector.rotate({ x: 10 + i, y: 0 }, Math.random() * 6.28)
// const where = Vector.add(this.position, unit)
// spawn.seeker(where.x, where.y); //(x, y, radius = 8, sides = 6)
// }
const delay = 4
me.babies(0.05 * simulation.difficulty + 1)
};
me.babies = function(len) {
const delay = Math.max(3, Math.floor(15 - len / 2))
let i = 0
const len = 3 * simulation.difficulty
let spawnFlutters = () => {
if (i < len) {
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 where = Vector.add(this.position, unit)
spawn.seeker(where.x, where.y); //(x, y, radius = 8, sides = 6)
// const phase = i / len * 2 * Math.PI
// const where = Vector.add(this.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5))
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++
}
requestAnimationFrame(spawnFlutters);
}
}
requestAnimationFrame(spawnFlutters);
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: radius * 0.9,
color: "rgba(255,0,255,0.2)",
time: len * (delay - 1)
});
}
me.onDamage = function() {
if (this.health < this.nextHealthThreshold && this.alive) {
this.health = this.nextHealthThreshold - 0.01
this.nextHealthThreshold = Math.floor(this.health * 4) / 4
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() {
// this.armor();
this.gravity();
if (this.isInvulnerable) {
this.repulsion();
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) {

View File

@@ -220,13 +220,14 @@ const tech = {
damage: 1, //used for tech changes to player damage that don't have complex conditions
damageFromTech() {
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 (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.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.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.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
@@ -331,6 +332,7 @@ const tech = {
count: 0,
frequency: 1,
frequencyDefault: 1,
isSkin: true,
allowed() {
return !m.isAltSkin
},
@@ -352,7 +354,7 @@ const tech = {
},
{
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,
count: 0,
frequency: 1,
@@ -373,7 +375,7 @@ const tech = {
},
{
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,
count: 0,
frequency: 2,
@@ -396,7 +398,7 @@ const tech = {
{
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>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,
count: 0,
frequency: 1,
@@ -2104,7 +2106,6 @@ const tech = {
count: 0,
frequency: 1,
frequencyDefault: 1,
isSkin: true,
allowed() {
return !tech.isRelay
},
@@ -2257,7 +2258,6 @@ const tech = {
count: 0,
frequency: 1,
frequencyDefault: 1,
isSkin: true,
allowed() {
return !tech.isFlipFlop
},
@@ -3482,9 +3482,9 @@ const tech = {
}
},
{
name: "technical debt", // overengineering
name: "technical debt",
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,
count: 0,
@@ -4274,7 +4274,7 @@ const tech = {
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
},
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() {
tech.isNeedles = true
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",
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",
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,
maxCount: 1,
@@ -8176,28 +8195,28 @@ const tech = {
},
{
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,
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
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",
effect() {
tech.fieldDuplicate = 0.11
powerUps.setDupChance(); //needed after adjusting duplication chance
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)
}
},
remove() {
tech.fieldDuplicate = 0
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,
isDiaphragm: null,
hardLanding: null,
isNoGroundDamage: null,
}

View File

@@ -812,7 +812,31 @@ summary {
display: inline-block;
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 {
background-color: hsl(254, 44%, 75%);
border-radius: 25%;

View File

@@ -1,25 +1,61 @@
******************************************************** NEXT PATCH **************************************************
tech: elasticity - skin, does "crouch landings" a tiny bit more
jump and move faster, +15% defense
(replaces squirrel cage rotor)
tech: aerostat - +88% damage off the ground, but -22% damage on the ground
negative mass field required
tech: diaphragm - skin, defense cycles between -33% and +100%
requires aperture
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
tungsten carbide 150->200 maximum health
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
new community map yingYang by Richard0820
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
*********************************************************** 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
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