plasma ball

plasma ball is now live, but it's still in beta
  still needs
    new graphics
    damage balancing
    fast decay in mob shields
    player angle rotation speed while firing adds to fire speed
    tech upgrade to get electrical arcs that randomly damage nearby mobs
    current tech synergy
      capacitor bank,plasma jet(range?)

reservoir level is less crowded, so you can dodge mobs easier
  horizontal flipped version is so reenabled
pure science renamed paradigm shift
difficulty scaling for heal and mob damage reduced 2%

some possible bug fixes, I don't know...
This commit is contained in:
landgreen
2022-03-20 15:43:51 -07:00
parent fc64d2daa4
commit dde4432279
11 changed files with 489 additions and 140 deletions

View File

@@ -1519,6 +1519,7 @@ const b = {
if (input.fire && Matter.Query.collides(this, map).length) {
Matter.Body.setPosition(this, Vector.add(this.position, { x: 20 * Math.cos(this.angle), y: 20 * Math.sin(this.angle) }))
if (Matter.Query.collides(this, map).length) {
Matter.Body.setVelocity(this, { x: 0, y: 0 });
Matter.Sleeping.set(this, true)
this.endCycle = simulation.cycle + 5
this.dropCaughtPowerUp()
@@ -2605,7 +2606,7 @@ const b = {
},
worm(where, isFreeze = tech.isSporeFreeze) { //used with the tech upgrade in mob.death()
const bIndex = bullet.length;
const wormSize = 6 + tech.wormSize * 7.2 * Math.random()
const wormSize = 6 + tech.wormSize * 7 * Math.random()
if (bIndex < 500) { //can't make over 500 spores
bullet[bIndex] = Bodies.polygon(where.x, where.y, 3, 3, {
inertia: Infinity,
@@ -2616,7 +2617,7 @@ const b = {
frictionAir: 0.025,
thrust: (tech.isFastSpores ? 0.001 : 0.0005) * (1 + 0.5 * (Math.random() - 0.5)),
wormSize: wormSize,
wormTail: 1 + wormSize,
wormTail: 1 + Math.max(4, wormSize - 2 * tech.wormSize),
dmg: (tech.isMutualism ? 7 : 2.9) * wormSize, //bonus damage from tech.isMutualism //2.5 is extra damage as worm
lookFrequency: 100 + Math.floor(37 * Math.random()),
classType: "bullet",
@@ -3329,6 +3330,165 @@ const b = {
y: speed * Math.sin(dir)
});
},
// plasmaBall(position, velocity, radius) {
// // radius *= Math.sqrt(tech.bulletSize)
// const me = bullet.length;
// bullet[me] = Bodies.polygon(position.x, position.y, 20, radius, {
// density: 0.000001, // 0.001 is normal density
// inertia: Infinity,
// frictionAir: 0.003,
// dmg: 0, //damage on impact
// damage: 0, //damage done over time
// scale: 1 - 0.006 / tech.isBulletsLastLonger,
// classType: "bullet",
// collisionFilter: {
// category: cat.bullet,
// mask: 0 //cat.mob | cat.mobBullet // cat.map | cat.body | cat.mob | cat.mobShield
// },
// minDmgSpeed: 0,
// endCycle: Infinity,
// count: 0,
// radius: radius,
// portFrequency: 5 + Math.floor(5 * Math.random()),
// nextPortCycle: Infinity, //disabled unless you have the teleport tech
// beforeDmg(who) {
// if (!this.target && who.alive) {
// this.target = who;
// if (who.radius < 20) {
// this.targetRelativePosition = {
// x: 0,
// y: 0
// } //find relative position vector for zero mob rotation
// } else if (Matter.Query.collides(this, [who]).length > 0) {
// const normal = Matter.Query.collides(this, [who])[0].normal
// this.targetRelativePosition = Vector.rotate(Vector.sub(Vector.sub(this.position, who.position), Vector.mult(normal, -this.radius)), -who.angle) //find relative position vector for zero mob rotation
// } else {
// this.targetRelativePosition = Vector.rotate(Vector.sub(this.position, who.position), -who.angle) //find relative position vector for zero mob rotation
// }
// this.collisionFilter.category = cat.body;
// this.collisionFilter.mask = null;
// let bestVertexDistance = Infinity
// let bestVertex = null
// for (let i = 0; i < this.target.vertices.length; i++) {
// const dist = Vector.magnitude(Vector.sub(this.position, this.target.vertices[i]));
// if (dist < bestVertexDistance) {
// bestVertex = i
// bestVertexDistance = dist
// }
// }
// this.targetVertex = bestVertex
// }
// },
// onEnd() {},
// do() {
// if (this.count < 20) {
// this.count++
// //grow
// const SCALE = 1.06
// Matter.Body.scale(this, SCALE, SCALE);
// this.radius *= SCALE;
// } else {
// //shrink
// Matter.Body.scale(this, this.scale, this.scale);
// this.radius *= this.scale;
// if (this.radius < 8) this.endCycle = 0;
// }
// if (this.target && this.target.alive) { //if stuck to a target
// const rotate = Vector.rotate(this.targetRelativePosition, this.target.angle) //add in the mob's new angle to the relative position vector
// if (this.target.isVerticesChange) {
// Matter.Body.setPosition(this, this.target.vertices[this.targetVertex])
// } else {
// Matter.Body.setPosition(this, Vector.add(Vector.add(rotate, this.target.velocity), this.target.position))
// }
// if (this.target.isBoss) {
// if (this.target.speed > 8) Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.98))
// } else {
// if (this.target.speed > 4) Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.95))
// }
// Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9);
// // Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9)
// if (this.target.isShielded) {
// this.target.damage(m.dmgScale * this.damage, true); //shield damage bypass
// const SCALE = 1 - 0.004 / tech.isBulletsLastLonger //shrink if mob is shielded
// Matter.Body.scale(this, SCALE, SCALE);
// this.radius *= SCALE;
// } else {
// this.target.damage(m.dmgScale * this.damage);
// }
// } else if (this.target !== null) { //look for a new target
// this.collisionFilter.category = cat.bullet;
// this.collisionFilter.mask = cat.mob //| cat.mobShield //cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
// if (tech.isSpawnBulletsOnDeath && bullet.length < 180 && !this.target.isMobBullet) {
// let targets = []
// for (let i = 0, len = mob.length; i < len; i++) {
// const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
// if (dist < 1000000) targets.push(mob[i])
// }
// const radius = Math.min(this.radius * 0.5, 9)
// const len = bullet.length < 80 ? 2 : 1
// for (let i = 0; i < len; i++) {
// if (targets.length - i > 0) {
// const index = Math.floor(Math.random() * targets.length)
// const speed = 6 + 6 * Math.random()
// const velocity = Vector.mult(Vector.normalise(Vector.sub(targets[index].position, this.position)), speed)
// b.foam(this.position, Vector.rotate(velocity, 0.5 * (Math.random() - 0.5)), radius)
// } else {
// b.foam(this.position, Vector.rotate({
// x: 15 + 10 * Math.random(),
// y: 0
// }, 2 * Math.PI * Math.random()), radius)
// }
// }
// }
// this.target = null
// } else if (Matter.Query.point(map, this.position).length > 0) { //slow when touching map or blocks
// const slow = 0.85
// Matter.Body.setVelocity(this, {
// x: this.velocity.x * slow,
// y: this.velocity.y * slow
// });
// const SCALE = 0.96
// Matter.Body.scale(this, SCALE, SCALE);
// this.radius *= SCALE;
// // } else if (Matter.Query.collides(this, body).length > 0) {
// } else if (Matter.Query.point(body, this.position).length > 0) {
// const slow = 0.9
// Matter.Body.setVelocity(this, {
// x: this.velocity.x * slow,
// y: this.velocity.y * slow
// });
// const SCALE = 0.96
// Matter.Body.scale(this, SCALE, SCALE);
// this.radius *= SCALE;
// } else {
// this.force.y += this.mass * tech.foamGravity; //gravity
// if (tech.isFoamAttract) {
// for (let i = 0, len = mob.length; i < len; i++) {
// if (!mob[i].isBadTarget && Vector.magnitude(Vector.sub(mob[i].position, this.position)) < 375 && mob[i].alive && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
// this.force = Vector.mult(Vector.normalise(Vector.sub(mob[i].position, this.position)), this.mass * 0.004)
// const slow = 0.9
// Matter.Body.setVelocity(this, {
// x: this.velocity.x * slow,
// y: this.velocity.y * slow
// });
// break
// }
// }
// }
// }
// if (this.nextPortCycle < simulation.cycle) { //teleport around if you have tech.isBulletTeleport
// this.nextPortCycle = simulation.cycle + this.portFrequency
// const range = 15 * Math.sqrt(this.radius) * Math.random()
// Matter.Body.setPosition(this, Vector.add(this.position, Vector.rotate({ x: range, y: 0 }, 2 * Math.PI * Math.random())))
// }
// }
// });
// if (tech.isBulletTeleport) bullet[me].nextPortCycle = simulation.cycle + bullet[me].portFrequency
// Composite.add(engine.world, bullet[me]); //add bullet to world
// Matter.Body.setVelocity(bullet[me], velocity);
// },
foam(position, velocity, radius) {
// radius *= Math.sqrt(tech.bulletSize)
const me = bullet.length;

View File

@@ -188,7 +188,7 @@ function collisionChecks(event) {
time: simulation.drawTime
});
}
if (tech.isLessDamageReduction && !mob[k].shield) mob[k].damageReduction *= mob[k].isBoss ? 1.01 : 1.06
if (tech.isLessDamageReduction && !mob[k].shield) mob[k].damageReduction *= mob[k].isBoss ? 1.005 : 1.05
return;
}
//mob + body collisions

View File

@@ -326,7 +326,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
</span>
&nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
} else if (tech.tech[i].isLore) {
text += `<div class="pause-grid-module"><div class="grid-title lore-text"><div class="circle-grid lore" ${style}></div> &nbsp; ${tech.tech[i].name} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
text += `<div class="pause-grid-module"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[i].name} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
} else {
text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" ${style}><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
}
@@ -379,7 +379,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
if (!who.classList.contains("build-tech-selected")) who.classList.add("build-tech-selected");
tech.giveTech(index)
} else if (!tech.tech[index].isNonRefundable) {
tech.totalCount -= tech.tech[index].count
// tech.totalCount -= tech.tech[index].count
tech.removeTech(index);
who.classList.remove("build-tech-selected");
} else {

View File

@@ -15,35 +15,35 @@ const level = {
start() {
if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.isHorizontalFlipped = true
// m.setField("molecular assembler")
// b.giveGuns("drones")
// tech.giveTech("autonomous navigation")
// tech.giveTech("delivery drone")
// tech.giveTech("dynamo-bot upgrade")
// m.setField("metamaterial cloaking")
// b.giveGuns("harpoon")
// tech.giveTech("grappling hook")
// tech.giveTech("bulk modulus")
// for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech");
// for (let i = 0; i < 9; i++) tech.giveTech("dynamo-bot")
// for (let i = 10; i < tech.tech.length; i++) { tech.tech[i].isBanished = true }
// powerUps.research.changeRerolls(100000)
// for (let i = 0; i < 2; i++) tech.giveTech("laser-bot")
// for (let i = 0; i < 2; i++) tech.giveTech("undefined")
// tech.tech[297].frequency = 100
// m.setField("plasma torch")
// tech.giveTech("plasma ball")
// m.immuneCycle = Infinity //you can't take damage
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// simulation.enableConstructMode() //used to build maps in testing mode
// level.reactor();
// level.testing(); //not in rotation, used for testing
// level.perplex()
if (simulation.isTraining) { level.walk(); } else { level.intro(); }
// level.pavilion(); //not in rotation, used for testing
if (simulation.isTraining) { level.walk(); } else { level.intro(); } //normal starting level ************************************************
// powerUps.research.changeRerolls(3000)
// for (let i = 0; i < 30; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "tech", false);
// for (let i = 0; i < 3; i++) tech.giveTech("undefined")
// lore.techCount = 3
// simulation.isCheating = false //true;
// localSettings.loreCount = 2; //this sets what conversation is heard
// localSettings.loreCount = 0; //this sets what conversation is heard
// if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
// level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation
// level.null()
// lore.unlockTesting();
// tech.giveTech("tinker"); //show junk tech in experiment mode
} else {
@@ -113,6 +113,9 @@ const level = {
for (let i = 0; i < 2; i++) powerUps.spawn(level.exit.x + 10 * (Math.random() - 0.5), level.exit.y - 100 + 10 * (Math.random() - 0.5), "tech", false) //exit
// for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + 90 * (Math.random() - 0.5), player.position.y + 90 * (Math.random() - 0.5), "tech", false); //start
}
if (m.plasmaBall) {
m.plasmaBall.isOn = false
}
},
trainingText(say) {
simulation.lastLogTime = 0; //clear previous messages
@@ -130,7 +133,7 @@ const level = {
simulation.accelScale = 1 //mob acceleration increases each level
simulation.CDScale = 1 //mob CD time decreases each level
simulation.dmgScale = Math.max(0.1, 0.34 * simulation.difficulty) //damage done by mobs scales with total levels
simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale;
simulation.healScale = 1 / (1 + simulation.difficulty * 0.052) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale;
},
difficultyIncrease(num = 1) {
for (let i = 0; i < num; i++) {
@@ -140,7 +143,7 @@ const level = {
if (simulation.CDScale > 0.15) simulation.CDScale *= 0.965 //mob CD time decreases each level
}
simulation.dmgScale = Math.max(0.1, 0.34 * simulation.difficulty) //damage done by mobs scales with total levels
simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale;
simulation.healScale = 1 / (1 + simulation.difficulty * 0.052) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale;
// console.log(`CD = ${simulation.CDScale}`)
},
difficultyDecrease(num = 1) { //used in easy mode for simulation.reset()
@@ -151,8 +154,8 @@ const level = {
if (simulation.CDScale < 1) simulation.CDScale /= 0.965 //mob CD time decreases each level
}
if (simulation.difficulty < 1) simulation.difficulty = 0;
simulation.dmgScale = Math.max(0.1, 0.35 * simulation.difficulty) //damage done by mobs scales with total levels
simulation.healScale = 1 / (1 + simulation.difficulty * 0.055)
simulation.dmgScale = Math.max(0.1, 0.34 * simulation.difficulty) //damage done by mobs scales with total levels
simulation.healScale = 1 / (1 + simulation.difficulty * 0.052)
},
difficultyText() {
if (simulation.difficultyMode === 1) {
@@ -836,7 +839,7 @@ const level = {
// const block = body[body.length] = Bodies.rectangle(x, y, width, height, {
collisionFilter: {
category: cat.map,
mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
mask: cat.player | cat.body | cat.bullet | cat.powerUp // | cat.mob | cat.mobBullet
},
isNoSetCollision: true,
inertia: Infinity, //prevents rotation
@@ -3173,9 +3176,12 @@ 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(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");
@@ -3190,12 +3196,19 @@ const level = {
spawn.mapVertex(-687, -1936, "-612 50 0 100 612 50 612 -50 -612 -50");
//2nd floor right building
spawn.mapRect(550, -3050, 600, 175);
// spawn.mapRect(550, -3050, 600, 175);
spawn.mapRect(550, -3050, 600, 75);
spawn.bodyRect(-125, -2025, 475, 25);
//2nd floor left building
spawn.mapRect(-925, -2350, 675, 200);
spawn.mapRect(-825, -2825, 425, 275);
// 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);
@@ -3203,8 +3216,11 @@ const level = {
spawn.bodyRect(-375, -2150, 100, 150, 0.2);
//2nd floor left pillar
spawn.mapRect(-1400, -2625, 325, 25);
spawn.mapRect(-1400, -3225, 325, 25);
spawn.mapRect(-1400, -3825, 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);
@@ -3231,7 +3247,7 @@ const level = {
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, 300, -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 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
@@ -3242,10 +3258,10 @@ const level = {
// 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
// simulation.isHorizontalFlipped = true
if (simulation.isHorizontalFlipped) { //flip the map horizontally
spawn.mapVertex(584, -2435, "0 0 300 0 150 600 0 600");
spawn.mapVertex(1116, -2435, "0 0 300 0 300 600 150 600");
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
@@ -3255,7 +3271,7 @@ const level = {
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, 700)
const boost1 = level.boost(-900, -2000, 790)
level.setPosToSpawn(500, 850); //normal spawn
level.custom = () => {
ctx.fillStyle = "#c0c3c9" ///!!!!!!!!!! for flipped x: newX = -oldX - width
@@ -3287,11 +3303,11 @@ const level = {
ctx.fill();
//shadow
ctx.fillStyle = "rgba(0,10,30,0.1)"
ctx.fillRect(-1150, -2900, 600, 925);
ctx.fillRect(-1150, -3000, 600, 1025);
ctx.fillRect(450, -3100, 300, 275);
ctx.fillRect(450, -3625, 200, 225);
ctx.fillRect(400, -2575, 425, 325);
ctx.fillRect(250, -2150, 675, 150);
ctx.fillRect(400, -2775, 425, 450);
ctx.fillRect(250, -2300, 675, 300);
slime.query();
if (isWaterfallFilling) {
@@ -3319,6 +3335,8 @@ 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.33) {
spinnerArray.push(level.spinner(65, -300, 40, 450, 0.003, Math.PI / 2))
@@ -3336,7 +3354,7 @@ const level = {
Matter.Body.setVertices(spinnerArray[spinnerArray.length - 1].bodyB, Vertices.fromPath(hexagon))
}
const boost1 = level.boost(800, -2000, 700)
const boost1 = level.boost(800, -2000, 790)
level.custom = () => {
ctx.fillStyle = "#c0c3c9"
@@ -3346,7 +3364,6 @@ const level = {
ctx.fillStyle = "#d0d4d6"
ctx.fillRect(-1100, -1925, 825, 2925) //large pillar background
ctx.fillRect(450, -1925, 825, 2925) //large pillar background
ctx.fillStyle = "#cff" //exit
ctx.fillRect(1475, -4900, 525, 425)
level.exit.drawAndCheck();
@@ -3369,11 +3386,11 @@ const level = {
ctx.fill();
//shadow
ctx.fillStyle = "rgba(0,10,30,0.1)"
ctx.fillRect(550, -2900, 600, 925);
ctx.fillRect(550, -3000, 600, 1025);
ctx.fillRect(-750, -3100, 300, 275);
ctx.fillRect(-650, -3625, 200, 225);
ctx.fillRect(-825, -2575, 425, 325);
ctx.fillRect(-925, -2150, 675, 150);
ctx.fillRect(-825, -2775, 425, 450);
ctx.fillRect(-925, -2300, 675, 300);
slime.query();
if (isWaterfallFilling) {
@@ -6019,10 +6036,10 @@ const level = {
const balance = level.spinner(5500, -412.5, 25, 660) //entrance
const rotor = level.rotor(7000, 580, -0.001);
const doorSortieSalle = level.door(8590, -520, 20, 800, 750)
let buttonSortieSalle
let portalEnBas
// let buttonSortieSalle
// let portalEnBas
let portalEnHaut
let door3isClosing = false;
// let door3isClosing = false;
function drawOnTheMapMapRect(x, y, dx, dy) {
spawn.mapRect(x, y, dx, dy);

View File

@@ -34,9 +34,9 @@ const m = {
category: cat.player,
mask: cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield
},
death() {
m.death();
}
// death() {
// m.death();
// }
});
Matter.Body.setMass(player, m.mass);
Composite.add(engine.world, [player]);
@@ -2085,7 +2085,126 @@ const m = {
description: "use <strong class='color-f'>energy</strong> to emit short range <strong class='color-plasma'>plasma</strong><br><strong class='color-d'>damages</strong> and <strong>pushes</strong> mobs away",
set() {
b.isExtruderOn = false
if (tech.isExtruder) {
if (m.plasmaBall) {
m.plasmaBall.isOn = false
Matter.Composite.remove(engine.world, m.plasmaBall);
}
if (tech.isPlasmaBall) {
// m.plasmaBall = {
// position: { x: m.pos.x + 10 * Math.cos(m.angle), y: m.pos.y + 10 * Math.sin(m.angle) },
// velocity: { x: 0, y: 0 },
// radius: 1,
// }
m.plasmaBall = Bodies.circle(m.pos.x + 10 * Math.cos(m.angle), m.pos.y + 10 * Math.sin(m.angle), 1, {
collisionFilter: {
group: 0,
category: 0,
mask: 0 //cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield
},
frictionAir: 0,
// radius: 1,
// friction: 0,
// frictionStatic: 0,
// restitution: 0,
alpha: 0.6,
isAttached: false,
isOn: false,
drain: 0.0012,
radiusLimit: 10,
damage: 0.18,
setPositionToNose() {
const nose = { x: m.pos.x + 10 * Math.cos(m.angle), y: m.pos.y + 10 * Math.sin(m.angle) }
Matter.Body.setPosition(this, Vector.add(nose, Vector.mult(Vector.normalise(Vector.sub(nose, m.pos)), this.circleRadius)));
},
fire() {
this.isAttached = false;
const speed = 4 //scale with mass?
Matter.Body.setVelocity(this, {
x: 0.4 * player.velocity.x + speed * Math.cos(m.angle),
y: 0.2 * player.velocity.y + speed * Math.sin(m.angle)
});
},
do() {
if (this.isOn) {
//collisions with map
if (Matter.Query.collides(this, map).length > 0) {
const scale = Math.max(0.7, 0.99 - 1 / m.plasmaBall.circleRadius)
Matter.Body.scale(m.plasmaBall, scale, scale); //shrink fast
if (m.plasmaBall.circleRadius < m.plasmaBall.radiusLimit) this.isOn = false
}
//collisions with mobs
const whom = Matter.Query.collides(this, mob)
const dmg = this.damage * m.dmgScale
for (let i = 0, len = whom.length; i < len; i++) {
if (whom[i].bodyA.alive) whom[i].bodyA.damage(dmg);
if (whom[i].bodyB.alive) whom[i].bodyB.damage(dmg);
}
//graphics
var gradient = ctx.createRadialGradient(this.position.x, this.position.y, 0, this.position.x, this.position.y, this.circleRadius);
gradient.addColorStop(0, `rgba(255,255,255,${this.alpha})`);
gradient.addColorStop(0.2, `rgba(255,200,255,${this.alpha})`);
gradient.addColorStop(1, `rgba(255,0,255,${this.alpha})`);
ctx.fillStyle = gradient
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.circleRadius, 0, 2 * Math.PI);
ctx.fill();
}
},
});
Composite.add(engine.world, m.plasmaBall);
m.hold = function() {
if (m.isHolding) {
m.drawHold(m.holdingTarget);
m.holding();
m.throwBlock();
} else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
m.grabPowerUp();
m.lookForPickUp();
//field is active
if (!m.plasmaBall.isAttached) { //return ball to player
const scale = 0.7
Matter.Body.scale(m.plasmaBall, scale, scale); //shrink fast
if (m.plasmaBall.circleRadius < m.plasmaBall.radiusLimit) {
m.plasmaBall.isAttached = true
m.plasmaBall.isOn = true
m.plasmaBall.setPositionToNose()
}
} else if (m.energy > m.plasmaBall.drain) { //charge up when attached
m.energy -= m.plasmaBall.drain;
const scale = 1 + 5 * Math.pow(Math.max(1, m.plasmaBall.circleRadius), -1.5)
Matter.Body.scale(m.plasmaBall, scale, scale); //grow
m.plasmaBall.setPositionToNose()
//add friction for player when holding ball, maybe more friction in vertical
} else {
m.fieldCDcycle = m.cycle + 90;
m.plasmaBall.fire()
}
} else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
m.pickUp();
} else {
m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
if (m.plasmaBall.isAttached) {
m.fieldCDcycle = m.cycle + 30;
m.plasmaBall.fire()
}
}
m.drawFieldMeter("rgba(0, 0, 0, 0.2)")
m.plasmaBall.do()
}
} else if (tech.isExtruder) {
m.hold = function() {
b.isExtruderOn = false
if (m.isHolding) {

View File

@@ -821,7 +821,7 @@ const simulation = {
level.zones = [];
simulation.drawList = [];
if (tech.isDronesTravel) {
if (tech.isDronesTravel && player.alive) {
//count drones
let count = 0
let deliveryCount = 0
@@ -945,7 +945,7 @@ const simulation = {
}
}
if (m.pos.y > simulation.fallHeight) { // if 4000px deep
if (m.pos.y > simulation.fallHeight || isNaN(player.position.x)) { // if 4000px deep
Matter.Body.setVelocity(player, {
x: 0,
y: 0

View File

@@ -3747,7 +3747,7 @@ const spawn = {
if (this.countDown-- < 0) { //explode
this.death();
//hit player
if (Vector.magnitude(Vector.sub(this.position, player.position)) < this.explodeRange) {
if (Vector.magnitude(Vector.sub(this.position, player.position)) < this.explodeRange && m.immuneCycle < m.cycle) {
m.damage(0.01 * simulation.dmgScale * (tech.isRadioactiveResistance ? 0.25 : 1));
m.energy -= 0.1 * (tech.isRadioactiveResistance ? 0.25 : 1)
if (m.energy < 0) m.energy = 0

View File

@@ -58,6 +58,7 @@ const tech = {
simulation.makeTextLog(`<span class='color-var'>tech</span>.removeTech("<span class='color-text'>${tech.tech[index].name}</span>")`)
tech.tech[index].remove();
tech.tech[index].count = 0;
tech.totalCount -= totalRemoved
simulation.updateTechHUD();
tech.tech[index].isLost = true
simulation.updateTechHUD();
@@ -211,7 +212,7 @@ const tech = {
},
damageFromTech() {
let dmg = 1 //m.fieldDamage
if (tech.isTechDebt) dmg *= 4 - 0.1 * tech.totalCount
if (tech.isTechDebt) dmg *= 4 - 0.08 * tech.totalCount
if (tech.isAxion && tech.isHarmMACHO) dmg *= 1 + 0.75 * (1 - m.harmReduction())
if (tech.OccamDamage) dmg *= tech.OccamDamage
if (tech.isCloakingDamage) dmg *= 1.35
@@ -370,7 +371,7 @@ const tech = {
if (gunTechPool.length) {
const index = Math.floor(Math.random() * gunTechPool.length)
tech.giveTech(gunTechPool[index]) // choose from the gun pool
tech.tech[gunTechPool[index]].isFromAppliedScience = true //makes it not remove properly under pure science
tech.tech[gunTechPool[index]].isFromAppliedScience = true //makes it not remove properly under paradigm shift
simulation.makeTextLog(`<span class='color-var'>tech</span>.giveTech("<span class='color-text'>${tech.tech[gunTechPool[index]].name}</span>")`)
}
}
@@ -747,7 +748,7 @@ const tech = {
},
{
name: "regression",
description: "bullet <strong>collisions</strong> increase <strong>vulnerability</strong> to<br><strong class='color-d'>damage</strong> by <strong>6%</strong> for mobs <em>(1% for bosses)</em>",
description: "bullet <strong>collisions</strong> increase <strong>vulnerability</strong> to<br><strong class='color-d'>damage</strong> by <strong>5%</strong> for mobs <em>(0.5% for bosses)</em>",
maxCount: 1,
count: 0,
frequency: 1,
@@ -1620,7 +1621,7 @@ const tech = {
},
{
name: "Pauli exclusion",
description: `after receiving <strong class='color-harm'>harm</strong> from a <strong>collision</strong> become<br><strong>immune</strong> to <strong class='color-harm'>harm</strong> for <strong>1.5</strong> extra seconds`,
description: `after receiving <strong class='color-harm'>harm</strong> from a <strong>collision</strong> become<br><strong>immune</strong> to <strong class='color-harm'>harm</strong> for <strong>2.5</strong> extra seconds`,
maxCount: 9,
count: 0,
frequency: 1,
@@ -1628,7 +1629,7 @@ const tech = {
allowed() { return true },
requires: "",
effect() {
tech.collisionImmuneCycles += 90;
tech.collisionImmuneCycles += 150;
if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
},
remove() {
@@ -1637,7 +1638,7 @@ const tech = {
},
{
name: "spinstatistics theorem",
description: `become <strong>immune</strong> to <strong class='color-harm'>harm</strong> for <strong>1.9</strong> seconds<br>once every <strong>7</strong> seconds`,
description: `become <strong>immune</strong> to <strong class='color-harm'>harm</strong> for <strong>1.75</strong> seconds<br>once every <strong>7</strong> seconds`,
maxCount: 3,
count: 0,
frequency: 1,
@@ -1647,7 +1648,7 @@ const tech = {
},
requires: "",
effect() {
tech.cyclicImmunity += 114;
tech.cyclicImmunity += 105;
},
remove() {
tech.cyclicImmunity = 0;
@@ -3068,7 +3069,7 @@ const tech = {
}
},
{
name: "pure science",
name: "paradigm shift",
description: `<strong>clicking</strong> <strong class='color-m'>tech</strong> while paused <strong>ejects</strong> them<br><strong>4%</strong> chance to convert that tech into ${powerUps.orb.research(1)}`,
maxCount: 1,
count: 0,
@@ -3088,7 +3089,7 @@ const tech = {
// description: `increase <strong class='color-d'>damage</strong> by <strong>300%</strong> minus <strong>10%</strong> for <strong class='color-m'>tech</strong> you have learned(${4 - 0.1 * tech.totalCount})`,
// description: `increase <strong class='color-d'>damage</strong> by <strong>300%</strong>, but reduce <strong class='color-d'>damage</strong><br>by <strong>10%</strong> for <strong class='color-m'>tech</strong> you have learned`,
descriptionFunction() {
return `increase <strong class='color-d'>damage</strong> by <strong>300%</strong> minus <strong>10%</strong><br>for <strong class='color-m'>tech</strong> you have learned <em>(${Math.floor(100*(4 - 0.1 * tech.totalCount))-100}%)</em>`
return `increase <strong class='color-d'>damage</strong> by <strong>300%</strong> minus <strong>8%</strong><br>for <strong class='color-m'>tech</strong> you have learned <em>(${Math.floor(100*(4 - 0.08 * tech.totalCount))-100}%)</em>`
},
maxCount: 1,
count: 0,
@@ -3704,7 +3705,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return ((tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.nailRecoil) || (tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isFoamShot && !tech.isSporeWorm)) && !tech.isRivets && !tech.isIncendiary && !tech.isIceCrystals
return ((tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.nailRecoil) || (tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isFoamShot && !tech.isSporeWorm)) && !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",
effect() {
@@ -3743,7 +3744,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return ((tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate) || (tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isFoamShot && !tech.isSporeWorm)) && !tech.isNeedles && !tech.isIceCrystals
return ((tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate) || (tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isFoamShot && !tech.isSporeWorm)) && !tech.isNeedles && !tech.isIceCrystals && !tech.isIceShot
},
requires: "nail gun shot gun, not ice crystal, needles, or pneumatic actuator",
effect() {
@@ -5004,7 +5005,7 @@ const tech = {
name: "annelids",
description: "increase <strong class='color-p' style='letter-spacing: -0.8px;'>worm</strong> size and <strong class='color-d'>damage</strong><br>between <strong>10%</strong> and <strong>120%</strong>",
isGunTech: true,
maxCount: 9,
maxCount: 3,
count: 0,
frequency: 3,
frequencyDefault: 3,
@@ -6445,7 +6446,7 @@ const tech = {
frequency: 3,
frequencyDefault: 3,
allowed() {
return (build.isExperimentSelection || powerUps.research.count > 0) && m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isMissileField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport)
return (build.isExperimentSelection || powerUps.research.count > 0) && m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isMissileField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport || tech.isDronesTravel)
},
requires: "molecular assembler, no other manufacturing, no drone tech",
effect() {
@@ -6472,7 +6473,7 @@ const tech = {
frequency: 3,
frequencyDefault: 3,
allowed() {
return (build.isExperimentSelection || powerUps.research.count > 0) && m.maxEnergy > 0.5 && m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isSporeField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport)
return (build.isExperimentSelection || powerUps.research.count > 0) && m.maxEnergy > 0.5 && m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isSporeField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport || tech.isDronesTravel)
},
requires: "molecular assembler, no other manufacturing, no drone tech",
effect() {
@@ -6499,7 +6500,7 @@ const tech = {
frequency: 3,
frequencyDefault: 3,
allowed() {
return (build.isExperimentSelection || powerUps.research.count > 0) && m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isSporeField || tech.isMissileField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport)
return (build.isExperimentSelection || powerUps.research.count > 0) && m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isSporeField || tech.isMissileField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport || tech.isDronesTravel)
},
requires: "molecular assembler, no other manufacturing, no drone tech",
effect() {
@@ -6635,6 +6636,27 @@ const tech = {
if (this.count > 0) powerUps.research.changeRerolls(this.count * 2)
}
},
{
name: "plasma ball",
description: "charge up a ball of <strong class='color-plasma'>plasma</strong> and fire it",
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "plasma torch" && !tech.isExtruder
},
requires: "plasma torch, not extruder",
effect() {
tech.isPlasmaBall = true;
m.fieldUpgrades[m.fieldMode].set()
},
remove() {
tech.isPlasmaBall = false;
if (this.count) m.fieldUpgrades[m.fieldMode].set()
}
},
{
name: "extruder",
description: "<strong class='color-plasma'>plasma</strong> <strong>torch</strong> <strong class='color-plasma'>extrudes</strong> a thin hot wire<br>increases <strong class='color-d'>damage</strong> and <strong class='color-f'>energy</strong> drain",
@@ -6644,9 +6666,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "plasma torch"
return m.fieldUpgrades[m.fieldMode].name === "plasma torch" && !tech.isPlasmaBall
},
requires: "plasma torch",
requires: "plasma torch, not plasma ball",
effect() {
tech.isExtruder = true;
m.fieldUpgrades[m.fieldMode].set()
@@ -7642,54 +7664,6 @@ const tech = {
if (this.count) m.look = m.lookDefault
}
},
{
name: "Mech v4.48",
description: `open a portal to a primordial version of reality`,
maxCount: 1,
count: 0,
frequency: 0,
isNonRefundable: true,
isJunk: true,
allowed() { return true },
requires: "",
effect() {
window.open('https://scratch.mit.edu/projects/14005697/fullscreen/', '_blank')
},
remove() {}
},
{
name: "planetesimals",
description: `play <strong>planetesimals</strong> <em style = 'font-size:80%;'>(an asteroids-like game)</em><br>clear <strong>levels</strong> in <strong>planetesimals</strong> to spawn <strong class='color-m'>tech</strong><br>if you <strong style="color:red;">die</strong> in <strong>planetesimals</strong> you <strong style="color:red;">die</strong> in <strong>n-gon</strong>`,
maxCount: 1,
count: 0,
frequency: 0,
isNonRefundable: true,
isJunk: true,
allowed() { return true },
requires: "",
effect() {
window.open('../../planetesimals/index.html', '_blank')
// powerUps.spawn(m.pos.x, m.pos.y, "tech");
// for communicating to other tabs, like planetesimals
// Connection to a broadcast channel
const bc = new BroadcastChannel('planetesimals');
bc.activated = false
bc.onmessage = function(ev) {
if (ev.data === 'tech') powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
if (ev.data === 'death') {
m.death()
bc.close(); //end session
}
if (ev.data === 'ready' && !bc.activated) {
bc.activated = true //prevents n-gon from activating multiple copies of planetesimals
bc.postMessage("activate");
}
}
},
remove() {}
},
{
name: "facsimile",
description: `inserts a copy of your current level into the level list`,
@@ -9165,6 +9139,54 @@ const tech = {
},
remove() {}
},
{
name: "Mech v4.48",
description: `open a portal to a primordial version of reality`,
maxCount: 1,
count: 0,
frequency: 0,
isNonRefundable: true,
isJunk: true,
allowed() { return true },
requires: "",
effect() {
window.open('https://scratch.mit.edu/projects/14005697/fullscreen/', '_blank')
},
remove() {}
},
{
name: "planetesimals",
description: `play <strong>planetesimals</strong> <em style = 'font-size:80%;'>(an asteroids-like game)</em><br>clear <strong>levels</strong> in <strong>planetesimals</strong> to spawn <strong class='color-m'>tech</strong><br>if you <strong style="color:red;">die</strong> in <strong>planetesimals</strong> you <strong style="color:red;">die</strong> in <strong>n-gon</strong>`,
maxCount: 1,
count: 0,
frequency: 0,
isNonRefundable: true,
isJunk: true,
allowed() { return true },
requires: "",
effect() {
window.open('../../planetesimals/index.html', '_blank')
// powerUps.spawn(m.pos.x, m.pos.y, "tech");
// for communicating to other tabs, like planetesimals
// Connection to a broadcast channel
const bc = new BroadcastChannel('planetesimals');
bc.activated = false
bc.onmessage = function(ev) {
if (ev.data === 'tech') powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
if (ev.data === 'death') {
m.death()
bc.close(); //end session
}
if (ev.data === 'ready' && !bc.activated) {
bc.activated = true //prevents n-gon from activating multiple copies of planetesimals
bc.postMessage("activate");
}
}
},
remove() {}
},
//**************************************************
//************************************************** undefined / lore
//************************************************** tech
@@ -9537,5 +9559,6 @@ const tech = {
isGrapple: null,
isImmuneGrapple: null,
isDronesTravel: null,
isTechDebt: null
isTechDebt: null,
isPlasmaBall: null
}