`
for (let i = 0; i < level.levels.length; i++) {
if (i < level.levelsCleared) {
@@ -322,7 +325,7 @@ const level = {
simulation.draw.cons();
simulation.draw.body();
level.customTopLayer();
- let count = simulation.testing ? 0 : 240
+ let count = countMax = simulation.testing ? 0 : 180
let newLevelDraw = () => {
count--
if (count > 0) {
@@ -354,7 +357,16 @@ const level = {
// mobs.draw();
// } else
// if (count < 240) {
+
+ // ctx.lineDashOffset = 900 * Math.random()
+ // ctx.setLineDash([3, -8 + 0.5 * count]);
+
+ const scale = 10
+ ctx.setLineDash([scale * (countMax - count), scale * count]);
simulation.draw.wireFrame();
+ ctx.setLineDash([]);
+
+
// }
// else if (count === 91) { //hide text boss
// document.getElementById("choose-grid").style.opacity = "0"
@@ -591,6 +603,7 @@ const level = {
document.getElementById("choose-grid").style.visibility = "visible"
document.getElementById("choose-training").addEventListener("click", () => {
level.unPause()
+ document.body.style.cursor = "none";
simulation.isTraining = true
level.levelsCleared--;
level.onLevel--
@@ -608,6 +621,7 @@ const level = {
});
document.getElementById("choose-unPause").addEventListener("click", () => {
level.unPause()
+ document.body.style.cursor = "none";
level.nextLevel()
//reset hide image style
if (localSettings.isHideImages) {
@@ -31120,6 +31134,661 @@ const level = {
boss.showHealthBar = true;
powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
+ arena() {
+ simulation.makeTextLog(`
arena by
Richard0820`)
+ let isUsingSwordMod = false;
+ for (let i = 0; i < tech.tech.length; i++) {
+ if (tech.tech[i].name === 'size-weight illusion') { //to detect if the player is using the sword mod so that it won't mess up their mod. The sword mod adds this tech so if it is detected then the sword won't be removed from the gun array //Landgreen, don't add a tech with the same name
+ isUsingSwordMod = true;
+ }
+ }
+ if (!isUsingSwordMod) {
+ (function () {
+ const e = {
+ name: "sword",
+ descriptionFunction() { return `swing a
sword that
lifesteals healthdrains
health instead of ammunition
doesn't use
ammo` },
+ ammo: Infinity,
+ ammoPack: Infinity,
+ defaultAmmoPack: Infinity,
+ have: false,
+ cycle: 0,
+ sword: undefined,
+ bladeSegments: undefined,
+ bladeTrails: [],
+ angle: 0,
+ constraint: undefined,
+ do() {
+ if (input.fire && m.fireCDcycle > m.cycle) {
+ if (tech.isEnergyHealth) {
+ m.energy -= 0.004;
+ } else {
+ m.health -= 0.001;
+ m.displayHealth();
+ }
+ }
+ if (b.activeGun !== null && input.fire && (tech.isEnergyHealth ? m.energy >= 0.11 : m.health >= 0.11)) {
+ if (!this.sword && b.guns[b.activeGun].name === 'sword') {
+ Matter.Body.setMass(player, 1000);
+ ({ sword: this.sword, bladeSegments: this.bladeSegments } = this.createAndSwingSword());
+ this.angle = m.angle;
+ }
+ }
+ if (this.sword && !input.fire) {
+ this.cycle = 0;
+ Matter.Body.setAngularVelocity(this.sword, 0);
+ Matter.Body.setMass(player, 5)
+ Composite.remove(engine.world, this.sword);
+ this.sword.parts.forEach(part => {
+ Composite.remove(engine.world, part);
+ const index = bullet.indexOf(part);
+ if (index !== -1) {
+ bullet.splice(index, 1);
+ }
+ });
+ this.sword = undefined;
+ if (this.constraint) {
+ Composite.remove(engine.world, this.constraint);
+ this.constraint = undefined;
+ }
+ this.bladeTrails = [];
+ m.fireCDcycle = m.cycle + 10;
+ } else {
+ if (this.sword && (tech.isEnergyHealth ? m.energy >= 0.11 : m.health >= 0.11)) {
+ let handle;
+ for (let i = 0; i < bullet.length; i++) {
+ if (bullet[i].customName == "handle") {
+ handle = bullet[i];
+ }
+ }
+ if (!(this.angle > -Math.PI / 2 && this.angle < Math.PI / 2)) {
+ Matter.Body.setAngularVelocity(this.sword, -Math.PI * 0.1);
+ } else {
+ Matter.Body.setAngularVelocity(this.sword, Math.PI * 0.1);
+ }
+ if (!this.constraint && (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) {
+ this.constraint = Constraint.create({
+ bodyA: player,
+ bodyB: this.sword,
+ pointB: { x: -9, y: ((handle.position.y - this.sword.position.y)) },
+ stiffness: 0.1,
+ damping: 0.0001815,
+ length: 0,
+
+ });
+ Composite.add(engine.world, this.constraint);
+ } else if (!this.constraint) {
+ this.constraint = Constraint.create({
+ bodyA: player,
+ bodyB: this.sword,
+ pointB: { x: 9, y: ((handle.position.y - this.sword.position.y)) },
+ stiffness: 0.1,
+ damping: 0.0001815,
+ length: 0,
+ });
+ Composite.add(engine.world, this.constraint);
+ }
+ } else if (this.sword) {
+ if (tech.isEnergyHealth) {
+ m.energy = 0.01;
+ m.immuneCycle = m.cycle + 30;
+ }
+ this.cycle = 0;
+ Matter.Body.setAngularVelocity(this.sword, 0);
+ Matter.Body.setMass(player, 5)
+ Composite.remove(engine.world, this.sword);
+ this.sword.parts.forEach(part => {
+ Composite.remove(engine.world, part);
+ const index = bullet.indexOf(part);
+ if (index !== -1) {
+ bullet.splice(index, 1);
+ }
+ });
+ this.sword = undefined;
+ if (this.constraint) {
+ Composite.remove(engine.world, this.constraint);
+ this.constraint = undefined;
+ }
+ this.bladeTrails = [];
+ m.fireCDcycle = 0;
+ }
+ }
+ if (this.sword) {
+ for (let i = 0; i < this.bladeSegments.length; i++) {
+ const blade = this.bladeSegments[i];
+ const trail = this.bladeTrails[i] || [];
+ const vertices = blade.vertices.map(vertex => ({ x: vertex.x, y: vertex.y }));
+ trail.push(vertices);
+ if (trail.length > 10) {
+ trail.shift();
+ }
+ this.bladeTrails[i] = trail;
+ }
+
+ for (let i = 0; i < this.bladeTrails.length; i++) {
+ const trail = this.bladeTrails[i];
+
+ const alphaStep = 1 / trail.length;
+ let alpha = 0;
+
+ for (let j = 0; j < trail.length; j++) {
+ const vertices = trail[j];
+ ctx.beginPath();
+ ctx.moveTo(vertices[0].x, vertices[0].y);
+
+ for (let k = 1; k < vertices.length; k++) {
+ ctx.lineTo(vertices[k].x, vertices[k].y);
+ };
+
+ alpha += alphaStep;
+ ctx.closePath();
+ if (tech.isEnergyHealth) {
+ const eyeColor = m.fieldMeterColor;
+ const r = eyeColor[1];
+ const g = eyeColor[2];
+ const b = eyeColor[3];
+ const color = `#${r}${r}${g}${g}${b}${b}${Math.round(alpha * 255).toString(16).padStart(2, '0')}`;
+ ctx.fillStyle = color;
+ } else {
+ ctx.fillStyle = `rgba(220, 20, 60, ${alpha})`;
+ }
+ ctx.fill();
+ }
+ }
+ for (let i = 0; i < this.bladeSegments.length; i++) {
+ ctx.beginPath();
+ ctx.lineJoin = "miter";
+ ctx.miterLimit = 100;
+ ctx.strokeStyle = tech.isEnergyHealth ? m.fieldMeterColor : tech.isAmmoSword ? "#c0c0c0" : "crimson";
+ ctx.lineWidth = 5;
+ ctx.fillStyle = "black";
+ ctx.moveTo(this.bladeSegments[i].vertices[0].x, this.bladeSegments[i].vertices[0].y);
+ for (let j = 0; j < this.bladeSegments[i].vertices.length; j++) {
+ ctx.lineTo(this.bladeSegments[i].vertices[j].x, this.bladeSegments[i].vertices[j].y)
+ };
+ ctx.closePath();
+ ctx.stroke();
+ ctx.fill();
+ ctx.lineJoin = "round";
+ ctx.miterLimit = 10;
+ }
+ }
+ if (this.sword) {
+ for (let i = 0; i < mob.length; i++) {
+ if (Matter.Query.collides(this.sword, [mob[i]]).length > 0) {
+ const dmg = m.dmgScale * 6 * Math.sqrt(this.sword.speed);
+ if (m.health < 0.9) {
+ if (tech.isEnergyHealth) {
+ m.energy += 0.04;
+ } else {
+ m.health += 0.001 * (dmg - mob[i].health);
+ m.displayHealth();
+ }
+ } else {
+ if (tech.isEnergyHealth) {
+ m.energy += 0.04;
+ } else {
+ m.health = m.maxHealth;
+ m.displayHealth();
+ }
+ }
+ mob[i].damage(dmg, true);
+ simulation.drawList.push({
+ x: mob[i].position.x,
+ y: mob[i].position.y,
+ radius: Math.sqrt(dmg / this.sword.speed) * 50,
+ color: simulation.mobDmgColor,
+ time: simulation.drawTime
+ });
+ const angle = Math.atan2(mob[i].position.y - this.sword.position.y, mob[i].position.x - this.sword.position.x);
+ this.sword.force.x -= Math.cos(angle) * 5;
+ this.sword.force.y -= Math.sin(angle) * 5;
+ break
+ }
+ }
+ }
+ },
+ createAndSwingSword(x = player.position.x, y = player.position.y, angle = m.angle) {
+ if (this.cycle < m.cycle) {
+ this.cycle = Infinity;
+ m.fireCDcycle = Infinity;
+ const handleWidth = 20;
+ const handleHeight = 150;
+ const handle = Bodies.rectangle(x, y, handleWidth, handleHeight, spawn.propsIsNotHoldable);
+ bullet[bullet.length] = handle;
+ handle.customName = "handle";
+ bullet[bullet.length - 1].do = () => { };
+ const bladeWidth = 100;
+ const bladeHeight = 20;
+ const numBlades = 15;
+ const extensionFactor = 5;
+ const bladeSegments = [];
+ if ((angle > -Math.PI / 2 && angle < Math.PI / 2)) {
+ for (let i = 0; i < numBlades; i++) {
+ const extensionFactorFraction = (i / (numBlades - 1)) * extensionFactor;
+ const bladeX = x + i * (bladeWidth / 20);
+ const bladeY = y - handleHeight / 2 - i * (bladeHeight / 4.5) * extensionFactor;
+
+ const vertices = [
+ { x: bladeX, y: bladeY - bladeHeight / 2 },
+ { x: bladeX + bladeWidth / 2, y: bladeY + bladeHeight / 2 },
+ { x: bladeX - bladeWidth / 2, y: bladeY + bladeHeight / 2 },
+ { x: bladeX, y: bladeY - bladeHeight / 2 + 10 },
+ ];
+
+ const blade = Bodies.fromVertices(bladeX, bladeY, vertices, spawn.propsIsNotHoldable);
+ bullet[bullet.length] = blade;
+ bullet[bullet.length - 1].do = () => { };
+ Matter.Body.rotate(blade, -Math.sin(i * (Math.PI / 270) * 15));
+ bladeSegments.push(blade);
+ }
+ } else {
+ for (let i = 0; i < numBlades; i++) {
+ const extensionFactorFraction = (i / (numBlades - 1)) * extensionFactor;
+ const mirroredBladeX = x - i * (bladeWidth / 20);
+ const mirroredBladeY = y - handleHeight / 2 - i * (bladeHeight / 4.5) * extensionFactor;
+ const mirroredVertices = [
+ { x: mirroredBladeX, y: mirroredBladeY - bladeHeight / 2 },
+ { x: mirroredBladeX + bladeWidth / 2, y: mirroredBladeY + bladeHeight / 2 },
+ { x: mirroredBladeX - bladeWidth / 2, y: mirroredBladeY + bladeHeight / 2 },
+ { x: mirroredBladeX, y: mirroredBladeY - bladeHeight / 2 + 10 },
+ ];
+ const mirroredBlade = Bodies.fromVertices(mirroredBladeX, mirroredBladeY, mirroredVertices, spawn.propsIsNotHoldable);
+ bullet[bullet.length] = mirroredBlade;
+ bullet[bullet.length - 1].do = () => { };
+ Matter.Body.rotate(mirroredBlade, Math.sin(i * (Math.PI / 270) * 15));
+ bladeSegments.push(mirroredBlade);
+ }
+ }
+ const sword = Body.create({
+ parts: [handle, ...bladeSegments],
+ });
+
+ Composite.add(engine.world, sword);
+ Matter.Body.setPosition(sword, { x, y });
+
+ sword.collisionFilter.category = cat.bullet;
+ sword.collisionFilter.mask = cat.mobBullet | cat.mob;
+ Body.scale(sword, -1, 1, { x, y });
+ // sword.frictionAir -= 0.01;
+
+ return { sword, bladeSegments };
+ }
+ },
+ fire() { }
+ };
+ b.guns.push(e);
+ const gunArray = b.guns.filter(
+ (obj, index, self) =>
+ index === self.findIndex((item) => item.name === obj.name)
+ );
+ b.guns = gunArray;
+ })();
+ }
+ simulation.makeTextLog(`
arena by
Richard0820`);
+ let index = 0;
+ let index2 = 0;
+ let { sword: sword, bladeSegments: bladeSegments } = createSword();
+ const door = level.door(-950, -3000, 400, 4000, 2000, 10);
+ const door2 = level.door(550, -3000, 400, 4000, 2000, 10);
+ level.setPosToSpawn(-7900, -2550); //normal spawn
+ level.exit.x = 7875;
+ level.exit.y = -2530;
+ spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance
+ spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit
+ level.defaultZoom = 8000
+ simulation.zoomTransition(level.defaultZoom)
+ document.body.style.backgroundColor = "#987654";
+ color.map = "#765432" //custom map color
+ color.block = "#876543";
+ door.isClosing = true;
+ door2.isClosing = true;
+ spawnStuff(1000, -3100, 4450, 3125, 50 / simulation.difficultyMode);
+ spawnStuff(5400, -2425, 200, 2250, 5 / simulation.difficultyMode);
+ spawnStuff(5625, -2425, 2000, 275, 5 / simulation.difficultyMode);
+ spawnStuff(5625, -2125, 850, 1125, 5 / simulation.difficultyMode);
+ spawnStuff(6500, -2150, 475, 650, 5 / simulation.difficultyMode);
+ spawnStuff(7000, -2125, 325, 275, 5 / simulation.difficultyMode);
+ spawnStuff(5650, -950, 300, 450, 5 / simulation.difficultyMode);
+ spawn.randomLevelBoss(4225, -575);
+ for (let i = 0; i < 5; i++) {
+ powerUps.spawn(-6075, -2000, "heal");
+ }
+ let bladeTrails = [];
+ let isOwned = false;
+ class Particle {
+ constructor() {
+ this.x = player.position.x + Math.random() * 10000 - 5000;
+ this.y = player.position.y + Math.random() * 10000 - 5000;
+ this.vx = 0;
+ this.vy = 0;
+ this.accelX = 0;
+ this.accelY = 0;
+ this.life = 2000;
+ this.alpha = 1;
+ this.size = 8;
+ }
+
+ update() {
+ this.vx += this.accelX;
+ this.vy += this.accelY;
+ this.x += this.vx;
+ this.y += this.vy;
+
+ if (this.x < player.position.x - 5000 || this.x > player.position.x + 5000 ||
+ this.y < player.position.y - 5000 || this.y > player.position.y + 5000) {
+ this.reset();
+ }
+ }
+
+ reset() {
+ this.x = player.position.x + Math.random() * 10000 - 5000;
+ this.y = player.position.y + Math.random() * 10000 - 5000;
+ this.vx = 0;
+ this.vy = 0;
+ this.life = Math.random() * 1000 + 1000;
+ this.maxLife = this.life;
+ }
+
+ draw(ctx) {
+ ctx.beginPath();
+ ctx.fillStyle = `rgba(255, 255, 255, ${this.alpha})`;
+ ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
+ ctx.fill();
+ ctx.closePath();
+ }
+
+ isAlive() {
+ return this.life >= 0;
+ }
+ }
+ class ParticleSystem {
+ constructor() {
+ this.particles = [];
+ this.updateHandler = undefined;
+ }
+
+ addParticle(particle) {
+ this.particles.push(particle);
+ }
+
+ update(deltaTime = 0) {
+ this.particles.forEach(particle => {
+ particle.update(deltaTime);
+ this.updateHandler && this.updateHandler(particle);
+ });
+ }
+
+ onUpdate(fn) {
+ this.updateHandler = fn;
+ }
+ }
+ let system = new ParticleSystem();
+ for (let i = 0; i < 200; i++) {
+ let particle = new Particle();
+ system.addParticle(particle);
+ }
+ system.onUpdate((particle) => {
+ if (!particle.isAlive()) {
+ particle.reset();
+ }
+
+ particle.life -= 10;
+ particle.accelX = (Math.random() - 0.5) * 0.02;
+ particle.accelY = (Math.random() - 0.5) * 0.02;
+
+ if (particle.life >= particle.maxLife / 2) {
+ particle.alpha = 1 - (particle.life / particle.maxLife);
+ } else {
+ particle.alpha = particle.life / particle.maxLife;
+ }
+
+ particle.update();
+ });
+ function update() {
+ system.update();
+ }
+ function draw() {
+ system.particles.forEach(particle => particle.draw(ctx));
+ }
+ level.custom = () => {
+ update();
+ draw();
+ for (let i = 0, len = b.guns.length; i < len; i++) {
+ if (b.guns[i].name === "sword" && b.guns[i].have) {
+ isOwned = true;
+ }
+ }
+ Matter.Body.setPosition(sword, { x: -3950, y: -275 - (Math.sin(simulation.cycle / 100) * 50) });
+ Matter.Body.setAngularVelocity(sword, 0);
+ door.openClose();
+ door2.openClose();
+ if (Matter.Collision.collides(sword, player) && index <= 0 || isOwned) {
+ bladeTrails = [];
+ bladeSegments = [];
+ Composite.remove(engine.world, sword);
+ sword.parts.forEach(part => {
+ Composite.remove(engine.world, part);
+ const index = bullet.indexOf(part);
+ if (index !== -1) {
+ bullet.splice(index, 1);
+ }
+ });
+ b.giveGuns("sword");
+ door.isClosing = false;
+ door2.isClosing = false;
+ index++;
+ }
+
+ level.exit.drawAndCheck();
+
+ level.enter.draw();
+ if (tech.isEnergyHealth) {
+ ctx.beginPath();
+ const gradient = ctx.createRadialGradient(-3950, 0, 5, -3950, 0, 350 + Math.sin(simulation.cycle * 0.15) * 0.1);
+ gradient.addColorStop(0, m.fieldMeterColor);
+ gradient.addColorStop(0.9, "transparent");
+ // gradient.addColorStop(1, "darkgray");
+ ctx.fillStyle = gradient;
+ ctx.strokeStyle = "transparent";
+ ctx.fillRect(-4000, -350, 100, 350);
+ ctx.fill();
+ ctx.stroke();
+ } else {
+ ctx.beginPath();
+ const gradient = ctx.createLinearGradient(-3500, 0, -3500, -350 + Math.sin(simulation.cycle * 0.15) * 0.1);
+ gradient.addColorStop(0, "crimson");
+ gradient.addColorStop(0.9, "transparent");
+ // gradient.addColorStop(1, "darkgray");
+ ctx.fillStyle = gradient;
+ ctx.strokeStyle = "transparent";
+ ctx.fillRect(-4000, -350, 100, 350);
+ ctx.fill();
+ ctx.stroke();
+ }
+ if (player.position.x > -4000 && player.position.x < -3900 && player.position.y > -350 && player.position.y < 0) {
+ player.force.y -= 0.03;
+ }
+
+ if (player.position.x > level.exit.x && player.position.x < level.exit.x + 100 && player.position.y > level.exit.y - 150 && player.position.y < level.exit.y - 0 && player.velocity.y < .15 && index2 == 0 && !isUsingSwordMod) {
+ b.removeGun("sword"); //completely removing the stuff (if you leave properly through the door)
+ for (let i = 0, len = b.guns.length; i < len; i++) {
+ if (b.guns[i].name === "sword") {
+ b.guns.splice(i, 1);
+ break;
+ }
+ }
+ index2++;
+ simulation.makeTextLog(`If you want to keep this sword, visit
https://github.com/Whyisthisnotavalable/n-scythe. The sword is there.`)
+ }
+ for (let i = 0; i < bladeSegments.length; i++) {
+ const blade = bladeSegments[i];
+ const trail = bladeTrails[i] || [];
+ const vertices = blade.vertices.map(vertex => ({ x: vertex.x, y: vertex.y }));
+ trail.push(vertices);
+ if (trail.length > 10) {
+ trail.shift();
+ }
+ bladeTrails[i] = trail;
+ }
+
+ for (let i = 0; i < bladeTrails.length; i++) {
+ const trail = bladeTrails[i];
+
+ const alphaStep = 1 / trail.length;
+ let alpha = 0;
+
+ for (let j = 0; j < trail.length; j++) {
+ const vertices = trail[j];
+ ctx.beginPath();
+ ctx.moveTo(vertices[0].x, vertices[0].y);
+
+ for (let k = 1; k < vertices.length; k++) {
+ ctx.lineTo(vertices[k].x, vertices[k].y);
+ };
+
+ alpha += alphaStep;
+ ctx.closePath();
+ if (tech.isEnergyHealth) {
+ const eyeColor = m.fieldMeterColor;
+ const r = eyeColor[1];
+ const g = eyeColor[2];
+ const b = eyeColor[3];
+ const color = `#${r}${r}${g}${g}${b}${b}${Math.round(alpha * 255).toString(16).padStart(2, '0')}`;
+ ctx.fillStyle = color;
+ } else {
+ ctx.fillStyle = `rgba(220, 20, 60, ${alpha})`;
+ }
+ ctx.fill();
+ }
+ }
+ for (let i = 0; i < bladeSegments.length; i++) {
+ ctx.beginPath();
+ ctx.lineJoin = "miter";
+ ctx.miterLimit = 100;
+ ctx.strokeStyle = tech.isEnergyHealth ? m.fieldMeterColor : tech.isAmmoSword ? "#c0c0c0" : "crimson";
+ ctx.lineWidth = 5;
+ ctx.fillStyle = "black";
+ ctx.moveTo(bladeSegments[i].vertices[0].x, bladeSegments[i].vertices[0].y);
+ for (let j = 0; j < bladeSegments[i].vertices.length; j++) {
+ ctx.lineTo(bladeSegments[i].vertices[j].x, bladeSegments[i].vertices[j].y)
+ };
+ ctx.closePath();
+ ctx.stroke();
+ ctx.fill();
+ ctx.lineJoin = "round";
+ ctx.miterLimit = 10;
+ }
+ if (bladeSegments.length) {
+ ctx.beginPath();
+ ctx.lineJoin = "miter";
+ ctx.miterLimit = 100;
+ ctx.strokeStyle = tech.isEnergyHealth ? m.fieldMeterColor : tech.isAmmoSword ? "#c0c0c0" : "crimson";
+ ctx.lineWidth = 5;
+ ctx.fillStyle = "black";
+ ctx.moveTo(sword.parts[1].vertices[0].x, sword.parts[1].vertices[0].y);
+ for (let j = 0; j < sword.parts[1].vertices.length; j++) {
+ ctx.lineTo(sword.parts[1].vertices[j].x, sword.parts[1].vertices[j].y)
+ };
+ ctx.closePath();
+ ctx.fill();
+ ctx.lineJoin = "round";
+ ctx.miterLimit = 10;
+ }
+ };
+ level.customTopLayer = () => { };
+
+ spawn.mapRect(-10000, 0, 20000, 2000);
+ spawn.mapRect(-10000, -10000, 2000, 10000);
+ spawn.mapRect(8000, -10000, 2000, 10000);
+ spawn.mapRect(-10000, -10000, 20000, 2000);
+ spawn.spawnStairs(8000, 0, 15, 2500, 2500, true);
+ spawn.spawnStairs(-8000, 0, 15, 2500, 2500, false);
+
+ spawn.mapRect(-4000, -10, 100, 20);
+ spawn.mapRect(4000, -10, 100, 20);
+
+ spawn.mapRect(-1000, -10000, 2000, 8000);
+ spawn.mapRect(-500, -10000, 1000, 9700);
+ function createSword(x = 0, y = 0, angle = 0) { //sword asthetic
+ const handleWidth = 20;
+ const handleHeight = 150;
+ const handle = Bodies.rectangle(x, y, handleWidth, handleHeight, spawn.propsIsNotHoldable);
+ bullet[bullet.length] = handle;
+ handle.customName = "handle";
+ bullet[bullet.length - 1].do = () => { };
+ const bladeWidth = 100;
+ const bladeHeight = 20;
+ const numBlades = 15;
+ const extensionFactor = 5;
+ const bladeSegments = [];
+ if ((angle > -Math.PI / 2 && angle < Math.PI / 2)) {
+ for (let i = 0; i < numBlades; i++) {
+ const extensionFactorFraction = (i / (numBlades - 1)) * extensionFactor;
+ const bladeX = x + i * (bladeWidth / 20);
+ const bladeY = y - handleHeight / 2 - i * (bladeHeight / 4.5) * extensionFactor;
+
+ const vertices = [
+ { x: bladeX, y: bladeY - bladeHeight / 2 },
+ { x: bladeX + bladeWidth / 2, y: bladeY + bladeHeight / 2 },
+ { x: bladeX - bladeWidth / 2, y: bladeY + bladeHeight / 2 },
+ { x: bladeX, y: bladeY - bladeHeight / 2 + 10 },
+ ];
+
+ const blade = Bodies.fromVertices(bladeX, bladeY, vertices, spawn.propsIsNotHoldable);
+ bullet[bullet.length] = blade;
+ bullet[bullet.length - 1].do = () => { };
+ Matter.Body.rotate(blade, -Math.sin(i * (Math.PI / 270) * 15));
+ bladeSegments.push(blade);
+ }
+ } else {
+ for (let i = 0; i < numBlades; i++) {
+ const extensionFactorFraction = (i / (numBlades - 1)) * extensionFactor;
+ const mirroredBladeX = x - i * (bladeWidth / 20);
+ const mirroredBladeY = y - handleHeight / 2 - i * (bladeHeight / 4.5) * extensionFactor;
+ const mirroredVertices = [
+ { x: mirroredBladeX, y: mirroredBladeY - bladeHeight / 2 },
+ { x: mirroredBladeX + bladeWidth / 2, y: mirroredBladeY + bladeHeight / 2 },
+ { x: mirroredBladeX - bladeWidth / 2, y: mirroredBladeY + bladeHeight / 2 },
+ { x: mirroredBladeX, y: mirroredBladeY - bladeHeight / 2 + 10 },
+ ];
+ const mirroredBlade = Bodies.fromVertices(mirroredBladeX, mirroredBladeY, mirroredVertices, spawn.propsIsNotHoldable);
+ bullet[bullet.length] = mirroredBlade;
+ bullet[bullet.length - 1].do = () => { };
+ Matter.Body.rotate(mirroredBlade, Math.sin(i * (Math.PI / 270) * 15));
+ bladeSegments.push(mirroredBlade);
+ }
+ }
+ const sword = Body.create({
+ parts: [handle, ...bladeSegments],
+ });
+
+ Composite.add(engine.world, sword);
+ Matter.Body.setPosition(sword, { x, y });
+
+ sword.collisionFilter.category = cat.bullet;
+ sword.collisionFilter.mask = cat.bullet;
+ Body.scale(sword, -1, 1, { x, y });
+ Body.rotate(sword, Math.PI / 1.05)
+ sword.frictionAir = -0.01;
+
+ return { sword, bladeSegments };
+ }
+ function spawnStuff(x, y, width, height, num) {
+ for (let i = 0; i < num; i++) {
+ randomMob(x + width * Math.random(), y + height * Math.random(), Infinity)
+ }
+ }
+ function randomMob(x, y, chance = 1) {
+ if (spawn.spawnChance(chance) || chance === Infinity) {
+ const pick = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)];
+ spawn[pick](x, y);
+ }
+ if (tech.isDuplicateMobs && Math.random() < tech.duplicationChance()) {
+ const pick = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)];
+ spawn[pick](x, y);
+ }
+ }
+ },
// ********************************************************************************************************
// ********************************************************************************************************
// ***************************************** training levels **********************************************
diff --git a/js/mob.js b/js/mob.js
index 9f5a004..58f7ad5 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -1217,9 +1217,6 @@ const mobs = {
dmg *= this.damageReduction
//energy and heal drain should be calculated after damage boosts
if (tech.energySiphon && dmg !== Infinity && this.isDropPowerUp && m.immuneCycle < m.cycle) m.energy += Math.min(this.health, dmg) * tech.energySiphon
- if (tech.healthDrain && dmg !== Infinity && this.isDropPowerUp && Math.random() < tech.healthDrain * Math.min(this.health, dmg)) {
- powerUps.spawn(m.pos.x + 20 * (Math.random() - 0.5), m.pos.y + 20 * (Math.random() - 0.5), "heal");
- }
dmg /= Math.sqrt(this.mass)
}
@@ -1307,6 +1304,30 @@ const mobs = {
});
}
}
+ if (tech.healSpawn && Math.random() < tech.healSpawn) {
+ powerUps.spawn(this.position.x + 20 * (Math.random() - 0.5), this.position.y + 20 * (Math.random() - 0.5), "heal");
+ simulation.drawList.push({
+ x: this.position.x,
+ y: this.position.y,
+ radius: 50,
+ color: "#0eb",
+ time: 12
+ });
+ simulation.drawList.push({
+ x: this.position.x,
+ y: this.position.y,
+ radius: 100,
+ color: "#0eb",
+ time: 6
+ });
+ simulation.drawList.push({
+ x: this.position.x,
+ y: this.position.y,
+ radius: 200,
+ color: "#0eb",
+ time: 3
+ });
+ }
if (tech.deathSkipTime && !m.isBodiesAsleep) {
requestAnimationFrame(() => {
diff --git a/js/player.js b/js/player.js
index 8b8673f..d9e7a83 100644
--- a/js/player.js
+++ b/js/player.js
@@ -563,7 +563,6 @@ const m = {
if (tech.isHarmMACHO) dmg *= 0.4
if (tech.isImmortal) dmg *= 0.7
if (tech.energyRegen === 0) dmg *= 0.34
- // if (tech.healthDrain) dmg *= 1 + 3.33 * tech.healthDrain //tech.healthDrain = 0.03 at one stack //cause more damage
if (m.fieldMode === 0 || m.fieldMode === 3) dmg *= 0.973 ** m.coupling
if (tech.isLowHealthDefense) dmg *= 1 - Math.max(0, 1 - m.health) * 0.8
if (tech.isHarmReduceNoKill && m.lastKillCycle + 300 < m.cycle) dmg *= 0.26
@@ -577,11 +576,7 @@ const m = {
if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.27
if (tech.isTurret && m.crouch) dmg *= 0.34;
if (tech.isFirstDer && b.inventory[0] === b.activeGun) dmg *= 0.85 ** b.inventory.length
- if (tech.isEnergyHealth) {
- return Math.pow(dmg, 0.33) //defense has less effect
- } else {
- return dmg
- }
+ return tech.isEnergyHealth ? Math.pow(dmg, 0.5) : dmg //defense has less effect
},
rewind(steps) { // m.rewind(Math.floor(Math.min(599, 137 * m.energy)))
if (tech.isRewindGrenade) {
@@ -1071,6 +1066,111 @@ const m = {
ctx.restore();
}
},
+ polar() {
+ m.isAltSkin = true
+ m.color = {
+ hue: 0,
+ sat: 0,
+ light: 100,
+ }
+ // m.setFillColors();
+ m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)`
+ m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 35}%)`
+ let grd = ctx.createLinearGradient(-30, 0, 30, 0);
+ grd.addColorStop(0, m.fillColorDark);
+ grd.addColorStop(0.7, m.fillColor);
+ // grd.addColorStop(1, m.fillColor);
+ m.bodyGradient = grd
+
+ m.draw = function () {
+ ctx.fillStyle = m.fillColor;
+ m.walk_cycle += m.flipLegs * m.Vx;
+ ctx.save();
+ ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
+ ctx.translate(m.pos.x, m.pos.y);
+ m.calcLeg(Math.PI, -3);
+
+
+ const diff = (m.lastKillCycle - m.cycle + 240) / 240
+ const color = diff < 0 ? "#fff" : "#aaa"
+ const hue = 220 + 20 * Math.sin(0.01 * m.cycle)
+ const colorInverse = diff < 0 ? `hsl(${hue}, 80%, 40%)` : "#fff"
+ // const colorInverseFade = diff < 0 ? "#ccc" : "#fff"
+ m.drawLeg(color, colorInverse);
+ m.calcLeg(0, 0);
+ m.drawLeg(color, colorInverse);
+
+ ctx.rotate(m.angle);
+ ctx.beginPath();
+ ctx.arc(0, 0, 30, 0, 2 * Math.PI);
+ ctx.fillStyle = color
+ ctx.fill();
+
+ ctx.beginPath();
+ ctx.moveTo(15, 0)
+ ctx.lineTo(28, 0)
+ // ctx.arc(15, 0, 4, 0, 2 * Math.PI);
+ ctx.strokeStyle = colorInverse;
+ ctx.lineWidth = 4;
+ ctx.stroke();
+ ctx.restore();
+
+
+ // const scale = diff>0.3
+ // console.log(diff.toFixed(3), scale.toFixed(3))
+ ctx.beginPath();
+ ctx.ellipse(m.pos.x, m.pos.y, 24, 18, 3.14 * Math.random(), 0, 2 * Math.PI)
+ // `rgba(0,0,${100 + 30 * Math.sin(0.1 * m.cycle)},0.8)`
+ ctx.fillStyle = diff < 0 ? `hsl(${hue}, 80%, 40%)` : `rgba(255,255,255,${Math.min(Math.max(0, diff + 0.3), 1)})`
+ // ctx.fillStyle = colorInverse
+ // ctx.fillStyle = `rgba(0,0,0,${scale})`
+ ctx.fill();
+
+ m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
+ powerUps.boost.draw()
+ }
+ m.drawLeg = function (stroke, circles) {
+ // if (simulation.mouseInGame.x > m.pos.x) {
+ if (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2) {
+ m.flipLegs = 1;
+ } else {
+ m.flipLegs = -1;
+ }
+ ctx.save();
+ ctx.scale(m.flipLegs, 1); //leg lines
+ ctx.beginPath();
+ ctx.moveTo(m.hip.x, m.hip.y);
+ ctx.lineTo(m.knee.x, m.knee.y);
+ ctx.lineTo(m.foot.x, m.foot.y);
+ ctx.strokeStyle = stroke;
+ ctx.lineWidth = 6;
+ ctx.stroke();
+
+ //toe lines
+ ctx.beginPath();
+ ctx.moveTo(m.foot.x, m.foot.y);
+ ctx.lineTo(m.foot.x - 15, m.foot.y + 5);
+ ctx.moveTo(m.foot.x, m.foot.y);
+ ctx.lineTo(m.foot.x + 15, m.foot.y + 5);
+ ctx.lineWidth = 3;
+ ctx.stroke();
+
+ //hip joint
+ ctx.beginPath();
+ ctx.arc(m.hip.x, m.hip.y, 11, 0, 2 * Math.PI);
+ //knee joint
+ ctx.moveTo(m.knee.x + 5, m.knee.y);
+ ctx.arc(m.knee.x, m.knee.y, 5, 0, 2 * Math.PI);
+ //foot joint
+ ctx.moveTo(m.foot.x + 5, m.foot.y);
+ ctx.arc(m.foot.x, m.foot.y, 5, 0, 2 * Math.PI);
+ ctx.fillStyle = circles;
+ ctx.fill();
+ // ctx.lineWidth = 2;
+ // ctx.stroke();
+ ctx.restore();
+ }
+ },
strokeGap() {
m.isAltSkin = true
m.yOffWhen.stand = 52
@@ -1579,9 +1679,9 @@ const m = {
// m.setFillColors();
m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)`
m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 35}%)`
- let grd = ctx.createLinearGradient(-30, 0, 30, 0);
+ let grd = ctx.createLinearGradient(-20, 0, 15, 0);
grd.addColorStop(0, m.fillColorDark);
- grd.addColorStop(0.7, m.fillColor);
+ grd.addColorStop(1, m.fillColor);
// grd.addColorStop(1, m.fillColor);
m.bodyGradient = grd
@@ -1595,10 +1695,11 @@ const m = {
m.drawLeg("#eee");
m.calcLeg(0, 0);
m.drawLeg("#fff");
- ctx.rotate(0.017 * simulation.cycle);
+
+ ctx.rotate(0.024 * simulation.cycle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
- ctx.fillStyle = m.bodyGradient
+ ctx.fillStyle = m.energy > 0.85 * Math.min(1, m.maxEnergy) ? m.bodyGradient : "#fff"
ctx.fill();
ctx.restore();
@@ -3654,74 +3755,75 @@ const m = {
m.drawHold(m.holdingTarget);
m.holding();
m.throwBlock();
- } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
+ } else if (input.field) { //not hold but field button is pressed
if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen
m.grabPowerUp();
m.lookForPickUp();
+ if (m.fieldCDcycle < m.cycle) {
+ //field is active
+ if (!m.plasmaBall.isAttached) { //return ball to player
+ if (m.plasmaBall.isOn) {
+ m.plasmaBall.isPopping = true
+ } else {
+ m.plasmaBall.isAttached = true
+ m.plasmaBall.isOn = true
+ m.plasmaBall.isPopping = false
+ m.plasmaBall.alpha = 0.7
+ m.plasmaBall.setPositionToNose()
+ // m.plasmaBall.reset()
- //field is active
- if (!m.plasmaBall.isAttached) { //return ball to player
- if (m.plasmaBall.isOn) {
- m.plasmaBall.isPopping = true
- } else {
- m.plasmaBall.isAttached = true
- m.plasmaBall.isOn = true
- m.plasmaBall.isPopping = false
- m.plasmaBall.alpha = 0.7
+ }
+ // 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
+ if (tech.isCapacitor) {
+ m.energy -= m.plasmaBall.drain * 2;
+ const scale = 1 + 48 * Math.pow(Math.max(1, m.plasmaBall.circleRadius), -1.8)
+ Matter.Body.scale(m.plasmaBall, scale, scale); //grow
+ } else {
+ m.energy -= m.plasmaBall.drain;
+ const scale = 1 + 16 * Math.pow(Math.max(1, m.plasmaBall.circleRadius), -1.8)
+ Matter.Body.scale(m.plasmaBall, scale, scale); //grow
+ }
+ if (m.energy > m.maxEnergy) {
+ m.energy -= m.plasmaBall.drain * 2;
+ const scale = 1 + 16 * Math.pow(Math.max(1, m.plasmaBall.circleRadius), -1.8)
+ Matter.Body.scale(m.plasmaBall, scale, scale); //grow
+ }
m.plasmaBall.setPositionToNose()
- // m.plasmaBall.reset()
- }
- // 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
- if (tech.isCapacitor) {
- m.energy -= m.plasmaBall.drain * 2;
- const scale = 1 + 48 * Math.pow(Math.max(1, m.plasmaBall.circleRadius), -1.8)
- Matter.Body.scale(m.plasmaBall, scale, scale); //grow
+ //add friction for player when holding ball, more friction in vertical
+ // const floatScale = Math.sqrt(m.plasmaBall.circleRadius)
+ // const friction = 0.0002 * floatScale
+ // const slowY = (player.velocity.y > 0) ? Math.max(0.8, 1 - friction * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - friction * Math.abs(player.velocity.y)) //down : up
+ // Matter.Body.setVelocity(player, {
+ // x: Math.max(0.95, 1 - friction * Math.abs(player.velocity.x)) * player.velocity.x,
+ // y: slowY * player.velocity.y
+ // });
+
+ // if (player.velocity.y > 7) player.force.y -= 0.95 * player.mass * simulation.g //less gravity when falling fast
+ // player.force.y -= Math.min(0.95, 0.05 * floatScale) * player.mass * simulation.g; //undo some gravity on up or down
+
+ //float
+ const slowY = (player.velocity.y > 0) ? Math.max(0.8, 1 - 0.002 * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - 0.001 * Math.abs(player.velocity.y)) //down : up
+ Matter.Body.setVelocity(player, {
+ x: Math.max(0.95, 1 - 0.003 * Math.abs(player.velocity.x)) * player.velocity.x,
+ y: slowY * player.velocity.y
+ });
+ if (player.velocity.y > 5) {
+ player.force.y -= 0.9 * player.mass * simulation.g //less gravity when falling fast
+ } else {
+ player.force.y -= 0.5 * player.mass * simulation.g;
+ }
} else {
- m.energy -= m.plasmaBall.drain;
- const scale = 1 + 16 * Math.pow(Math.max(1, m.plasmaBall.circleRadius), -1.8)
- Matter.Body.scale(m.plasmaBall, scale, scale); //grow
+ m.fieldCDcycle = m.cycle + 90;
+ m.plasmaBall.fire()
}
- if (m.energy > m.maxEnergy) {
- m.energy -= m.plasmaBall.drain * 2;
- const scale = 1 + 16 * Math.pow(Math.max(1, m.plasmaBall.circleRadius), -1.8)
- Matter.Body.scale(m.plasmaBall, scale, scale); //grow
- }
- m.plasmaBall.setPositionToNose()
-
- //add friction for player when holding ball, more friction in vertical
- // const floatScale = Math.sqrt(m.plasmaBall.circleRadius)
- // const friction = 0.0002 * floatScale
- // const slowY = (player.velocity.y > 0) ? Math.max(0.8, 1 - friction * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - friction * Math.abs(player.velocity.y)) //down : up
- // Matter.Body.setVelocity(player, {
- // x: Math.max(0.95, 1 - friction * Math.abs(player.velocity.x)) * player.velocity.x,
- // y: slowY * player.velocity.y
- // });
-
- // if (player.velocity.y > 7) player.force.y -= 0.95 * player.mass * simulation.g //less gravity when falling fast
- // player.force.y -= Math.min(0.95, 0.05 * floatScale) * player.mass * simulation.g; //undo some gravity on up or down
-
- //float
- const slowY = (player.velocity.y > 0) ? Math.max(0.8, 1 - 0.002 * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - 0.001 * Math.abs(player.velocity.y)) //down : up
- Matter.Body.setVelocity(player, {
- x: Math.max(0.95, 1 - 0.003 * Math.abs(player.velocity.x)) * player.velocity.x,
- y: slowY * player.velocity.y
- });
- if (player.velocity.y > 5) {
- player.force.y -= 0.9 * player.mass * simulation.g //less gravity when falling fast
- } else {
- player.force.y -= 0.5 * player.mass * simulation.g;
- }
- } 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();
@@ -4204,6 +4306,7 @@ const m = {
}
}
}
+
if (m.isCloak) {
m.fieldRange = m.fieldRange * 0.85 + 130
m.fieldDrawRadius = m.fieldRange * 1.1 //* 0.88 //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy));
diff --git a/js/powerup.js b/js/powerup.js
index 649659d..5292b4d 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -687,7 +687,7 @@ const powerUps = {
return `
`
} else if (tech.isCancelTech) {
return `
randomize
`
- } else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted) { //don't show cancel if on initial level and haven't done tutorial
+ } 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 `
`
} else {
return `
cancel
`
@@ -745,7 +745,7 @@ const powerUps = {
text += `
cancel`
} else if (tech.isCancelTech) {
text += `
randomize`
- } else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted) {
+ } else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted && b.inventory.length === 0) {
text += `
cancel` //don't show cancel if on initial level and haven't done tutorial
} else {
text += `
cancel`
@@ -1539,7 +1539,7 @@ const powerUps = {
tech.removeTech(index)
} else {
powerUps.ejectTech(index)
- m.damage(0.06)
+ m.damage(0.04)
}
document.getElementById(`${index}-pause-tech`).style.textDecoration = "line-through"
document.getElementById(`${index}-pause-tech`).style.animation = ""
diff --git a/js/tech.js b/js/tech.js
index 12db9e6..4a66256 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -231,6 +231,8 @@ const tech = {
// }
// }
// }
+ if (tech.isDamageCooldown) dmg *= m.lastKillCycle + 240 > m.cycle ? 0.5 : 4
+ if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 1.93
if (tech.isDivisor && b.activeGun !== undefined && b.activeGun !== null && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.77
if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.85 : 2
if (tech.isDilate) dmg *= 1.5 + 0.6 * Math.sin(m.cycle * 0.0075)
@@ -254,7 +256,6 @@ const tech = {
if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.007
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2.11
if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.88, player.speed * 0.0193)
- if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 1.93
if (tech.isAxion && tech.isHarmMACHO) dmg *= 2 - m.defense()
if (tech.isHarmDamage && m.lastHarmCycle + 480 > m.cycle) dmg *= 3;
if (tech.lastHitDamage && m.lastHit) dmg *= 1 + tech.lastHitDamage * m.lastHit * (2 - m.defense()) // if (!simulation.paused) m.lastHit = 0
@@ -365,6 +366,30 @@ const tech = {
if (this.count) m.resetSkin();
}
},
+ {
+ name: "depolarization",
+ descriptionFunction() {
+ // return `
+300% damage or
-50% damageif a mob has
died in the last
5 seconds`
+ return `
+300% damage if no mobs died in the last 4 seconds
-50% damage if a mob died in the last 4 seconds`
+ },
+ maxCount: 1,
+ count: 0,
+ frequency: 1,
+ frequencyDefault: 1,
+ isSkin: true,
+ allowed() {
+ return !m.isAltSkin
+ },
+ requires: "not skinned",
+ effect() {
+ m.skin.polar();
+ tech.isDamageCooldown = true;
+ },
+ remove() {
+ tech.isDamageCooldown = false;
+ if (this.count) m.resetSkin();
+ }
+ },
{
name: "Higgs mechanism",
description: "
+77% fire ratewhile
firing your
position is fixed",
@@ -462,7 +487,7 @@ const tech = {
{
name: "mass-energy equivalence",
// description: "
energy protects you instead of
health√ of
defense reduction reduces max
energy",
- description: `
energy protects you instead of
healthdefensive upgrades
reduced by
~66%`,
+ description: `
energy protects you instead of
healthdefensive upgrades
reduced by about
50%`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -535,7 +560,7 @@ const tech = {
// description: "
charge,
parity, and
time invert to undo
defenserewind (1.5—5) seconds for
(66—220) energy",
// description: "after losing
health, if you have
full energyrewind time for
44 energy per second",
descriptionFunction() {
- return `after losing
health, if you have
${(100 * Math.min(100, m.maxEnergy)).toFixed(0)} energyrewind time for
20 energy per second`
+ return `after losing
health, if you have above
${(85 * Math.min(100, m.maxEnergy)).toFixed(0)} energyrewind time for
20 energy per second`
},
maxCount: 1,
count: 0,
@@ -1346,6 +1371,27 @@ const tech = {
tech.isShieldAmmo = false;
}
},
+ {
+ name: "enthalpy",
+ descriptionFunction() {
+ return `after mobs
diethey have a
+8% chance to spawn ${powerUps.orb.heal(1)}`
+ },
+ maxCount: 9,
+ count: 0,
+ frequency: 1000,
+ frequencyDefault: 1000,
+ isHealTech: true,
+ allowed() {
+ return true
+ },
+ requires: "",
+ effect() {
+ tech.healSpawn += 0.08;
+ },
+ remove() {
+ tech.healSpawn = 0;
+ }
+ },
{
name: "yield stress",
description: "
+55% damageto
mobs at maximum
health",
@@ -3233,27 +3279,6 @@ const tech = {
tech.isHealLowHealth = false;
}
},
- {
- name: "enthalpy",
- descriptionFunction() {
- return `doing
damage has a small chance to spawn ${powerUps.orb.heal(1)}` //
–10% defense
- },
- maxCount: 9,
- count: 0,
- frequency: 1,
- frequencyDefault: 1,
- isHealTech: true,
- allowed() {
- return true
- },
- requires: "",
- effect() {
- tech.healthDrain += 0.023;
- },
- remove() {
- tech.healthDrain = 0;
- }
- },
{
name: "maintenance",
descriptionFunction() {
@@ -3532,9 +3557,9 @@ const tech = {
{
name: "mass production",
descriptionFunction() {
- return `
tech always have
+3 choices to spawn
options for ${powerUps.orb.ammo(1)} or ${powerUps.orb.heal(1)} or ${powerUps.orb.research(1)}`
+ return `spawn ${powerUps.orb.ammo(3)}${powerUps.orb.heal(3)} ${powerUps.orb.research(2)}
tech have extra choices to spawn ${powerUps.orb.ammo(1)}, ${powerUps.orb.heal(1)}, or ${powerUps.orb.research(1)}`
},
- // description: `
tech always have
+3 choices to spawn
${powerUps.orb.ammo(8)} ${powerUps.orb.heal(8)} or ${powerUps.orb.research(5)}`,
+ // description: `< strong class='color-m' > tech always have < strong > +3 choices to spawn < br > ${ powerUps.orb.ammo(8) } ${ powerUps.orb.heal(8) } & nbsp;& nbsp; or ${ powerUps.orb.research(5) } `,
maxCount: 1,
count: 0,
frequency: 1,
@@ -3543,6 +3568,9 @@ const tech = {
requires: "",
effect() {
tech.isMassProduction = true
+ powerUps.spawnDelay("ammo", 4);
+ powerUps.spawnDelay("heal", 4);
+ powerUps.spawnDelay("research", 2);
},
remove() {
tech.isMassProduction = false
@@ -3551,7 +3579,7 @@ const tech = {
{
name: "research",
descriptionFunction() {
- return `spawn ${this.value > 36 ? this.value + powerUps.orb.research(1) : powerUps.orb.research(this.value)}
next time this effect is improved by ${powerUps.orb.research(5)}`
+ return `spawn ${this.value > 36 ? this.value + powerUps.orb.research(1) : powerUps.orb.research(this.value)}
next time this effect is improved by ${powerUps.orb.research(5)}`
},
maxCount: 9,
count: 0,
@@ -3610,7 +3638,7 @@ const tech = {
},
{
name: "pseudoscience",
- description: "
when selecting a power up, research 3 timesfor
free, but add
1-3% JUNK to the
tech pool",
+ description: "
when selecting a power up, research 3 timesfor
free, but add
1-3% JUNK to the
tech pool",
maxCount: 1,
count: 0,
frequency: 1,
@@ -3940,7 +3968,7 @@ const tech = {
// description: `when
paused clicking a
tech ejects it
with a
20% chance to remove without
ejecting`,
// description: `when
paused clicking a
tech ejects it
and a
20% chance to remove without
ejecting`,
descriptionFunction() {
- return `when
paused clicking a
tech ejects it
–6 ${tech.isEnergyHealth ? "
energy" : "
health"} each time and a
3% chance to fail`
+ return `when
paused clicking a
tech ejects it
–4 ${tech.isEnergyHealth ? "
energy" : "
health"} each time and a
3% chance to fail`
},
maxCount: 1,
count: 0,
@@ -5246,7 +5274,7 @@ const tech = {
},
{
name: "Zectron",
- description: `
+75% super ball density and
damage, but
after colliding with
super balls -25% energy`,
+ description: `
+90% super ball density and
damage, but
after colliding with
super balls -25% energy`,
isGunTech: true,
maxCount: 1,
count: 0,
@@ -11756,7 +11784,7 @@ const tech = {
fireRate: null,
bulletSize: null,
energySiphon: null,
- healthDrain: null,
+ healSpawn: null,
crouchAmmoCount: null,
bulletsLastLonger: null,
isImmortal: null,
@@ -12107,5 +12135,6 @@ const tech = {
isHarpoonFullHealth: null,
isMobFullHealth: null,
isMobFullHealthCloak: null,
- isMobLowHealth: null
+ isMobLowHealth: null,
+ isDamageCooldown: null,
}
\ No newline at end of file
diff --git a/style.css b/style.css
index f71c38e..b254cf7 100644
--- a/style.css
+++ b/style.css
@@ -1394,19 +1394,19 @@ summary {
} */
.blurry-text {
color: transparent;
- text-shadow: 0 0 9px rgba(0, 0, 0, 0.5);
+ text-shadow: 0 0 10px rgba(0, 0, 0, 0.6);
}
.unblur {
color: transparent;
- text-shadow: 0 0 9px rgba(0, 0, 0, 0.5);
- animation: 1.5s ease 1.2s normal forwards 1 unblur;
+ text-shadow: 0 0 7px rgba(0, 0, 0, 0.5);
+ animation: 2.5s ease 0.5s normal forwards 1 unblur;
}
@keyframes unblur {
0% {
color: transparent;
- text-shadow: 0 0 9px rgba(0, 0, 0, 0.5);
+ text-shadow: 0 0 7px rgba(0, 0, 0, 0.5);
}
100% {
diff --git a/todo.txt b/todo.txt
index 2b2dfdc..b90510e 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,18 +1,41 @@
******************************************************** NEXT PATCH **************************************************
-after beating the final boss the difficulty settings automatically opens
-quenching - double the damage and double the max health given
- aligned the effects more consistently with defense and difficulty based heal reduction
- prevented possible death by quenching
+community map - arena by Richard0820
+
+skin tech: depolarization - gain +300 damage or -50% damage if a mobs has died in last 5 seconds
+CPT triggers if you have above 90->85 energy
+ CPT skin graphically indicates when CPT is active
+mass-energy defense reduction is 66->50%
-fixed super balls bug
+new level load display animation draws the outline of the new map
+ only on reactor and final levels
+ choose MINIMAL HUD in settings to disable (or enter testing mode)
+enthalpy spawns heals on mobs death with a 5% chance
+ this is roughly an 80% increase in spawn rate
+mass production spawns a few ammo and heals when you first get it
+paradigm shift 6->4 health removed
+incendiary ammunition drone and shotgun explosions are 30% bigger
+Zectron super balls do 75->90% more damage and drain 25->20 energy on hitting player
+
+fixed bug with optical amplifier and cloaking field
+plasma ball can pick up power ups when out of energy, like other fields
+fixed bug with not hiding mouse
*********************************************************** TODO *****************************************************
+final and reactor menu is still kinda annoying
+ maybe tweak the style and duration
+
improve new player experience
training is too long to be a tutorial
before nail gun level offer player option to continue or switch to normal game
++40% foam size
++40% foam damage
+-40% foam ammo gain
+When foam is in an explosion it also explodes with size proportional to the size of the foam bubble
+Requires foam, explosion source, not aerogel
+
Cosmological natural selection: do something with black holes
spawn black hole mobs
after bosses die?
@@ -34,6 +57,9 @@ Foam slow down mobs twice as much and slowly pulls them towards the ground
Requires a source of foam and not aerogel
https://en.m.wikipedia.org/wiki/Tungsten_hexafluoride
+if needles touch map and mob at the same time pin mob to map
+ this might be better as a railgun tech, or a railgun rework
+ name rebar
make grappling hook of different shapes
shapes
@@ -55,6 +81,9 @@ on sucker mob death trigger radiation damage AoE and a graphic (Hawking radiati
tech prismatic laser - cycles between different laser colors every 1-2 seconds
+
+When you destroy an enemy’s shield it causes a large explosion. Requires not bubble fusion
+
sword slash for plasma torch (giving up on this for now, had trouble making graphics look good)
activates when mouse is close to player
gradual activation
@@ -65,6 +94,8 @@ sword slash for plasma torch (giving up on this for now, had trouble making gr
give them their own version of a slash?
make a tech that buffs the slash, but it disables extruder,plasma ball
+
+
more (all) bosses need to be made of parts
good examples: spiderBoss, dragonFlyBoss, beetleBoss
methods: