level: lock

new level: lock
  it's a work in progress
  I'm looking for feedback:
    anything confusing?
    combat too hard/easy?
      it will probably feel hard because you don't know the map yet

images are now hidden by default for new players
time dilation 18->15 energy/s

bug fixes:
  extended CSS media rules and power up selection code to entanglement
This commit is contained in:
landgreen
2023-01-23 20:01:26 -08:00
parent 43f3cfbae5
commit 6472d6d99a
18 changed files with 257 additions and 178 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 548 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
@@ -215,7 +215,7 @@
<details>
<summary>about</summary>
<div class="details-div" style="max-width: 450px;">
<a href="https://discord.gg/2eC9pgJ">
<a href="https://discord.gg/2eC9pgJ" aria-label="discord">
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1400 235">
<style>
.st0 {
@@ -228,7 +228,7 @@
</a>
Chat about n-gon in the <a href="https://discord.gg/JyfrKbXTfw">discord</a>.<br> Let me know about ideas, or bugs.
<br><br><br>
<a id="github" href="https://github.com/landgreen/n-gon">
<a id="github" href="https://github.com/landgreen/n-gon" aria-label="github">
<svg viewBox="0 0 100 16" xmlns="http://www.w3.org/2000/svg" fill="#1B1F23">
<path d="M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z" />
<g stroke='none' font-size="8px" font-family="Arial Black, sans-serif">
@@ -396,7 +396,6 @@
</svg>
<script src='lib/matter.min.js'></script>
<script src='lib/decomp.min.js'></script>
<script src='lib/randomColor.min.js'></script>
<script src="js/simulation.js"></script>
<script src="js/player.js"></script>
<script src="js/powerup.js"></script>

View File

@@ -517,6 +517,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
document.getElementById("field-" + m.fieldMode).classList.remove("build-field-selected");
m.setField(index)
document.getElementById("field-" + index).classList.add("build-field-selected");
document.getElementById("tech-150").focus();
} else if (m.fieldMode === 4) {
const i = 4 //update experiment text
simulation.molecularMode++
@@ -1461,10 +1462,8 @@ if (localSettings.isAllowed && !localSettings.isEmpty) {
localSettings.loreCount = 0; //this sets what conversation is heard
if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
}
if (localSettings.isHideImages === undefined) localSettings.isHideImages = false //default to show images
if (localSettings.isHideImages === undefined) localSettings.isHideImages = true //default to hide images
document.getElementById("hide-images").checked = localSettings.isHideImages
} else {
console.log('setting default localSettings')
const isAllowed = localSettings.isAllowed //don't overwrite isAllowed value
@@ -1483,7 +1482,7 @@ if (localSettings.isAllowed && !localSettings.isEmpty) {
isLoreDoesNotNeedReset: false,
isHuman: false,
key: undefined,
isHideImages: false, //default to show images
isHideImages: true, //default to hide images
};
input.setDefault()
if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage

View File

@@ -9,7 +9,7 @@ const level = {
levelsCleared: 0,
// 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"],
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"],
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"],
levels: [],
@@ -19,20 +19,22 @@ const level = {
// simulation.isHorizontalFlipped = true
// tech.giveTech("performance")
// level.difficultyIncrease(10 * 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(10)
// m.immuneCycle = Infinity //you can't take damage
// tech.tech[297].frequency = 100
// m.couplingChange(5)
// m.setField("metamaterial cloaking") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass pilot wave plasma torch
// m.setField("perfect diamagnetism") //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("shotgun") //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
// tech.giveTech("needle gun")
// tech.giveTech("eternalism")
// tech.giveTech("vacuum bomb")
// tech.giveTech("time crystals")
// tech.giveTech("ice-shot")
// for (let i = 0; i < 1; ++i) tech.giveTech("super ball")
// tech.isFoamBall = true
@@ -42,7 +44,7 @@ const level = {
// for (let i = 0; i < 10; 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.testChamber2();
// level.lock();
// spawn.nodeGroup(1200, 0, "slasher")
// spawn.blinkBoss(1900, -500)
// spawn.sneakBoss(1900, -500)
@@ -1447,14 +1449,8 @@ const level = {
isHazardRise: false,
hazard(x, y, width, height, damage = 0.002) {
return {
min: {
x: x,
y: y
},
max: {
x: x + width,
y: y + height
},
min: { x: x, y: y },
max: { x: x + width, y: y + height },
width: width,
height: height,
maxHeight: height,
@@ -1478,17 +1474,6 @@ const level = {
});
}
}
//collision with mobs
// if (!(simulation.cycle % 5) && !m.isBodiesAsleep) {
// query = Matter.Query.region(mob, this)
// for (let i = 0; i < query.length; i++) query[i].damage(5 * damage)
// }
// for (let i = 0, len = mob.length; i < len; i++) {
// if ( !mob[i].isBoss) {
// mob[i].damage(0.1 * damage)
// }
// }
}
},
query() {
@@ -1502,9 +1487,10 @@ const level = {
const DRAIN = 0.004 * (tech.isRadioactiveResistance ? 0.25 : 1)
if (m.energy > DRAIN) {
m.energy -= DRAIN
// m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1) * 0.03) //still take 2% damage while you have energy
if (tech.isEnergyHealth && m.energy < 0) m.death()
} else {
m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1))
}
}
//float
@@ -3718,10 +3704,7 @@ const level = {
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#d8dadf";
color.map = "#3d4240"
powerUps.spawnStartingPowerUps(-575, -2925)
// spawn.debris(750, -2200, 3700, 16); //16 debris per level //no debris?
//walls
spawn.mapRect(-3500, -5000, 1500, 6500);
spawn.mapRect(2000, -5000, 1500, 6500);
@@ -3732,7 +3715,6 @@ const level = {
//top floor exit
spawn.mapRect(1475, -4900, 50, 250);
spawn.mapRect(1400, -4475, 650, 50);
// ground
spawn.mapVertex(-687, 1060, "700 0 -700 0 -450 -300 450 -300"); //left base
spawn.mapVertex(863, 1060, "700 0 -700 0 -450 -300 450 -300"); //right base
@@ -3742,11 +3724,9 @@ const level = {
spawn.mapRect(-305, 550, 50, 500);
spawn.bodyRect(-717, 700, 25, 100); //door
spawn.bodyRect(-717, 800, 25, 100); //door
//1st floor //left
spawn.mapVertex(-1125 + 437, -50, "490 0 350 80 -350 80 -490 0 -350 -80 350 -80");
spawn.mapRect(-1225, -100, 1070, 100);
if (Math.random() < 0.33) {
spawn.mapVertex(-687, -1000, "-100 -300 0 -350 100 -300 100 300 0 350 -100 300");
} else if (Math.random() < 0.5) {
@@ -3757,13 +3737,9 @@ const level = {
//right
spawn.mapVertex(425 + 437, -50, "490 0 350 80 -350 80 -490 0 -350 -80 350 -80");
spawn.mapRect(325, -100, 1070, 100);
// spawn.mapRect(225, 675, 375, 25);
// spawn.mapRect(675, 450, 375, 25);
// spawn.mapRect(1125, 225, 375, 25);
spawn.mapRect(175, 675, 425, 25);
spawn.mapRect(1125, 225, 425, 25);
spawn.mapRect(650, 450, 425, 25);
if (Math.random() < 0.33) {
spawn.mapVertex(855, -1000, "-100 -300 0 -350 100 -300 100 300 0 350 -100 300");
} else if (Math.random() < 0.5) {
@@ -3771,25 +3747,14 @@ const level = {
} else {
spawn.mapVertex(855, -700, "-150 0 150 0 150 450 0 525 -150 450");
}
//2nd floor
spawn.mapVertex(-687, -1936, "-625 50 0 100 625 50 625 -50 -625 -50");
spawn.mapVertex(855, -1936, "-625 50 0 100 625 50 625 -50 -625 -50");
//2nd floor right building
// spawn.mapRect(550, -3050, 600, 175);
spawn.mapRect(550, -3050, 600, 75);
spawn.bodyRect(-125, -2025, 475, 25);
//2nd floor left building
// if (Math.random() > 0.5) {
// spawn.mapRect(-925, -2350, 675, 200);
// } else {
// }
spawn.mapRect(-925, -2350, 675, 50);
spawn.mapRect(-825, -2825, 425, 50);
// spawn.mapRect(-825, -2825, 425, 275);
spawn.mapRect(-450, -3125, 50, 350);
spawn.mapRect(-750, -3150, 350, 50);
spawn.mapRect(-650, -3400, 250, 300);
@@ -3798,10 +3763,7 @@ const level = {
//2nd floor left pillar
spawn.mapRect(-1400, -2625, 325, 25);
spawn.mapRect(-1450, -3225, 425, 25);
// spawn.mapRect(-1500, -3825, 525, 25);
spawn.mapRect(-1512.5, -3825, 550, 25);
// spawn.mapRect(-1400, -3225, 325, 25);
// spawn.mapRect(-1400, -3825, 325, 25);
spawn.randomMob(1000, -275, 0.2);
spawn.randomMob(950, -1725, 0.1);
@@ -3822,42 +3784,26 @@ const level = {
spawn.secondaryBossChance(75, -1350)
}
powerUps.addResearchToLevel() //needs to run after mobs are spawned
const slime = level.hazard(-2000, -5000, 4000, 6060); // hazard(x, y, width, height, damage = 0.003)
slime.height -= slime.maxHeight - 60 //start slime at zero
slime.min.y += slime.maxHeight
slime.max.y = slime.min.y + slime.height
const elevator1 = level.elevator(-1625, -90, 310, 800, -2000, 0.0025, {
up: 0.1,
down: 0.2
}) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) {
const elevator2 = level.elevator(1175, -3050, 200, 250, -4475, 0.0025, {
up: 0.12,
down: 0.2
}) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) {
const elevator1 = level.elevator(-1625, -90, 310, 800, -2000, 0.0025, { up: 0.1, down: 0.2 }) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) {
const elevator2 = level.elevator(1175, -3050, 200, 250, -4475, 0.0025, { up: 0.12, down: 0.2 }) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) {
let waterFallWidth = 0
let waterFallX = 0
let waterFallSmoothX = 0
let isWaterfallFilling = false
const riseRate = 0.30 + Math.min(1, simulation.difficulty * 0.005)
const spinnerArray = []
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// m.immuneCycle = Infinity //you can't take damage
// simulation.isHorizontalFlipped = true
if (simulation.isHorizontalFlipped) { //flip the map horizontally
spawn.mapVertex(584, -2500, "0 0 300 0 150 600 0 600");
spawn.mapVertex(1116, -2500, "0 0 300 0 300 600 150 600");
spawn.bodyRect(-200, -125, 625, 25);
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
elevator1.holdX = -elevator1.holdX // flip the elevator horizontally
elevator2.holdX = -elevator2.holdX // flip the elevator horizontally
spinnerArray.push(level.spinner(-110, -3325, 45, 600, 0.003, 0, 0, 0.01)) // spinner(x, y, width, height, density = 0.001, angle = 0, frictionAir = 0.001, angularVelocity = 0) {
const boost1 = level.boost(-900, -2000, 790)
level.setPosToSpawn(500, 850); //normal spawn
level.custom = () => {
@@ -3868,18 +3814,15 @@ const level = {
ctx.fillStyle = "#d0d4d6"
ctx.fillRect(275, -1925, 825, 2925) //large pillar background
ctx.fillRect(-1275, -1925, 825, 2925) //large pillar background
ctx.fillStyle = "#cff" //exit
ctx.fillRect(-2000, -4900, 525, 425)
level.exit.drawAndCheck();
level.enter.draw();
};
level.customTopLayer = () => {
boost1.query();
elevator1.move();
elevator2.move();
ctx.fillStyle = "#233"
ctx.beginPath(); //central dot on spinners
ctx.arc(spinnerArray[0].pointA.x, spinnerArray[0].pointA.y, 9, 0, 2 * Math.PI);
@@ -3895,7 +3838,6 @@ const level = {
ctx.fillRect(450, -3625, 200, 225);
ctx.fillRect(400, -2775, 425, 450);
ctx.fillRect(250, -2300, 675, 300);
slime.query();
if (isWaterfallFilling) {
if (slime.height < 5500) {
@@ -3924,7 +3866,6 @@ const level = {
} else { //not flipped
spawn.mapVertex(1116, -2500, "0 0 300 0 150 600 0 600");
spawn.mapVertex(584, -2500, "0 0 300 0 300 600 150 600");
if (Math.random() < 0.1) {
spinnerArray.push(level.spinner(65, -300, 40, 450, 0.003, Math.PI / 2))
} else if (Math.random() < 0.25) {
@@ -4447,42 +4388,93 @@ const level = {
}
},
testChamber2() {
lock() {
level.setPosToSpawn(0, -65); //lower start
level.exit.y = -1550;
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.exit.x = -1000;
level.exit.y = 2010;
level.exit.x = 2625;
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20);
level.defaultZoom = 2200
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#d0d5d5";
document.body.style.backgroundColor = "hsl(138, 3%, 74%)";
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)
const hazardSlime = level.hazard(900, -300, 3625, 2550) //hazard(x, y, width, height, damage = 0.002) {
const button = level.button(3975, -1425)
const doorCenterRight = level.door(2787, 775, 25, 225, 195, 5) //x, y, width, height, distance, speed = 1
const doorCenterLeft = level.door(2537, 775, 25, 225, 195, 5)
const doorButtonRight = level.door(4462, 1010, 25, 225, 195, 5)
const doorLeft = level.door(2538, 1825, 25, 225, 195, 5)
const buttonRight = level.button(4178, -355)
const buttonLeft = level.button(4585, 1235)
spawn.mapRect(4000, -350, 700, 125); //button platform
buttonLeft.isUp = true
buttonRight.isUp = true
const hazardSlimeLeft = level.hazard(900, -300, 1638, 2450) //hazard(x, y, width, height, damage = 0.002) {
const hazardSlimeRight = level.hazard(2812, -300, 1650, 2450) //hazard(x, y, width, height, damage = 0.002) {
//set slime to empty
// hazardSlimeLeft.height -= hazardSlimeLeft.maxHeight //start slime at zero
// hazardSlimeLeft.min.y += hazardSlimeLeft.maxHeight
// hazardSlimeLeft.max.y = hazardSlimeLeft.min.y + hazardSlimeLeft.height
// hazardSlimeRight.height -= hazardSlimeRight.maxHeight //start slime at zero
// hazardSlimeRight.min.y += hazardSlimeRight.maxHeight
// hazardSlimeRight.max.y = hazardSlimeRight.min.y + hazardSlimeRight.height
const balance = []
level.custom = () => {
portal[2].query()
portal[3].query()
ctx.fillStyle = "hsl(175, 35%, 76%)" //exit
ctx.fillRect(2537, 1775, 275, 275)
level.exit.drawAndCheck();
level.enter.draw();
button.query();
button.draw();
doorButtonRight.isClosing = hazardSlimeRight.min.y < 1275
doorCenterRight.isClosing = hazardSlimeRight.min.y < 1000
doorCenterLeft.isClosing = hazardSlimeLeft.min.y < 1000
doorLeft.isClosing = hazardSlimeLeft.min.y < 2050
doorButtonRight.openClose();
doorCenterRight.openClose();
doorCenterLeft.openClose();
doorLeft.openClose();
if (buttonRight.isUp) {
buttonRight.query();
if (!buttonRight.isUp) spawnRightMobs()
}
if (buttonLeft.isUp) {
buttonLeft.query();
if (!buttonLeft.isUp) spawnLeftMobs()
}
buttonRight.draw();
buttonLeft.draw();
if (hazardSlimeLeft.min.y < 2050) {
const drainRate = Math.min(Math.max(0.25, 4 - hazardSlimeLeft.min.y / 500), 4)
hazardSlimeLeft.level(buttonLeft.isUp, drainRate)
}
if (hazardSlimeRight.min.y < 2050) {
const drainRate = Math.min(Math.max(0.25, 4 - hazardSlimeRight.min.y / 500), 4)
hazardSlimeRight.level(buttonRight.isUp, drainRate)
}
portal[2].query()
portal[3].query()
};
level.customTopLayer = () => {
hazardSlime.query();
hazardSlimeLeft.query();
hazardSlimeRight.query();
portal[0].draw();
portal[1].draw();
portal[2].draw();
portal[3].draw();
ctx.fillStyle = "#444" //below portal
ctx.fillStyle = color.map //below portal
ctx.fillRect(375, 150, 200, 2525);
ctx.fillStyle = "rgba(0,0,0,0.1)" //shadows
ctx.fillRect(-250, -1550, 1250, 1575);
for (let i = 0, len = vanish.length; i < len; i++) vanish[i].query()
ctx.fillRect(2537, -350, 275, 2425);
ctx.fillStyle = "#233" //balances center dot
ctx.beginPath();
for (let i = 0; i < balance.length; i++) {
ctx.arc(balance[i].center.x, balance[i].center.y, 9, 0, 2 * Math.PI);
}
ctx.fill();
// for (let i = 0, len = vanish.length; i < len; i++) vanish[i].query()
};
//outer wall
// spawn.mapRect(-1400, 0, 1800, 1200); //floor
//entrance and outer walls
spawn.mapRect(-1400, 0, 1800, 2675);
spawn.mapRect(-1400, -1025, 1225, 1500);
spawn.mapRect(-325, -15, 525, 225);
@@ -4496,23 +4488,128 @@ const level = {
spawn.mapRect(750, -1425, 1100, 175);
spawn.mapRect(750, -1400, 250, 825);
spawn.mapRect(750, -350, 250, 575);
// spawn.mapRect(750, -1275, 250, 600);
// spawn.mapRect(3550, -1850, 1200, 600);
spawn.mapRect(625, 2100, 4300, 575); //floor
spawn.mapRect(-1400, -4425, 7250, 1000); //ceiling
// const vanish = []
// vanish.push(level.vanish(400, -1512, 150, 50))
// vanish.push(level.vanish(825, -625, 100, 325))
spawn.mapRect(3825, -1425, 975, 175);
spawn.mapRect(625, 2050, 4300, 625);
spawn.mapRect(4450, -3525, 1400, 6200);
//the pit
const vanish = []
vanish.push(level.vanish(400, -1512, 150, 50))
vanish.push(level.vanish(2625, -675, 300, 175))
vanish.push(level.vanish(1775, -675, 325, 150))
//blocks at entrance
spawn.bodyRect(150, -175, 50, 165);
spawn.bodyRect(825, -425, 155, 75, 0.5);
//left button room (on the far right in the
spawn.mapRect(4450, -3525, 1400, 4500);
spawn.mapRect(4450, 1235, 1400, 1440);
spawn.mapRect(4775, 750, 1075, 825);
spawn.mapRect(4450, 950, 50, 75);
//other ideas for left and right alternate setups
//just a floor covered with boosts
//something focused on funnel shapes
//several rooms with tunnels connecting them
//spinners
//right side
if (Math.random() < 1) {
spawn.mapVertex(3350, 350, "-100 0 100 0 100 700 0 750 -100 700");
balance.push(level.rotor(3463, 150, 300, 25, 0.001, 0)) //balance(x, y, width, height, density = 0.001, angle = 0, frictionAir = 0.001, angularVelocity = 0, rotationForce = 0.0005) {
balance.push(level.rotor(3463, 500, 300, 25, 0.001, 0))
spawn.mapVertex(3875, 350, "-100 0 100 0 100 700 0 750 -100 700");
spawn.mapVertex(2900, 1743, "-100 0 70 0 100 30 100 1000 -100 1000");
spawn.mapVertex(3025, 1811, "-150 0 120 0 150 30 150 600 -150 600");
spawn.mapVertex(3200, 2079, "-150 0 120 0 150 30 150 600 -150 600");
spawn.mapVertex(4425, 1743, "-150 30 -120 0 150 0 150 1000 -150 1000");
spawn.mapVertex(4250, 1811, "-150 30 -120 0 150 0 150 600 -150 600");
spawn.mapVertex(4075, 2079, "-150 30 -120 0 150 0 150 600 -150 600");
}
//left side
if (Math.random() < 1) {
// spawn.mapVertex(2325, 1325, "-150 0 150 0 150 150 0 225 -150 150");
spawn.mapVertex(1285, 1275, "-150 0 150 0 150 150 0 225 -150 150");
spawn.mapVertex(1033, 1750, "0 200 200 200 300 50 300 -50 200 -200 0 -200");
spawn.mapVertex(1575, 1750, "0 200 -200 200 -300 50 -300 -50 -200 -200 0 -200 100 -50 100 50"); //larger "0 400 -250 400 -400 100 -400 -100 -250 -400 0 -400"
spawn.mapVertex(1287, 2185, "-100 30 -80 0 80 0 100 30 100 300 -100 300");
spawn.mapVertex(2050, 2050, "-150 30 -120 0 120 0 150 30 150 300 -150 300");
// spawn.mapRect(1700, 1550, 275, 25);
// spawn.mapRect(2175, 1275, 325, 25);
spawn.mapRect(1600, 950, 375, 25);
spawn.mapRect(1025, -50, 50, 25);
spawn.mapRect(1025, 275, 175, 25);
spawn.mapRect(1025, 600, 325, 25);
spawn.mapRect(2450, -50, 50, 25);
spawn.mapRect(2325, 275, 175, 25);
spawn.mapRect(2175, 600, 325, 25);
// spawn.mapVertex(3400, 1250, "-100 -300 0 -350 100 -300 100 300 0 350 -100 300");
}
//left button room in center divider
spawn.mapRect(2525, -350, 300, 1100);
spawn.mapRect(2525, 975, 300, 800);
spawn.mapRect(2775, 650, 50, 125);
spawn.mapRect(2525, 650, 50, 125);
//exit room
spawn.mapRect(2475, 2040, 350, 200);
spawn.mapRect(2800, 1750, 25, 325);
spawn.mapRect(2525, 1750, 50, 75);
//safety edge blocks //maybe remove?
// spawn.mapRect(2525, -375, 25, 50);
// spawn.mapRect(2800, -375, 25, 50);
// spawn.mapRect(1825, -1450, 25, 50);
// spawn.mapRect(4000, -375, 25, 50);
//blocks
spawn.bodyRect(150, -175, 50, 165, 0.2); //block at entrance
spawn.bodyRect(1275, 825, 100, 100, 0.2);
spawn.bodyRect(2600, -425, 150, 50, 0.2);
spawn.bodyRect(3900, -150, 50, 100, 0.2);
spawn.bodyRect(3350, 1950, 75, 100, 0.2);
spawn.bodyRect(3850, 1975, 75, 75, 0.2);
spawn.bodyRect(1600, 1950, 75, 100, 0.2);
spawn.bodyRect(725, -1650, 150, 100, 0.2);
spawn.bodyRect(800, -1700, 75, 50, 0.2);
const spawnRightMobs = () => {
spawn.randomMob(4200, 100, 1);
spawn.randomMob(4200, 600, 1);
spawn.randomMob(2975, 625, 0.5);
spawn.randomMob(3050, 100, 0.5);
spawn.randomMob(3400, -100, 0.4);
spawn.randomMob(3825, -100, 0.4);
spawn.randomMob(3625, 1950, 0.4);
spawn.randomMob(3275, 1650, 0.4);
spawn.randomMob(3075, 1375, 0.3);
spawn.randomMob(4000, 1650, 0.1);
spawn.randomMob(4100, 1425, 0);
spawn.randomGroup(3025, 325, 1);
if (simulation.difficulty > 1) spawn.secondaryBossChance(3520, 1169)
}
const spawnLeftMobs = () => {
spawn.randomMob(2375, 1900, 1);
spawn.randomMob(1825, 1325, 0.5);
spawn.randomMob(2250, 1050, 0.5);
spawn.randomMob(1675, 825, 0.4);
spawn.randomMob(1250, 575, 0.4);
spawn.randomMob(2400, 575, 0.4);
spawn.randomMob(1250, 1575, 0.3);
spawn.randomMob(1075, -100, 0.3);
spawn.randomMob(2450, -100, 0.2);
spawn.randomGroup(1350, -775, 1);
if (simulation.difficulty > 1) spawn.randomLevelBoss(1491, 495);
}
spawn.randomMob(2650, -750, 0.4);
spawn.randomMob(300, -1725, 0.4);
spawn.randomMob(750, -1775, 0.4);
spawn.randomMob(550, -2225, 0.4);
spawn.randomMob(2700, -475, 0.4);
spawn.randomMob(2375, -200, 0.2);
spawn.randomMob(3350, -225, 0.3);
powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
sewers() {
const button1 = level.button(6600, 2675)
@@ -4589,8 +4686,6 @@ const level = {
spawn.mapRect(3050, -600, 200, 800); //right down tube wall
spawn.mapRect(3100, 0, 1200, 200); //tube right exit ceiling
spawn.mapRect(4200, 0, 200, 1900);
spawn.mapVertex(3500, 1000, "-500 -500 -400 -600 400 -600 500 -500 500 500 400 600 -400 600 -500 500");
spawn.mapVertex(3600, 1940, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40");
spawn.mapRect(3925, 2288, 310, 50);

View File

@@ -1076,7 +1076,7 @@ const m = {
},
setFieldRegen() {
if (m.fieldMode === 6) {
m.fieldRegen = 0.003 //18 energy per second
m.fieldRegen = 0.0025 //15 energy per second
} else if (m.fieldMode === 4) {
m.fieldRegen = 0.002 //12 energy per second
} else {
@@ -2785,7 +2785,7 @@ 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>18</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>+25%</strong> movement and <strong><em>fire rate</em></strong><br>generate <strong>15</strong> <strong class='color-f'>energy</strong> per second",
set() {
// m.fieldMeterColor = "#0fc"
// m.fieldMeterColor = "#ff0"

View File

@@ -333,7 +333,7 @@ const powerUps = {
},
endDraft(type, isCanceled = false) { //type should be a gun, tech, or field
if (isCanceled) {
if (tech.isCancelTech && Math.random() < 0.85) {
if (tech.isCancelTech && Math.random() < 0.85 && type !== "entanglement") {
// powerUps.research.use('tech')
powerUps[type].effect();
return
@@ -628,7 +628,9 @@ const powerUps = {
},
researchText(type) {
let text = ""
if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
if (type === "entanglement") {
text += `<div class='choose-grid-module entanglement flipX'>entanglement</div>`
} else if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
text += `<div onclick="powerUps.research.use('${type}')" class='research-card'>` // style = "margin-left: 192px; margin-right: -192px;"
tech.junkResearchNumber = Math.ceil(4 * Math.random())
text += `<div><div> <span style="position:relative;">`
@@ -702,14 +704,14 @@ const powerUps = {
hideStyle: `style="height:auto; border: none; background-color: transparent;"`,
gunText(choose, click) {
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/gun/${b.guns[choose].name}.webp');"`
return `<div class="choose-grid-module card-background" onclick="${click}" ${style}>
return `<div class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}" ${style}>
<div class="card-text">
<div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choose].name}</div>
${b.guns[choose].description}</div></div>`
},
fieldText(choose, click) {
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/field/${m.fieldUpgrades[choose].name}${choose === 0 ? Math.floor(Math.random()*10) : ""}.webp');"`
return `<div class="choose-grid-module card-background" onclick="${click}" ${style}>
return `<div class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}"${style}>
<div class="card-text">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choose].name}</div>
${m.fieldUpgrades[choose].description}</div></div>`
@@ -717,7 +719,7 @@ const powerUps = {
techText(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}" ${style}>
return `<div class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}"${style}>
<div class="card-text">
<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>`
@@ -726,7 +728,7 @@ const powerUps = {
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');"`
return `<div class="choose-grid-module card-background" onclick="${click}" ${style}>
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;">
@@ -739,7 +741,7 @@ const powerUps = {
gunTechText(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}" ${style}>
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;">
@@ -780,7 +782,7 @@ const powerUps = {
}
}, 1);
}
return `<div id = "junk-${choose}" class="choose-grid-module card-background" onclick="${click}" ${style}>
return `<div id = "junk-${choose}" class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}"${style}>
<div class="card-text">
<div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
@@ -1096,12 +1098,14 @@ const powerUps = {
},
effect() {
if (m.alive && localSettings.entanglement) {
let text = ""
document.getElementById("choose-grid").style.gridTemplateColumns = "384px 384px 384px"
// let text = ""
// document.getElementById("choose-grid").style.gridTemplateColumns = "384px 384px 384px"
let text = powerUps.buildColumns(3, "entanglement")
// text += powerUps.researchText('tech')
text += "<div></div>"
text += "<div class='choose-grid-module entanglement flipX'>entanglement</div>"
text += `<div class='choose-grid-module' onclick='powerUps.endDraft("tech",true)' style="width: 82px; text-align: center;font-size: 1.1em;font-weight: 100;justify-self: end;">cancel</div>` //powerUps.cancelText('tech')
// text += "<div></div>"
// text += "<div class='choose-grid-module entanglement flipX'>entanglement</div>"
// text += `<div class='choose-grid-module' onclick='powerUps.endDraft("tech",true)' style="width: 82px; text-align: center;font-size: 1.1em;font-weight: 100;justify-self: end;">cancel</div>` //powerUps.cancelText('tech')
if (localSettings.entanglement.fieldIndex) {
const choose = localSettings.entanglement.fieldIndex //add field
text += powerUps.fieldText(choose, `powerUps.choose('field',${choose})`)

View File

@@ -1529,13 +1529,11 @@ const simulation = {
} else if (e.button === 4) {
simulation.outputMapString(`${Math.floor(simulation.constructMouseDownPosition.x)}, ${Math.floor(simulation.constructMouseDownPosition.y)}`);
} else if (simulation.mouseInGame.x > simulation.constructMouseDownPosition.x && simulation.mouseInGame.y > simulation.constructMouseDownPosition.y) { //make sure that the width and height are positive
if (e.button === 0) { //add map
if (level.isProcedural) {
simulation.outputMapString(`spawn.mapRect(x+${x}, y+${y}, ${dx}, ${dy});\n`);
} else {
simulation.outputMapString(`spawn.mapRect(${x}, ${y}, ${dx}, ${dy});\n`);
}
//see map in world
spawn.mapRect(x, y, dx, dy);
@@ -1545,14 +1543,12 @@ const simulation = {
Matter.Body.setStatic(map[len], true); //make static
Composite.add(engine.world, map[len]); //add to world
simulation.draw.setPaths() //update map graphics
} else if (e.button === 2) { //add body
if (level.isProcedural) {
simulation.outputMapString(`spawn.bodyRect(x+${x}, y+${y}, ${dx}, ${dy});\n`);
} else {
simulation.outputMapString(`spawn.bodyRect(${x}, ${y}, ${dx}, ${dy});\n`);
}
//see map in world
spawn.bodyRect(x, y, dx, dy);
len = body.length - 1

View File

@@ -2664,9 +2664,6 @@ const spawn = {
me.spin = function() {
this.checkStatus();
this.torque += 0.000035 * this.inertia;
this.fill = randomColor({
hue: "blue"
});
//draw attack vector
const mag = this.radius * 2.5 + 50;
ctx.strokeStyle = "rgba(0,0,0,0.2)";

View File

@@ -3399,7 +3399,7 @@ const tech = {
{
name: "technical debt", // overengineering
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.max(41 / (tech.totalCount + 21), 4 - 0.15 * tech.totalCount) ))-100}%)</em>`
},
maxCount: 1,
count: 0,
@@ -5276,7 +5276,7 @@ const tech = {
allowed() {
return !tech.isImmuneExplosion && (build.isExperimentSelection || powerUps.research.count > 2) && (tech.haveGunCheck("missiles") || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb))
},
requires: "an explosive damage source, not electric reactive armor",
requires: "an explosive damage source, not rocket propelled grenade",
effect() {
tech.isSmartRadius = true;
for (let i = 0; i < 3; i++) {
@@ -5345,7 +5345,7 @@ const tech = {
b.setGrenadeMode()
},
remove() {
tech.isImmuneExplosion = true;
tech.isImmuneExplosion = false;
tech.isRPG = false;
b.setGrenadeMode()
}

File diff suppressed because one or more lines are too long

View File

@@ -1,17 +1,40 @@
******************************************************** NEXT PATCH **************************************************
tech: RPG - gains the rocket jumping effects from electric armor
new level: lock
it's a work in progress
I'm looking for feedback:
anything confusing?
combat too hard/easy?
it will probably feel hard because you don't know the map yet
eternalism no longer makes tech options have 50% opacity when choosing
images are now hidden by default for new players
time dilation 18->15 energy/s
some new images for cloaking tech
and some images were made brighter
bug fixes
safari media rules css fixed
bug fixes:
extended CSS media rules and power up selection code to entanglement
*********************************************************** TODO *****************************************************
level: lock
replace vanish elements with doors to fit theme better
can you do a sideways door?
should there be something in the top part of the map?
add alt versions of left and right sides
make flipped L/R version (after everything else is done)
tech: add an selection option to all tech, gun, fields to do something
set all mobs to 30% health, and stun all mobs
50% chance to convert all power ups into research
heal to full
tech: if you die inside MACHO, heal to full and delete the MACHO for the rest of the Level
MACHO gives less defense
tech: after bosses die<br>they spawn a research
tech: neutrino oscillation - when a mob dies there is a __% chance to convert a random existing power up to a different type
tech: +8% damage each time you kill a boss
tech: maybe missiles explode when they hit walls, but explosions only drain energy
@@ -19,41 +42,9 @@ tech: sticky grenades
needs another effect to be good enough
stick to mobs?
testChamber2
mechanics
cover exit with slime, press button to lower slime and exit
companion cube
bring cube to the end and use it to unlock research
level draws on the block to show it's different
only this block can trigger a button?
if cube no longer exists or is off the map spawn a new one
or maybe add a button for the player to destroy current cube and spawn new cube
double portal fling chain
for player?
for cube
button that activates a laser beam that hits a target and opens a door
in order to enter the door you need to place the cube on the button to activate the laser
cube has to fly through a portal in order to get to the button
you can't use your body
story:
you pick up the cube early on and have to get it to a button
you run through the level to get the cube, clearing the level of mobs
picking up the cube spawns the boss
maybe an extra hard boss that is designed for that level
blockBoss?
you must get the cube to a button near the start of the level
the button opens a door
normal blocks don't work
normal blocks spawn into mobs like blockBoss
or mobs don't spawn blocks
or just the code looks for the cube
or the cube is resting on a button, and when you take the cube off the button the laser fires
make a mob similar to slasher
because it's just a very well made mob.
tech - only allow 1,2 turrets at time?
turrets never run out of ammo
or turrets automatically use one of your mine ammos when they run out?
@@ -1168,7 +1159,6 @@ if pause is pressed while selecting power ups, display pause menu on top of sele
***major themes missing***
***maybe redo***
heuristics
negative feedback - too dark
supercritical fission
***past style themes***
field emitter - isometric, clean white robot spherical gun turret on bird legs, blender 3d, style of artstation and behance, Disney Pixar, cute