subway stations

subway
  2 new subway stations
  more visible button graphics on subway

new constraints
  no health bars
  no pause while choosing

tech: coherence - past choices are added to all future tech
  requires decoherence
  research and cancel buttons have a sticky scroll positioning
eternalism: you can't pause while choosing, but you can otherwise pause now
  1.25->1.3 damage

bugs
  MIRV missiles now interact with time dilation properly
This commit is contained in:
landgreen
2024-08-31 08:28:05 -07:00
parent 220a6b4c15
commit ebd22741d4
10 changed files with 557 additions and 161 deletions

View File

@@ -6723,10 +6723,7 @@ const b = {
// }
// } else {
m.fireCDcycle = m.cycle + tech.missileFireCD * b.fireCDscale / countReduction; // cool down
const direction = {
x: Math.cos(m.angle),
y: Math.sin(m.angle)
}
const direction = { x: Math.cos(m.angle), y: Math.sin(m.angle) }
// const where = {
// x: m.pos.x + 30 * direction.x,
// y: m.pos.y + 30 * direction.y
@@ -6752,23 +6749,17 @@ const b = {
let count = 0
const fireMissile = () => {
if (m.crouch) {
b.missile({
x: m.pos.x + 30 * direction.x,
y: m.pos.y + 30 * direction.y
}, m.angle, 20, sqrtCountReduction)
b.missile({ x: m.pos.x + 30 * direction.x, y: m.pos.y + 30 * direction.y }, m.angle, 20, sqrtCountReduction)
bullet[bullet.length - 1].force.x += 0.5 * push.x * (Math.random() - 0.5)
bullet[bullet.length - 1].force.y += 0.004 + 0.5 * push.y * (Math.random() - 0.5)
} else {
b.missile({
x: m.pos.x + 30 * direction.x,
y: m.pos.y + 30 * direction.y
}, m.angle, -15, sqrtCountReduction)
b.missile({ x: m.pos.x + 30 * direction.x, y: m.pos.y + 30 * direction.y }, m.angle, -15, sqrtCountReduction)
bullet[bullet.length - 1].force.x += push.x * (Math.random() - 0.5)
bullet[bullet.length - 1].force.y += 0.005 + push.y * (Math.random() - 0.5)
}
}
const cycle = () => {
if ((simulation.paused || m.isBodiesAsleep) && m.alive) {
if ((simulation.paused) && m.alive) {
requestAnimationFrame(cycle)
} else {
count++
@@ -6781,15 +6772,9 @@ const b = {
requestAnimationFrame(cycle);
} else {
if (m.crouch) {
b.missile({
x: m.pos.x + 40 * direction.x,
y: m.pos.y + 40 * direction.y
}, m.angle, 25)
b.missile({ x: m.pos.x + 40 * direction.x, y: m.pos.y + 40 * direction.y }, m.angle, 25)
} else {
b.missile({
x: m.pos.x + 40 * direction.x,
y: m.pos.y + 40 * direction.y
}, m.angle, -12)
b.missile({ x: m.pos.x + 40 * direction.x, y: m.pos.y + 40 * direction.y }, m.angle, -12)
bullet[bullet.length - 1].force.y += 0.04 * (Math.random() - 0.2)
}
}

View File

@@ -1421,7 +1421,7 @@ window.addEventListener("keydown", function (event) {
// level.levelAnnounce();
document.body.style.cursor = "none";
requestAnimationFrame(cycle);
} else if (!tech.isNoDraftPause) {
} else { //if (!tech.isNoDraftPause)
simulation.paused = true;
build.pauseGrid()
document.body.style.cursor = "auto";

View File

@@ -17,7 +17,9 @@ const level = {
if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode
// simulation.isHorizontalFlipped = true
// level.levelsCleared = 4
// spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
// spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
// level.levelsCleared = 11
// level.updateDifficulty()
// tech.giveTech("performance")
// m.maxHealth = m.health = 1//00000000
@@ -44,17 +46,20 @@ const level = {
// b.guns[8].ammo = 100000000
// requestAnimationFrame(() => { tech.giveTech("stimulated emission") });
// tech.giveTech("Hilbert space")
// for (let i = 0; i < 1; ++i) tech.giveTech("decoherence")
// for (let i = 0; i < 1; ++i) tech.giveTech("mass-energy equivalence")
// tech.addJunkTechToPool(0.5)
// for (let i = 0; i < 1; ++i) tech.giveTech("coherence")
// for (let i = 0; i < 1; ++i) tech.giveTech("nitinol")
// m.skin.egg();
// for (let i = 0; i < 1; ++i) tech.giveTech("depolarization")
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("wikipedia") });
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("field coupling") });
// for (let i = 0; i < 1; i++) tech.giveTech("interest")
// m.lastKillCycle = m.cycle
// for (let i = 0; i < 1; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 3; i++) powerUps.directSpawn(m.pos.x + 200, m.pos.y - 50, "boost", false);
// for (let i = 0; i < 4; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 7; i++) powerUps.directSpawn(m.pos.x + 200, m.pos.y - 250, "research", false);
// spawn.bodyRect(575, -700, 150, 150); //block mob line of site on testing
// level.heal();
// level.subway();
level[simulation.isTraining ? "walk" : "initial"]() //normal starting level **************************************************
@@ -334,6 +339,30 @@ const level = {
constraintDescription1: "", //used in pause menu and console
constraintDescription2: "",
constraint: [
{
description: "no pause while choosing",
effect() {
level.isNoPause = true
},
remove() {
level.isNoPause = false
}
},
{
description: "no health bars",
effect() {
mobs.healthBar = () => { }
level.isHideHealth = true
document.getElementById("health").style.display = "none"
document.getElementById("health-bg").style.display = "none"
},
remove() {
mobs.healthBar = mobs.defaultHealthBar
level.isHideHealth = false
document.getElementById("health").style.display = "inline"
document.getElementById("health-bg").style.display = "inline"
}
},
{
description: "0.5x energy regen",
effect() {
@@ -561,6 +590,8 @@ const level = {
reducedHealthLost: 0,
isReducedHealth: false,
isReducedRegen: 1,
isHideHealth: false,
isNoPause: false,
levelAnnounce() {
const cheating = simulation.isCheating ? "(testing)" : ""
if (level.levelsCleared === 0) {
@@ -2604,7 +2635,6 @@ const level = {
//start a conversation based on the number of conversations seen
if (localSettings.loreCount > lore.conversation.length - 1) localSettings.loreCount = lore.conversation.length - 1; //repeat final conversation if lore count is too high
if (!simulation.isCheating && localSettings.loreCount < lore.conversation.length) {
tech.isNoDraftPause = true //disable pause
lore.testSpeechAPI() //see if speech is working
lore.chapter = localSettings.loreCount //set the chapter to listen to to be the lore level (you can't use the lore level because it changes during conversations)
lore.sentence = 0 //what part of the conversation to start on
@@ -3185,7 +3215,7 @@ const level = {
train[train.length - 1].stops = { left: -7225, right: -1725 }
const stationList = [] //use to randomize station order
for (let i = 1, totalNumberOfStations = 8; i < totalNumberOfStations; ++i) stationList.push(i) //!!!! update station number when you add a new station
for (let i = 1, totalNumberOfStations = 10; i < totalNumberOfStations; ++i) stationList.push(i) //!!!! update station number when you add a new station
shuffle(stationList);
stationList.splice(0, 3); //remove some stations to keep it to 4 stations
stationList.unshift(0) //add index zero to the front of the array
@@ -3201,6 +3231,8 @@ const level = {
}
removeAll(map);
map = [];
removeAll(composite);
composite = []
//remove any powerUp that is too far from player
for (let i = 0; i < powerUp.length; ++i) {
if (Vector.magnitudeSquared(Vector.sub(player.position, powerUp[i].position)) > 9000000) { //remove any powerUp farther then 3000 pixels from player
@@ -3244,7 +3276,25 @@ const level = {
}
}
}
gateButton.draw();
// gateButton.draw();
if (gateButton.isUp) {
//aura around button
ctx.beginPath();
ctx.ellipse(gateButton.min.x + gateButton.width * 0.5, gateButton.min.y + 6, 0.75 * gateButton.width, 0.5 * gateButton.width, 0, Math.PI, 0); //ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise)
ctx.fillStyle = `hsla(345, 100%, 80%,${0.1 + 0.4 * Math.random()})`
ctx.fill();
ctx.fillStyle = "hsl(345, 100%, 75%)"
ctx.fillRect(gateButton.min.x, gateButton.min.y - 10, gateButton.width, 25)
ctx.strokeStyle = "#000"//"rgba(255,255,255,0.2)"
ctx.lineWidth = 2
ctx.strokeRect(gateButton.min.x, gateButton.min.y - 10, gateButton.width, 25)
} else {
ctx.fillStyle = "hsl(345, 100%, 75%)"
ctx.fillRect(gateButton.min.x, gateButton.min.y, gateButton.width, 10)
ctx.strokeStyle = "#000"//"rgba(255,255,255,0.2)"
ctx.lineWidth = 2
ctx.strokeRect(gateButton.min.x, gateButton.min.y, gateButton.width, 10)
}
}
}
const stations = [ //update totalNumberOfStations as you add more stations
@@ -3940,8 +3990,235 @@ const level = {
ctx.fillRect(x + 950, -675, 400, 125);
}
},
() => { //angled jumps
const buttonsCoords = [{ x: x + 50, y: -1395 }, { x: x - 625, y: -2945 }, { x: x + 900, y: -2945 }]
const buttonsCoordsIndex = Math.floor(Math.random() * buttonsCoords.length) //pick a random element from the array
spawn.mapRect(x + -1500, -210, 3000, 400);//station floor
boosts = []
boosts.push(level.boost(x - 311, -218, 1200, 1.85))
spawn.mapRect(x + -225, -525, 675, 375);
spawn.mapRect(x + -1350, -1175, 400, 675);
spawn.mapRect(x + -225, -2125, 675, 400);
// spawn.mapRect(x + -225, -1325, 675, 550);
spawn.mapRect(x + -225, -1400, 675, 650);
boosts.push(level.boost(x - 1335, -1200, 1800, 1))
boosts.push(level.boost(x + 1272, -1300, 1550, 2.75)) //far right
//high up walls
boosts.push(level.boost(x + 1455, -2048, 1450, 2.5))
spawn.mapRect(x + 1500, -3825, 325, 1900);
boosts.push(level.boost(x - 1555, -2048, 1450, 0.64))
// spawn.mapRect(x + -1625, -3975, 3450, 325);
spawn.mapRect(x + -1825, -4000, 325, 2150);
spawn.mapRect(x + -1825, -4070, 3650, 375);//roof
spawn.randomMob(x + 100, -2125, 0);
boosts.push(level.boost(x + 75, -2175, 2800))
spawn.mapRect(x + -100, -3900, 400, 400);
Matter.Body.setAngle(map[map.length - 1], map[map.length - 1].angle - Math.PI / 4);
spawn.mapRect(x + 225, -2950, 1100, 150);
spawn.mapRect(x + -1325, -2950, 1325, 150);
if (isExitOpen) {
level.exit.x = buttonsCoords[buttonsCoordsIndex].x;
level.exit.y = buttonsCoords[buttonsCoordsIndex].y - 25;
} else {
var gateButton = level.button(buttonsCoords[buttonsCoordsIndex].x, buttonsCoords[buttonsCoordsIndex].y, 126, false) //x, y, width = 126, isSpawnBase = true
gateButton.isUp = true
if (stationNumber > gatesOpenRight) {
var gate = level.doorMap(x + 1375, -525, 50, 375, 300, 20, false) //x, y, width, height, distance, speed = 20
} else if (stationNumber < gatesOpenLeft) {
var gate = level.doorMap(x - 1375, -525, 50, 375, 300, 20, false) //x, y, width, height, distance, speed = 20
}
}
if (!isExitOpen) {
spawn.randomMob(x + 350, -600, 0);
spawn.randomMob(x + -25, -600, 0);
spawn.randomMob(x + 600, -300, 0);
spawn.randomMob(x + 1050, -300, 0);
spawn.randomMob(x + 350, -1525, 0);
spawn.randomMob(x + -75, -1525, 0);
spawn.randomMob(x + -1075, -1275, 0);
spawn.randomMob(x + -1350, -2050, 0);
spawn.randomMob(x + -50, -2250, 0);
spawn.randomMob(x + -200, -3050, 0);
spawn.randomMob(x + -925, -3150, 0);
spawn.randomMob(x + 450, -3125, 0);
spawn.randomMob(x + 1075, -3025, 0);
spawn.randomMob(x + 750, -3125, 0);
spawn.randomMob(x + -725, -3125, 0);
}
stationCustom = () => {
for (let i = 0; i < boosts.length; i++) {
boosts[i].query()
}
}
stationCustomTopLayer = () => {
checkGate(gate, gateButton)
ctx.fillStyle = "rgba(0,0,0,0.08)"
ctx.fillRect(x - 225, -775, 675, 275);
ctx.fillRect(x - 225, -1750, 675, 375);
}
},
() => { //people movers
simulation.removeEphemera("zoom")//stop previous zooms
simulation.zoomTransition(2000)
const buttonsCoords = [{ x: x - 65, y: -2045 }] //only one button location?
const buttonsCoordsIndex = Math.floor(Math.random() * buttonsCoords.length) //pick a random element from the array
const moverDirection = stationNumber > 0 ? 1 : -1
console.log(stationNumber)
if (isExitOpen) {
level.exit.x = buttonsCoords[buttonsCoordsIndex].x;
level.exit.y = buttonsCoords[buttonsCoordsIndex].y - 25;
} else {
var gateButton = level.button(buttonsCoords[buttonsCoordsIndex].x, buttonsCoords[buttonsCoordsIndex].y, 126, false) //x, y, width = 126, isSpawnBase = true
gateButton.isUp = true
if (stationNumber > gatesOpenRight) {
var gate = level.doorMap(x + 1375, -525, 50, 375, 300, 20, false) //x, y, width, height, distance, speed = 20
} else if (stationNumber < gatesOpenLeft) {
var gate = level.doorMap(x - 1375, -525, 50, 375, 300, 20, false) //x, y, width, height, distance, speed = 20
}
}
//floor 0
spawn.mapRect(x + -1500, -210, 3000, 400);//station floor
const movers = []
movers.push(level.mover(x + -1200, -220, 900, 50, 3 * moverDirection))
movers.push(level.mover(x + 300, -220, 900, 50, 3 * moverDirection))
spawn.mapRect(x + -4700, -7000, 700, 5200);//Left wall
spawn.mapRect(x + 4000, -7000, 500, 5200);//Right wall
const portals = []
portals.push(level.portal({ x: x - 315, y: -310 }, Math.PI, { x: x - 3985, y: -2110 }, 0))
spawn.mapRect(x - 1375, -1100, 2750, 300);
spawn.mapRect(x + -300, -525, 600, 550);
//floor 1 fast with jump in middle
movers.push(level.mover(x - 4000, -2025, 2700, 50, 30 * moverDirection))
movers.push(level.mover(x + 1300, -2025, 2700, 50, 30 * moverDirection))
portals.push(level.portal({ x: x + 3985, y: -2110 }, Math.PI, { x: x - 3985, y: -3410 }, 0))
spawn.mapRect(x + -500, -2050, 1000, 150);
spawn.mapRect(x + -4200, -2300, 1225, 125);
spawn.mapRect(x + 2675, -2350, 1625, 150);
//up mode triggered by player contact
const elevator0 = level.elevator(x - 1300, -1175, 175, 50, -1600, 0.011, { up: 0.01, down: 0.7 })
const elevator1 = level.elevator(x + 1125, -1175, 175, 50, -1600, 0.011, { up: 0.01, down: 0.7 })
//floor 2 slow with some things to jump on and mobs
portals.push(level.portal({ x: x + 3985, y: -3410 }, Math.PI, { x: x - 3985, y: -5110 }, 0))
movers.push(level.mover(x - 4000, -3325, 8000, 50, 7 * moverDirection))
if (Math.random() < 0.5) {
spawn.mapRect(x + 1125, -3625, 325, 200);
spawn.mapRect(x - 1350, -3600, 375, 175);
spawn.mapRect(x + 325, -3825, 325, 100);
spawn.mapRect(x - 675, -3800, 450, 75);
spawn.mapRect(x - 1775, -3900, 175, 400);
spawn.mapRect(x - 2100, -4275, 325, 775);
spawn.mapRect(x + 2625, -3700, 450, 125);
spawn.mapRect(x - 3350, -3335, 175, 50);
spawn.mapRect(x - 200, -3335, 500, 50);
spawn.mapRect(x + 3200, -3335, 325, 50);
} else {
spawn.mapRect(x + -325, -3550, 425, 125);
spawn.mapRect(x + -1100, -3750, 425, 75);
spawn.mapRect(x + -2175, -3500, 200, 200);
spawn.mapRect(x + 675, -3700, 175, 75);
spawn.mapRect(x + 2375, -3425, 275, 125);
spawn.mapRect(x + 1750, -3650, 275, 75);
spawn.mapRect(x + 1125, -3850, 175, 550);
spawn.mapRect(x + -3300, -4175, 675, 550);
}
spawn.mapRect(x + 3550, -3625, 550, 100);
spawn.mapRect(x + -4100, -3650, 325, 100);
if (!isExitOpen) {
spawn.randomMob(x + 3900, -3725, 0);
spawn.randomMob(x + 3675, -3700, 0);
spawn.randomMob(x + 2075, -3400, 0);
spawn.randomMob(x + 2500, -3500, 0);
spawn.randomMob(x + 1975, -3700, 0);
spawn.randomMob(x + 1250, -3900, 0);
spawn.randomMob(x + 800, -3750, 0);
spawn.randomMob(x + 2700, -4700, 0);
spawn.randomMob(x + -75, -3650, 0);
spawn.randomMob(x + 575, -3500, 0);
spawn.randomMob(x + -850, -3900, 0);
spawn.randomMob(x + -2725, -4350, 0);
spawn.randomMob(x + -2975, -4300, 0);
spawn.randomMob(x + -3950, -3675, 0);
spawn.randomMob(x + -2950, -3450, 0);
spawn.randomMob(x + -2075, -3575, 0);
spawn.randomMob(x + -1650, -3450, 0);
spawn.randomMob(x + -2825, -4400, 0);
spawn.randomMob(x + -900, -4475, 0);
spawn.randomMob(x + -75, -3575, 0);
spawn.randomMob(x + 3900, -3775, 0);
spawn.randomMob(x + 2825, -3375, 0);
spawn.randomMob(x + 2075, -3425, 0);
spawn.randomMob(x + 1525, -3425, 0);
spawn.randomMob(x + 350, -3500, 0);
spawn.randomMob(x + -1675, -3650, 0);
spawn.randomMob(x + -3025, -3450, 0);
spawn.randomMob(x + -3850, -3750, 0);
}
//floor 3 fast with bumps
spawn.mapRect(x + -4250, -7000, 8475, 325);//roof
portals.push(level.portal({ x: x + 3985, y: -5110 }, Math.PI, { x: x + 320, y: -310 }, 0))
movers.push(level.mover(x - 4000, -5025, 8000, 50, 50 * moverDirection))
if (Math.random() < 0.5) {
spawn.mapVertex(x - 2100, -5050, "-150 0 150 0 5 -150 -5 -150")
spawn.mapVertex(x - 0, -5100, "-500 0 500 0 25 -300 -25 -300")
spawn.mapVertex(x + 2100, -5050, "-300 0 300 0 100 -100 -100 -100")
} else {
spawn.mapVertex(x - 2100, -5050, "-100 0 100 0 25 -100 -25 -100")
spawn.mapVertex(x - 0, -5050, "-400 0 400 0 100 -100 -100 -100")
spawn.mapVertex(x + 2100, -5050, "-400 0 400 0 100 -100 -100 -100")
}
spawn.mapRect(x + 2000, -6700, 200, 1250);
spawn.mapRect(x + -100, -6700, 200, 1075);
spawn.mapRect(x + -2125, -6700, 50, 925);
// spawn.mapRect(x + -4150, -5325, 975, 125); //portal over hang
// spawn.mapRect(x + 3325, -5300, 850, 100);//portal over hang
stationCustom = () => {
for (let i = 0; i < movers.length; i++) movers[i].push();
for (let i = 0; i < portals.length; i++) {
portals[i][2].query()
portals[i][3].query()
}
}
stationCustomTopLayer = () => {
for (let i = 0; i < portals.length; i++) {
portals[i][0].draw()
portals[i][1].draw()
portals[i][2].draw()
portals[i][3].draw()
}
elevator0.moveOnTouch()
elevator1.moveOnTouch()
//custom draw so you can see the mover tracks on subway map with the Line of sight graphics
ctx.strokeStyle = "#000"
ctx.lineWidth = 4;
ctx.setLineDash([40, 40]);
for (let i = 0; i < movers.length; i++) {
ctx.beginPath();
ctx.moveTo(movers[i].vertices[0].x + 2, movers[i].vertices[0].y - 3);
ctx.lineTo(movers[i].vertices[1].x - 2, movers[i].vertices[1].y - 3);
ctx.lineDashOffset = (-simulation.cycle * movers[i].VxGoal) % 80;
ctx.stroke();
}
ctx.setLineDash([0, 0]);
checkGate(gate, gateButton)
}
},
]
// stations[4]() //for testing a specific station
//update totalNumberOfStations to a higher number when adding new maps
simulation.zoomTransition(level.defaultZoom)
// stations[9]() //for testing a specific station
stations[stationList[Math.abs(stationNumber % stationList.length)]]() //*************** run this one when uploading
//add in standard station map infrastructure
spawn.mapRect(x + -8000, 0, 16000, 800);//tunnel floor

View File

@@ -30,6 +30,20 @@ const mobs = {
// }
}
},
defaultHealthBar() {
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].seePlayer.recall && mob[i].showHealthBar) {
const h = mob[i].radius * 0.3;
const w = mob[i].radius * 2;
const x = mob[i].position.x - w / 2;
const y = mob[i].position.y - w * 0.7;
ctx.fillStyle = "rgba(100, 100, 100, 0.3)";
ctx.fillRect(x, y, w, h);
ctx.fillStyle = "rgba(255,0,0,0.7)";
ctx.fillRect(x, y, w * mob[i].health, h);
}
}
},
healthBar() {
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].seePlayer.recall && mob[i].showHealthBar) {
@@ -1010,8 +1024,9 @@ const mobs = {
this.death(); //death with no power up
}
},
healthBar() { //draw health by mob //most health bars are drawn in mobs.healthbar();
if (this.seePlayer.recall) {
//draw health by mob //most health bars are drawn in mobs.healthBar(); , not this
healthBar() {
if (this.seePlayer.recall && !level.isHideHealth) {
const h = this.radius * 0.3;
const w = this.radius * 2;
const x = this.position.x - w / 2;

View File

@@ -987,6 +987,121 @@ const m = {
powerUps.boost.draw()
}
},
egg() {
m.isAltSkin = true
m.yOffWhen.stand = 52
m.yOffWhen.jump = 72
m.coyoteCycles = 11
m.hardLandCDScale = 0.5
m.hardLanding = 160
m.squirrelFx = 1.4;
m.squirrelJump = 1.16;
m.setMovement()
m.draw = function () {
if (powerUps.boost.endCycle > simulation.cycle) {
//gel that acts as if the wind is blowing it when player moves
ctx.save();
ctx.translate(m.pos.x, m.pos.y);
m.velocitySmooth = Vector.add(Vector.mult(m.velocitySmooth, 0.8), Vector.mult(player.velocity, 0.2))
ctx.rotate(Math.atan2(m.velocitySmooth.y, m.velocitySmooth.x))
ctx.beginPath();
const radius = 39
const mag = 14 * Vector.magnitude(m.velocitySmooth) + radius
ctx.arc(0, 0, radius, -Math.PI / 2, Math.PI / 2);
ctx.bezierCurveTo(-radius, radius, -radius, 0, -mag, 0); // bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
ctx.bezierCurveTo(-radius, 0, -radius, -radius, 0, -radius);
// const time = (powerUps.boost.endCycle - m.cycle) / powerUps.boost.duration
const time = Math.min(0.5, (powerUps.boost.endCycle - simulation.cycle) / powerUps.boost.duration)
ctx.fillStyle = `rgba(0,0,0,${0.04 + 0.3 * time})`
ctx.fill()
// ctx.strokeStyle = "#333"
// ctx.lineWidth = 1
// ctx.stroke();
ctx.restore();
}
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, -1.25);
m.drawLeg("#606060");
m.calcLeg(0, 0);
m.drawLeg("#444");
ctx.rotate(m.angle);
ctx.beginPath();
// ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.ellipse(0, 0, 0.9 * 31, 1.05 * 31, 0, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
// ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.ellipse(15, 0, 0.8 * 4, 1.1 * 4, 0, 0, 2 * Math.PI);
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.75 + m.yOffGoal * 0.25; //smoothly move leg height towards height goal
}
m.drawLeg = function (stroke) {
if (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2) {
m.flipLegs = 1;
} else {
m.flipLegs = -1;
}
const hip = { x: m.hip.x - 5, y: m.hip.y + 5 }
const sub = Vector.sub(m.knee, hip)
const off = Vector.mult(Vector.rotate(Vector.normalise(sub), Math.PI / 2), 8)
const kneeBraceHigh = Vector.add(hip, off)
const kneeBraceLow = Vector.add(kneeBraceHigh, Vector.mult(sub, 0.9))
const foot = { x: m.foot.x - 10, y: m.foot.y - 15 }
ctx.save();
ctx.scale(m.flipLegs, 1); //leg lines
ctx.beginPath();
ctx.moveTo(hip.x, hip.y);
ctx.lineTo(m.knee.x, m.knee.y);
ctx.lineTo(foot.x, foot.y);
//extra upper leg brace
ctx.moveTo(kneeBraceHigh.x, kneeBraceHigh.y);
ctx.lineTo(kneeBraceLow.x, kneeBraceLow.y);
ctx.lineTo(m.knee.x, m.knee.y);
ctx.strokeStyle = stroke;
ctx.lineWidth = 3;
ctx.stroke();
//foot
ctx.beginPath();
ctx.moveTo(foot.x, foot.y);
ctx.quadraticCurveTo(m.foot.x - 30, m.foot.y + 12, m.foot.x + 13, m.foot.y + 3);
ctx.lineWidth = 1.5;
ctx.stroke();
//hip joint
ctx.beginPath();
ctx.arc(m.hip.x, m.hip.y - 2, 11, 0, 2 * Math.PI);
//knee joint
ctx.moveTo(m.knee.x + 3, m.knee.y);
ctx.arc(m.knee.x, m.knee.y, 3, 0, 2 * Math.PI);
//knee brace
// ctx.moveTo(kneeBraceHigh.x + 4, kneeBraceHigh.y);
// ctx.arc(kneeBraceHigh.x, kneeBraceHigh.y, 4, 0, 2 * Math.PI);
ctx.moveTo(kneeBraceLow.x + 2.5, kneeBraceLow.y);
ctx.arc(kneeBraceLow.x, kneeBraceLow.y, 2.5, 0, 2 * Math.PI);
//foot joint
ctx.moveTo(foot.x + 2.5, foot.y);
ctx.arc(foot.x, foot.y, 2.5, 0, 2 * Math.PI);
ctx.fillStyle = "#f6f6f6"//m.fillColor;
ctx.fill();
ctx.lineWidth = 1;
// ctx.strokeStyle = "#333"
ctx.stroke();
ctx.restore();
}
},
mech() {
m.isAltSkin = true
m.yOffWhen.stand = 52
@@ -1031,6 +1146,7 @@ const m = {
m.drawLeg("#606060");
m.calcLeg(0, 0);
m.drawLeg("#444");
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);

View File

@@ -250,7 +250,6 @@ const powerUps = {
} else if (type === "field") {
m.setField(index)
} else if (type === "tech") {
// if (tech.isBanish && tech.tech[index].isBanished) tech.tech[index].isBanished = false
simulation.inGameConsole(`<div class="circle-grid tech"></div> &nbsp; <span class='color-var'>tech</span>.giveTech("<strong class='color-text'>${tech.tech[index].name}</strong>")`);
tech.giveTech(index)
}
@@ -261,7 +260,6 @@ const powerUps = {
document.getElementById("choose-grid").style.pointerEvents = "none";
document.body.style.cursor = "none";
setTimeout(() => {
// if (!tech.isNoDraftPause)
document.body.style.cursor = "auto";
document.getElementById("choose-grid").style.pointerEvents = "auto";
document.getElementById("choose-grid").style.transitionDuration = "0s";
@@ -269,7 +267,7 @@ const powerUps = {
simulation.isChoosing = true; //stops p from un pausing on key down
if (!simulation.paused) {
if (tech.isNoDraftPause) {
if (tech.isNoDraftPause || level.isNoPause) {
document.getElementById("choose-grid").style.opacity = "1"
} else {
simulation.paused = true;
@@ -610,14 +608,6 @@ const powerUps = {
tech.addJunkTechToPool(0.01)
}
powerUps.research.currentRerollCount++
// if (tech.isBanish && type === 'tech') { // banish researched tech
// const banishLength = tech.isDeterminism ? 1 : 3 + tech.extraChoices * 2
// for (let i = 0; i < banishLength; i++) {
// const index = powerUps.tech.choiceLog.length - i - 1
// if (powerUps.tech.choiceLog[index] && tech.tech[powerUps.tech.choiceLog[index]]) tech.tech[powerUps.tech.choiceLog[index]].isBanished = true
// }
// simulation.inGameConsole(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`)
// }
if (tech.isResearchReality) {
m.switchWorlds()
simulation.trails()
@@ -769,24 +759,24 @@ const powerUps = {
if (tech.isSuperDeterminism) {
return `<div></div>`
} else if (tech.isCancelTech && tech.cancelTechCount === 0) {
return `<div class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 115px;"><span class="color-randomize">randomize</span></div>`
return `<div class='cancel-card sticky' onclick='powerUps.endDraft("${type}",true)' style="width: 115px;"><span class="color-randomize">randomize</span></div>`
} else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted && b.inventory.length === 0) { //don't show cancel if on initial level and haven't done tutorial
return `<div class='cancel-card' style="visibility: hidden;"></div>`
return `<div class='cancel-card sticky' style="visibility: hidden;"></div>`
} else {
return `<div class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 85px;">cancel</div>`
return `<div class='cancel-card sticky' onclick='powerUps.endDraft("${type}",true)' style="width: 85px;">cancel</div>`
}
},
researchText(type) {
let text = ""
if (type === "entanglement") {
text += `<div class='choose-grid-module entanglement flipX' onclick='powerUps.endDraft("${type}",true)'>entanglement</div>`
text += `<div class='choose-grid-module entanglement flipX sticky' onclick='powerUps.endDraft("${type}",true)'>entanglement</div>`
} else if (tech.isJunkResearch && powerUps.research.currentRerollCount < 2) {
text += `<div onclick="powerUps.research.use('${type}')" class='research-card'>` // style = "margin-left: 192px; margin-right: -192px;"
text += `<div onclick="powerUps.research.use('${type}')" class='research-card sticky'>` // style = "margin-left: 192px; margin-right: -192px;"
text += `<div><div> <span style="position:relative;">`
text += `<div class="circle-grid junk" style="position:absolute; top:0; left:${15 * i}px ;opacity:0.8; border: 1px #fff solid;width: 1.15em;height: 1.15em;"></div>`
text += `</span>&nbsp; <span class='research-select'>pseudoscience</span></div></div></div>`
} else if (powerUps.research.count > 0) {
text += `<div onclick="powerUps.research.use('${type}')" class='research-card' >` // style = "margin-left: 192px; margin-right: -192px;"
text += `<div onclick="powerUps.research.use('${type}')" class='research-card sticky' >` // style = "margin-left: 192px; margin-right: -192px;"
text += `<div><div><span style="position:relative;">`
for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `<div class="circle-grid research" style="font-size:0.82em; position:absolute; top:0; left:${(18 - len * 0.21) * i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
text += `</span>&nbsp; <span class='research-select'>${tech.isResearchReality ? "<span class='alt'>alternate reality</span>" : "research"}</span></div></div></div>`
@@ -798,7 +788,7 @@ const powerUps = {
researchAndCancelText(type) {
let text = `<div class='research-cancel'>`
if (type === "entanglement") {
text += `<span class='research-card entanglement flipX' style="width: 275px;" onclick='powerUps.endDraft("${type}",true)'><span style="letter-spacing: 6px;">entanglement</span></span>` //&zwnj;
text += `<span class='research-card entanglement flipX' style="width: 275px;" onclick='powerUps.endDraft("${type}",true)'><span style="letter-spacing: 6px;">entanglement</span></span>`
} else if (tech.isJunkResearch && powerUps.research.currentRerollCount < 2) {
text += `<span onclick="powerUps.research.use('${type}')" class='research-card' style="width: 275px;float: left;">` // style = "margin-left: 192px; margin-right: -192px;"
text += `<div><div><span style="position:relative;">`
@@ -1239,37 +1229,55 @@ const powerUps = {
for (let i = 0; i < tech.tech.length; i++) tech.tech[i].isRecentlyShown = false //reset recently shown back to zero
if (options.length > 0) {
let text = powerUps.buildColumns(totalChoices, "tech")
addTech = (choose) => {
if (tech.tech[choose].isFieldTech) {
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].isJunk) {
text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isSkin) {
text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isInstant) {
text += powerUps.instantTechText(choose, `powerUps.choose('tech',${choose})`)
} else { //normal tech
text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`)
}
}
if (tech.isRetain) {
for (let i = 0, len = powerUps.retainList.length; i < len; i++) {
//find index from name and add tech to options
for (let j = 0, len = tech.tech.length; j < len; j++) {
if (tech.tech[j].name === powerUps.retainList[i] && tech.tech[j].count < tech.tech[j].maxCount && tech.tech[j].allowed()) { //&& !tech.tech[j].isRecentlyShown
addTech(j)
}
}
}
}
for (let i = 0; i < totalChoices; i++) {
if (options.length < 1) break
const choose = options[Math.floor(Math.seededRandom(0, options.length))] //pick an element from the array of options
if (tech.isBanish) {
tech.tech[choose].isBanished = true
if (i === 0) simulation.inGameConsole(`options.length = ${optionLengthNoDuplicates} <em class='color-text'>//removed from pool by decoherence</em>`)
}
removeOption(choose) //move from future options pool to avoid repeats on this selection
tech.tech[choose].isRecentlyShown = true //this flag prevents this option from being shown the next time you pick up a tech power up
if (Math.random() < tech.junkChance + level.junkAdded) { // choose is set to a random JUNK tech
const list = []
for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].isJunk) list.push(i)
}
chooseJUNK = list[Math.floor(Math.random() * list.length)]
if (tech.isRetain) powerUps.retainList.push(tech.tech[chooseJUNK].name)
text += powerUps.junkTechText(chooseJUNK, `powerUps.choose('tech',${chooseJUNK})`)
} else {
if (tech.tech[choose].isFieldTech) {
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].isJunk) {
text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isSkin) {
text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isInstant) {
text += powerUps.instantTechText(choose, `powerUps.choose('tech',${choose})`)
} else { //normal tech
text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`)
const choose = options[Math.floor(Math.seededRandom(0, options.length))] //pick an element from the array of options
if (tech.isBanish) {
tech.tech[choose].isBanished = true
if (i === 0) simulation.inGameConsole(`options.length = ${optionLengthNoDuplicates} <em class='color-text'>//removed from pool by decoherence</em>`)
}
if (options.length < 1) break
removeOption(choose) //remove from future options pool to avoid repeats on this selection
//this flag prevents this option from being shown the next time you pick up a tech power up
//check if not extra choices from "path integral"
tech.tech[choose].isRecentlyShown = true
if (tech.isRetain) powerUps.retainList.push(tech.tech[choose].name)
addTech(choose)
}
}
if (tech.isExtraBotOption) {
@@ -1360,6 +1368,7 @@ const powerUps = {
}
},
},
retainList: [],
entanglement: {
name: "entanglement",
color: "#fff", //"hsl(248,100%,65%)",

View File

@@ -1497,7 +1497,7 @@ const tech = {
descriptionFunction() {
return `${powerUps.orb.boost(1)} also give <strong>0.3x</strong> <strong class='color-defense'>damage taken</strong><br>for <strong>${(powerUps.boost.duration / 60).toFixed(0)}</strong> seconds</span>`
},
maxCount: 9,
maxCount: 1,
count: 1,
frequency: 2,
frequencyDefault: 2,
@@ -3598,7 +3598,7 @@ const tech = {
allowed() {
return !tech.isSuperDeterminism
},
requires: "not superdeterminism",
requires: "not, superdeterminism",
bonusResearch: 7,
effect() {
tech.isBanish = true
@@ -3614,6 +3614,24 @@ const tech = {
tech.isBanish = false
}
},
{
name: "coherence",
description: `after observing a ${powerUps.orb.tech()} <strong class='color-choice'><span>ch</span><span>oi</span><span>ce</span></strong><br>that <strong class='color-choice'><span>ch</span><span>oi</span><span>ce</span></strong> is available for all <strong>all</strong> future ${powerUps.orb.tech()}`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return tech.isBanish
},
requires: "decoherence",
effect() {
tech.isRetain = true
},
remove() {
tech.isRetain = false
}
},
{
name: "peer review",
description: `after you <strong class='color-r'>research</strong> gain <strong>1.05x</strong> <strong class='color-d'>damage</strong><br>and <strong>+1%</strong> <strong class='color-junk'>JUNK</strong> <strong class='color-choice'><span>ch</span><span>oi</span><span>ces</span></strong>`,
@@ -3743,9 +3761,9 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isSuperDeterminism && !tech.isNoDraftPause
return !tech.isSuperDeterminism
},
requires: "not superdeterminism, eternalism",
requires: "not superdeterminism",
effect() {
tech.isPauseSwitchField = true;
for (let i = 0, len = tech.tech.length; i < len; i++) {
@@ -3763,7 +3781,7 @@ const tech = {
},
{
name: "eternalism",
description: `<strong>1.25x</strong> <strong class='color-d'>damage</strong><br><strong>time</strong> can't be <strong>paused</strong> <em style ="float: right;">(time can still be dilated)</em>`,
description: `<strong>1.3x</strong> <strong class='color-d'>damage</strong>, but <strong>time</strong> doesn't <strong>pause</strong><br>while <strong class='color-choice'><span>ch</span><span>oos</span><span>ing</span></strong> ${powerUps.orb.field()}, ${powerUps.orb.tech()}, or ${powerUps.orb.gun()}`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -3772,7 +3790,7 @@ const tech = {
return !tech.isPauseSwitchField && !tech.isPauseEjectTech && !tech.isWormHolePause
},
requires: "not unified field theory, paradigm shift, invariant",
damage: 1.25,
damage: 1.3,
effect() {
tech.damage *= this.damage
tech.isNoDraftPause = true
@@ -3960,7 +3978,7 @@ const tech = {
{
name: "dark patterns",
description: "<strong>1.3x</strong> <strong class='color-d'>damage</strong><br><strong>+15%</strong> <strong class='color-junk'>JUNK</strong> <strong class='color-choice'><span>ch</span><span>oi</span><span>ces</span></strong>",
maxCount: 9,
maxCount: 3,
count: 0,
frequency: 1,
frequencyDefault: 1,
@@ -4604,9 +4622,9 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isSuperDeterminism && !tech.isNoDraftPause
return !tech.isSuperDeterminism
},
requires: "not superdeterminism, eternalism",
requires: "not superdeterminism",
effect() {
tech.isPauseEjectTech = true;
},
@@ -6181,7 +6199,7 @@ const tech = {
{
name: "water shielding",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Radiation_protection#Radiation_shielding' class="link">water shielding</a>`,
description: "reduce <strong class='color-p'>radioactive</strong> effects on you by <strong>0.8x</strong><br><em>neutron bomb, drones, explosions, slime</em>",
description: "reduce <strong class='color-p'>radioactive</strong> effects on you by <strong>0.2x</strong><br><em>neutron bomb, drones, explosions, slime</em>",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -7735,7 +7753,7 @@ const tech = {
// },
name: "electronegativity",
descriptionFunction() {
return `<strong>1.0023x</strong> <strong class='color-d'>damage</strong> per <strong class='color-f'>energy</strong><br><em style ="float: right;">(${(1 + 0.23 * m.energy).toFixed(2)} at current energy, ${(1 + 0.23 * m.maxEnergy).toFixed(2)}x at maximum energy)</em>`
return `<strong>1.0023x</strong> <strong class='color-d'>damage</strong> per <strong class='color-f'>energy</strong><br><em style ="float: right;">(${(1 + 0.23 * m.energy).toFixed(2)}x, ${(1 + 0.23 * m.maxEnergy).toFixed(2)}x at max energy)</em>`
},
// description: "<strong>+1%</strong> <strong class='color-d'>damage</strong> per <strong>8</strong> stored <strong class='color-f'>energy</strong>",
isFieldTech: true,
@@ -11020,7 +11038,7 @@ const tech = {
},
{
name: "rhythm",
description: "you oscillate up and down",
description: "you oscillate up and down<br>also you look like an egg",
maxCount: 1,
count: 0,
frequency: 0,
@@ -11031,6 +11049,7 @@ const tech = {
},
requires: "",
effect() {
m.skin.egg();
setInterval(() => {
m.yOffWhen.stand = 53 + 28 * Math.sin(simulation.cycle * 0.2)
if (m.onGround && !m.crouch) m.yOffGoal = m.yOffWhen.stand
@@ -11929,6 +11948,7 @@ const tech = {
cancelTechCount: null,
isBotDamage: null,
isBanish: null,
isRetain: null,
isMaxEnergyTech: null,
isLowEnergyDamage: null,
isRewindBot: null,