diff --git a/.DS_Store b/.DS_Store
index 0940df6..0509efd 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/js/bullet.js b/js/bullet.js
index bb7324f..486255c 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -2906,7 +2906,7 @@ const b = {
// }
},
onEnd() {
- if (tech.isDroneRespawn) {
+ if (tech.isDroneRespawn && b.inventory.length) {
const who = b.guns[b.activeGun]
if (who.name === "drones" && who.ammo > 0 && mob.length) {
b.droneRadioactive({ x: this.position.x, y: this.position.y }, 0)
@@ -3320,55 +3320,57 @@ const b = {
// bullet[me].turnRate = 0.005 * (Math.random() - 0.5)
bullet[me].isInMap = false
bullet[me].do = function() {
- const whom = Matter.Query.collides(this, mob)
- if (whom.length && this.speed > 20) { //if touching a mob
- for (let i = 0, len = whom.length; i < len; i++) {
- who = whom[i].bodyA
- if (who && who.mob) {
- let immune = false
- for (let i = 0; i < this.immuneList.length; i++) { //check if this needle has hit this mob already
- if (this.immuneList[i] === who.id) {
- immune = true
- break
+ if (!m.isBodiesAsleep) {
+ const whom = Matter.Query.collides(this, mob)
+ if (whom.length && this.speed > 20) { //if touching a mob
+ for (let i = 0, len = whom.length; i < len; i++) {
+ who = whom[i].bodyA
+ if (who && who.mob) {
+ let immune = false
+ for (let i = 0; i < this.immuneList.length; i++) { //check if this needle has hit this mob already
+ if (this.immuneList[i] === who.id) {
+ immune = true
+ break
+ }
}
- }
- if (!immune) {
- if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.94) {
- b.explosion(this.position, 220 * tech.nailSize + 50 * Math.random()); //makes bullet do explosive damage at end
- }
- this.immuneList.push(who.id) //remember that this needle has hit this mob once already
- let dmg = this.dmg * tech.nailSize * b.dmgScale
- if (tech.isNailRadiation) {
- mobs.statusDoT(who, (tech.isFastRadiation ? 6 : 2) * tech.nailSize, tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles
- dmg *= 0.25
- }
- if (tech.isCrit && who.isStunned) dmg *= 4
- who.damage(dmg, tech.isShieldPierce);
- if (who.alive) who.foundPlayer();
- if (who.damageReduction) {
- simulation.drawList.push({ //add dmg to draw queue
- x: this.position.x,
- y: this.position.y,
- radius: Math.log(dmg + 1.1) * 40 * who.damageReduction + 3,
- color: simulation.playerDmgColor,
- time: simulation.drawTime
- });
+ if (!immune) {
+ if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.94) {
+ b.explosion(this.position, 220 * tech.nailSize + 50 * Math.random()); //makes bullet do explosive damage at end
+ }
+ this.immuneList.push(who.id) //remember that this needle has hit this mob once already
+ let dmg = this.dmg * tech.nailSize * b.dmgScale
+ if (tech.isNailRadiation) {
+ mobs.statusDoT(who, (tech.isFastRadiation ? 6 : 2) * tech.nailSize, tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles
+ dmg *= 0.25
+ }
+ if (tech.isCrit && who.isStunned) dmg *= 4
+ who.damage(dmg, tech.isShieldPierce);
+ if (who.alive) who.foundPlayer();
+ if (who.damageReduction) {
+ simulation.drawList.push({ //add dmg to draw queue
+ x: this.position.x,
+ y: this.position.y,
+ radius: Math.log(dmg + 1.1) * 40 * who.damageReduction + 3,
+ color: simulation.playerDmgColor,
+ time: simulation.drawTime
+ });
+ }
}
}
}
+ } else if (Matter.Query.collides(this, map).length) { //penetrate walls
+ if (!this.isInMap) { //turn after entering the map, but only turn once
+ this.isInMap = true
+ Matter.Body.setVelocity(this, Vector.rotate(this.velocity, 0.25 * (Math.random() - 0.5)));
+ Matter.Body.setAngle(this, Math.atan2(this.velocity.y, this.velocity.x))
+ }
+ Matter.Body.setPosition(this, Vector.add(this.position, Vector.mult(this.velocity, -0.98))) //move back 1/2 your velocity = moving at 1/2 speed
+ } else if (Matter.Query.collides(this, body).length) { //penetrate blocks
+ Matter.Body.setAngularVelocity(this, 0)
+ Matter.Body.setPosition(this, Vector.add(this.position, Vector.mult(this.velocity, -0.94))) //move back 1/2 your velocity = moving at 1/2 speed
+ } else if (this.speed < 30) {
+ this.force.y += this.mass * 0.001; //no gravity until it slows down to improve aiming
}
- } else if (Matter.Query.collides(this, map).length) { //penetrate walls
- if (!this.isInMap) { //turn after entering the map, but only turn once
- this.isInMap = true
- Matter.Body.setVelocity(this, Vector.rotate(this.velocity, 0.25 * (Math.random() - 0.5)));
- Matter.Body.setAngle(this, Math.atan2(this.velocity.y, this.velocity.x))
- }
- Matter.Body.setPosition(this, Vector.add(this.position, Vector.mult(this.velocity, -0.98))) //move back 1/2 your velocity = moving at 1/2 speed
- } else if (Matter.Query.collides(this, body).length) { //penetrate blocks
- Matter.Body.setAngularVelocity(this, 0)
- Matter.Body.setPosition(this, Vector.add(this.position, Vector.mult(this.velocity, -0.94))) //move back 1/2 your velocity = moving at 1/2 speed
- } else if (this.speed < 30) {
- this.force.y += this.mass * 0.001; //no gravity until it slows down to improve aiming
}
};
} else {
@@ -3541,7 +3543,25 @@ const b = {
}
},
randomBot(where = player.position, isKeep = true, isLaser = true) {
- if (Math.random() < 0.166 && isLaser) {
+ if (tech.isNailBotUpgrade) { //check for upgrades first
+ b.nailBot(where, isKeep)
+ if (isKeep) tech.nailBotCount++;
+ } else if (tech.isFoamBotUpgrade) {
+ b.foamBot(where, isKeep)
+ if (isKeep) tech.foamBotCount++;
+ } else if (tech.isBoomBotUpgrade) {
+ b.boomBot(where, isKeep)
+ if (isKeep) tech.boomBotCount++;
+ } else if (tech.isLaserBotUpgrade) {
+ b.laserBot(where, isKeep)
+ if (isKeep) tech.laserBotCount++;
+ } else if (tech.isOrbitBotUpgrade) {
+ b.orbitBot(where, isKeep);
+ if (isKeep) tech.orbitBotCount++;
+ } else if (tech.isDynamoBotUpgrade) {
+ b.dynamoBot(where, isKeep)
+ if (isKeep) tech.dynamoBotCount++;
+ } else if (Math.random() < 0.166 && isLaser) { //random
b.laserBot(where, isKeep)
if (isKeep) tech.laserBotCount++;
} else if (Math.random() < 0.2) {
diff --git a/js/level.js b/js/level.js
index 4ff657e..6aca0a9 100644
--- a/js/level.js
+++ b/js/level.js
@@ -17,10 +17,10 @@ const level = {
// localSettings.levelsClearedLastGame = 10
// level.difficultyIncrease(1) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true
- // m.setField("wormhole")
- // b.giveGuns("laser")
+ // m.setField("metamaterial cloaking")
+ // b.giveGuns("harpoon")
// for (let i = 0; i < 9; i++) tech.giveTech("slow light")
- // tech.giveTech("invariant")
+ // tech.giveTech("boson composite")
// for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech");
// tech.giveTech("charmed baryons")
// tech.giveTech("tinsellated flagella")
@@ -41,7 +41,7 @@ const level = {
// for (let i = 0; i < 3; i++) tech.giveTech("undefined")
// lore.techCount = 3
// simulation.isCheating = false //true;
- // localSettings.loreCount = 1; //this sets what conversation is heard
+ // localSettings.loreCount = 0; //this sets what conversation is heard
// 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()
@@ -137,7 +137,7 @@ const level = {
if (simulation.accelScale < 6) simulation.accelScale *= 1.025 //mob acceleration increases each level
if (simulation.CDScale > 0.15) simulation.CDScale *= 0.965 //mob CD time decreases each level
}
- simulation.dmgScale = 0.41 * simulation.difficulty //damage done by mobs increases each level
+ simulation.dmgScale = 0.4 * simulation.difficulty //damage done by mobs increases each level
simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale;
// console.log(`CD = ${simulation.CDScale}`)
},
@@ -149,7 +149,7 @@ 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 = 0.41 * simulation.difficulty //damage done by mobs increases each level
+ simulation.dmgScale = 0.4 * simulation.difficulty //damage done by mobs increases each level
if (simulation.dmgScale < 0.1) simulation.dmgScale = 0.1;
simulation.healScale = 1 / (1 + simulation.difficulty * 0.055)
},
@@ -241,7 +241,6 @@ const level = {
level.levels.push("gauntlet"); //add level to the end of the randomized levels list
level.levels.push("final"); //add level to the end of the randomized levels list
}
- console.log(level.levels)
}
},
flipHorizontal() {
@@ -341,9 +340,10 @@ const level = {
y += height / 2
const who = body[body.length] = Bodies.rectangle(x, y, width, height, {
collisionFilter: {
- category: cat.body,
- mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
+ category: cat.map,
+ mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
},
+ isNoSetCollision: true,
isNotHoldable: true,
frictionAir: frictionAir,
friction: 1,
@@ -435,9 +435,10 @@ const level = {
force += simulation.g
const who = body[body.length] = Bodies.rectangle(x, isAtTop ? maxHeight : y, width, height, {
collisionFilter: {
- category: cat.body,
- mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
+ category: cat.map,
+ mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
},
+ isNoSetCollision: true,
inertia: Infinity, //prevents rotation
isNotHoldable: true,
friction: 1,
@@ -581,21 +582,32 @@ const level = {
const rotor1 = Matter.Bodies.rectangle(x, y, width, radius, {
density: density,
isNotHoldable: true,
- isNonStick: true
+ isNonStick: true,
+ collisionFilter: {
+ category: cat.map,
+ mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
+ },
+ isNoSetCollision: true,
});
const rotor2 = Matter.Bodies.rectangle(x, y, width, radius, {
angle: Math.PI / 2,
density: density,
isNotHoldable: true,
- isNonStick: true
+ isNonStick: true,
+ collisionFilter: {
+ category: cat.map,
+ mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
+ },
+ isNoSetCollision: true,
});
rotor = Body.create({ //combine rotor1 and rotor2
parts: [rotor1, rotor2],
restitution: 0,
collisionFilter: {
- category: cat.body,
- mask: cat.body | cat.mob | cat.mobBullet | cat.mobShield | cat.powerUp | cat.player | cat.bullet
+ category: cat.map,
+ mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
},
+ isNoSetCollision: true,
});
Matter.Body.setPosition(rotor, {
x: x,
@@ -605,10 +617,10 @@ const level = {
body[body.length] = rotor1
body[body.length] = rotor2
- setTimeout(function() {
- rotor.collisionFilter.category = cat.body;
- rotor.collisionFilter.mask = cat.body | cat.player | cat.bullet | cat.mob | cat.mobBullet //| cat.map
- }, 1000);
+ // setTimeout(function() {
+ // rotor.collisionFilter.category = cat.body;
+ // rotor.collisionFilter.mask = cat.body | cat.player | cat.bullet | cat.mob | cat.mobBullet //| cat.map
+ // }, 1000);
const constraint = Constraint.create({ //fix rotor in place, but allow rotation
pointA: {
@@ -794,8 +806,6 @@ const level = {
this.isTouched = false
this.collisionFilter.mask = 0 //cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
this.returnCount = this.returnTime
- const size = 1
- // const vertices = [{ x: x * size, y: y, index: 0, isInternal: false }, { x: (x + width) * size, y: y, index: 1, isInternal: false }, { x: (x + width) * size, y: y + height, index: 4, isInternal: false }, { x: x * size, y: y + height, index: 3, isInternal: false }]
Matter.Body.setVertices(this, this.shrinkVertices(1)) //take on harpoon shape
Matter.Body.setVertices(this, vertices) //take on harpoon shape
}
@@ -818,7 +828,7 @@ const level = {
//delete any overlapping blocks
const blocks = Matter.Query.collides(this, body)
for (let i = 0; i < blocks.length; i++) {
- if (blocks[i].bodyB !== this) { //dont' delete yourself
+ if (blocks[i].bodyB !== this && blocks[i].bodyB !== m.holdingTarget) { //dont' delete yourself <----- bug here maybe...
Matter.Composite.remove(engine.world, blocks[i].bodyB);
blocks[i].bodyB.isRemoveMeNow = true
for (let i = 1; i < body.length; i++) { //find which index in body array it is and remove from array
@@ -1168,6 +1178,9 @@ const level = {
x: Math.max(0.95, 1 - 0.036 * Math.abs(player.velocity.x)) * player.velocity.x,
y: slowY * player.velocity.y
});
+ //undo 1/2 of gravity
+ player.force.y -= 0.5 * player.mass * simulation.g;
+
}
//float power ups
powerUpCollide = Matter.Query.region(powerUp, this)
@@ -2427,16 +2440,16 @@ const level = {
button.query();
button.draw();
vanish1.query();
- vanish2.query();
- vanish3.query();
- vanish4.query();
- vanish5.query();
+ // vanish2.query();
+ // vanish3.query();
+ // vanish4.query();
+ // vanish5.query();
};
const vanish1 = level.vanish(1400, -200, 200, 50) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it
- const vanish2 = level.vanish(1825, -150, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it
- const vanish3 = level.vanish(1975, -150, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it
- const vanish4 = level.vanish(1825, -300, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it
- const vanish5 = level.vanish(1975, -300, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it
+ // const vanish2 = level.vanish(1825, -150, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it
+ // const vanish3 = level.vanish(1975, -150, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it
+ // const vanish4 = level.vanish(1825, -300, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it
+ // const vanish5 = level.vanish(1975, -300, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it
level.setPosToSpawn(0, -450); //normal spawn
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.exit.x = 6500;
@@ -2489,11 +2502,11 @@ const level = {
spawn.mapRect(4850, -275, 50, 175);
//???
- level.difficultyIncrease(1) //30 is near max on hard //60 is near max on why
+ level.difficultyIncrease(15) //30 is near max on hard //60 is near max on why
m.addHealth(Infinity)
// spawn.starter(1900, -500, 200) //big boy
-
+ spawn.slashBoss(1900, -500)
// spawn.launcherBoss(3200, -500)
// spawn.laserTargetingBoss(1700, -500)
// spawn.powerUpBoss(3200, -500)
@@ -2519,7 +2532,7 @@ const level = {
// for (let i = 0; i < 10; ++i) spawn.bodyRect(1600 + 5, -500, 30, 40);
// for (let i = 0; i < 5; i++) spawn.focuser(1900, -500)
- spawn.pulsar(1900, -500)
+ // spawn.pulsar(1900, -500)
// spawn.shield(mob[mob.length - 1], 1900, -500, 1);
// mob[mob.length - 1].isShielded = true
// spawn.nodeGroup(1200, 0, "grenadier")
@@ -8598,7 +8611,7 @@ const level = {
//Boss Spawning
if (simulation.difficulty > 5) {
- spawn.randomLevelBoss(-2200, -700, ["historyBoss", "powerUpBossBaby", "blockBoss", "revolutionBoss"]);
+ spawn.randomLevelBoss(-2200, -700, ["powerUpBossBaby", "blockBoss", "revolutionBoss"]);
setTimeout(() => {
simulation.makeTextLog("UNKNOWN: \"They are coming for you.\"", 600);
diff --git a/js/spawn.js b/js/spawn.js
index ba4b229..ca1a078 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -5,7 +5,7 @@ const spawn = {
randomLevelBoss(x, y, options = [
"shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
"powerUpBoss", "powerUpBossBaby", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss",
- "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "mantisBoss"
+ "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "mantisBoss", "slashBoss"
]) {
spawn[options[Math.floor(Math.random() * options.length)]](x, y)
},
@@ -3514,6 +3514,170 @@ const spawn = {
ctx.setLineDash([]);
}
},
+ slashBoss(x, y, radius = 80) {
+ mobs.spawn(x, y, 5, radius, "rgb(201,202,225)");
+ let me = mob[mob.length - 1];
+ Matter.Body.rotate(me, 2 * Math.PI * Math.random());
+ me.isBoss = true;
+ me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
+ me.startingDamageReduction = me.damageReduction
+ me.isInvulnerable = false
+ me.frictionAir = 0.01
+ me.seeAtDistance2 = 1000000;
+ me.accelMag = 0.001 + 0.0003 * simulation.accelScale;
+ Matter.Body.setDensity(me, 0.0005); //normal is 0.001
+ me.collisionFilter.mask = cat.bullet | cat.player | cat.body | cat.map
+ me.memory = Infinity;
+ me.seePlayerFreq = 20
+ me.lockedOn = null;
+
+ me.torqueMagnitude = 0.00024 * me.inertia * (Math.random() > 0.5 ? -1 : 1);
+ me.delay = 120 * simulation.CDScale;
+ me.cd = 0;
+ me.swordRadius = 0;
+ me.swordVertex = 1
+ me.swordRadiusMax = 1100 + 20 * simulation.difficulty;
+ me.swordRadiusGrowRate = me.swordRadiusMax * (0.005 + 0.0003 * simulation.difficulty)
+ me.isSlashing = false;
+ me.swordDamage = 0.07 * simulation.dmgScale
+ me.laserAngle = 3 * Math.PI / 5
+ const seeDistance2 = 200000
+ spawn.shield(me, x, y);
+ me.onDamage = function() {};
+ me.onDeath = function() {
+ powerUps.spawnBossPowerUp(this.position.x, this.position.y)
+ };
+ me.do = function() {
+ this.seePlayerByHistory();
+ this.attraction();
+ this.checkStatus();
+ if (!m.isBodiesAsleep) this.sword() //does various things depending on what stage of the sword swing
+
+ // ctx.beginPath(); //hide map
+ // ctx.arc(this.position.x, this.position.y, 3000, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay
+ // ctx.fillStyle = "#444";
+ // ctx.fill();
+ };
+ me.swordWaiting = function() {
+ if (
+ this.seePlayer.recall &&
+ this.cd < simulation.cycle &&
+ this.distanceToPlayer2() < seeDistance2 &&
+ Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 &&
+ Matter.Query.ray(body, this.position, this.playerPosRandomY()).length === 0
+ ) {
+ //find vertex farthest away from player
+ let dist = 0
+ for (let i = 0, len = this.vertices.length; i < len; i++) {
+ const D = Vector.magnitudeSquared(Vector.sub({ x: this.vertices[i].x, y: this.vertices[i].y }, m.pos))
+ if (D > dist) {
+ dist = D
+ this.swordVertex = i
+ }
+ }
+ this.laserAngle = this.swordVertex / 5 * 2 * Math.PI + 0.6283
+ this.sword = this.swordGrow
+ Matter.Body.setVelocity(this, { x: 0, y: 0 });
+ Matter.Body.setAngularVelocity(this, 0)
+ this.accelMag = 0
+ this.damageReduction = 0
+ this.isInvulnerable = true
+ this.frictionAir = 1
+ }
+ }
+ me.sword = me.swordWaiting //base function that changes during different aspects of the sword swing
+ me.swordGrow = function() {
+ this.laserSword(this.vertices[this.swordVertex], this.angle + this.laserAngle);
+ this.swordRadius += this.swordRadiusGrowRate
+ if (this.swordRadius > this.swordRadiusMax) {
+ this.sword = this.swordSlash
+ this.spinCount = 0
+ }
+
+ ctx.beginPath();
+ let vertices = this.vertices;
+ ctx.moveTo(vertices[0].x, vertices[0].y);
+ for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
+ ctx.lineTo(vertices[0].x, vertices[0].y);
+ ctx.lineWidth = 20;
+ ctx.strokeStyle = "rgba(255,255,255,0.7)";
+ ctx.stroke();
+ }
+ me.swordSlash = function() {
+ this.laserSword(this.vertices[this.swordVertex], this.angle + this.laserAngle);
+ this.torque += this.torqueMagnitude;
+ this.spinCount++
+ if (this.spinCount > 80) {
+ this.sword = this.swordWaiting
+ this.swordRadius = 0
+ this.accelMag = 0.001 * simulation.accelScale;
+ this.cd = simulation.cycle + this.delay;
+ this.damageReduction = this.startingDamageReduction
+ this.isInvulnerable = false
+ this.frictionAir = 0.01
+ }
+ ctx.beginPath();
+ let vertices = this.vertices;
+ ctx.moveTo(vertices[0].x, vertices[0].y);
+ for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
+ ctx.lineTo(vertices[0].x, vertices[0].y);
+ ctx.lineWidth = 20;
+ ctx.strokeStyle = "rgba(255,255,255,0.7)";
+ ctx.stroke();
+ }
+ me.laserSword = function(where, angle) {
+ const vertexCollision = function(v1, v1End, domain) {
+ for (let i = 0; i < domain.length; ++i) {
+ let v = domain[i].vertices;
+ const len = v.length - 1;
+ for (let j = 0; j < len; j++) {
+ results = simulation.checkLineIntersection(v1, v1End, v[j], v[j + 1]);
+ if (results.onLine1 && results.onLine2) {
+ const dx = v1.x - results.x;
+ const dy = v1.y - results.y;
+ const dist2 = dx * dx + dy * dy;
+ if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[j], v2: v[j + 1] };
+ }
+ }
+ results = simulation.checkLineIntersection(v1, v1End, v[0], v[len]);
+ if (results.onLine1 && results.onLine2) {
+ const dx = v1.x - results.x;
+ const dy = v1.y - results.y;
+ const dist2 = dx * dx + dy * dy;
+ if (dist2 < best.dist2) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[0], v2: v[len] };
+ }
+ }
+ };
+ best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
+ const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
+ vertexCollision(where, look, body); // vertexCollision(where, look, mob);
+ vertexCollision(where, look, map);
+ if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]);
+ if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
+ m.immuneCycle = m.cycle + tech.collisionImmuneCycles + 60; //player is immune to damage for an extra second
+ m.damage(this.swordDamage);
+ simulation.drawList.push({ //add dmg to draw queue
+ x: best.x,
+ y: best.y,
+ radius: this.swordDamage * 1500,
+ color: "rgba(80,0,255,0.5)",
+ time: 20
+ });
+ }
+ if (best.dist2 === Infinity) best = look;
+ ctx.beginPath(); //draw beam
+ ctx.moveTo(where.x, where.y);
+ ctx.lineTo(best.x, best.y);
+ ctx.strokeStyle = "rgba(100,100,255,0.1)"; // Purple path
+ ctx.lineWidth = 25;
+ ctx.stroke();
+ ctx.strokeStyle = "rgba(100,100,255,0.5)"; // Purple path
+ ctx.lineWidth = 5;
+ ctx.setLineDash([70 + 300 * Math.random(), 55 * Math.random()]);
+ ctx.stroke(); // Draw it
+ ctx.setLineDash([]);
+ }
+ },
slasher(x, y, radius = 36 + Math.ceil(Math.random() * 25)) {
mobs.spawn(x, y, 5, radius, "rgb(201,202,225)");
let me = mob[mob.length - 1];
diff --git a/js/tech.js b/js/tech.js
index 89b3ca6..0bd7f03 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -214,7 +214,7 @@ const tech = {
if (tech.isAxion && tech.isHarmMACHO) dmg *= 1 + 0.75 * (1 - m.harmReduction())
if (tech.OccamDamage) dmg *= tech.OccamDamage
if (tech.isCloakingDamage) dmg *= 1.35
- if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.5
+ if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555
if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599
if (m.isSneakAttack && m.cycle > m.lastKillCycle + 240) dmg *= tech.sneakAttackDmg
if (tech.isTechDamage) dmg *= 1.9
@@ -1016,7 +1016,7 @@ const tech = {
{
name: "nail-bot upgrade",
link: `nail-bot upgrade`,
- description: "convert your current bots to nail-bots
+500% fire rate and +40% nail velocity",
+ description: "convert your bots to nail-bots
+500% fire rate and +40% nail velocity",
maxCount: 1,
count: 0,
frequency: 3,
@@ -1072,7 +1072,7 @@ const tech = {
{
name: "foam-bot upgrade",
link: `foam-bot upgrade`,
- description: "convert your current bots to foam-bots
300% increased foam size and fire rate",
+ description: "convert your bots to foam-bots
300% increased foam size and fire rate",
maxCount: 1,
count: 0,
frequency: 3,
@@ -1128,7 +1128,7 @@ const tech = {
{
name: "boom-bot upgrade",
link: `boom-bot upgrade`,
- description: "convert your current bots to boom-bots
300% increased explosion damage and size",
+ description: "convert your bots to boom-bots
300% increased explosion damage and size",
maxCount: 1,
count: 0,
frequency: 3,
@@ -1186,7 +1186,7 @@ const tech = {
{
name: "laser-bot upgrade",
link: `laser-bot upgrade`,
- description: "convert your current bots to laser-bots
100% improved damage, efficiency, and range", // 400% increased laser-bot laser damage",
+ description: "convert your bots to laser-bots
100% improved damage, efficiency, and range", // 400% increased laser-bot laser damage",
maxCount: 1,
count: 0,
frequency: 3,
@@ -1242,7 +1242,7 @@ const tech = {
{
name: "orbital-bot upgrade",
link: `orbital-bot upgrade`,
- description: "convert your current bots to orbital-bots
increase damage by 300% and radius by 50%",
+ description: "convert your bots to orbital-bots
increase damage by 300% and radius by 50%",
maxCount: 1,
count: 0,
frequency: 3,
@@ -1307,7 +1307,7 @@ const tech = {
{
name: "dynamo-bot upgrade",
link: `dynamo-bot upgrade`,
- description: "convert your current bots to dynamo-bots
increase regen to 23 energy per second",
+ description: "convert your bots to dynamo-bots
increase regen to 23 energy per second",
maxCount: 1,
count: 0,
frequency: 3,
@@ -1748,7 +1748,7 @@ const tech = {
},
{
name: "NAND gate",
- description: "if in the ON state
do 50% more damage",
+ description: "if in the ON state
do 55.5% more damage",
maxCount: 1,
count: 0,
frequency: 4,
@@ -6116,6 +6116,25 @@ const tech = {
if (this.count > 0) powerUps.research.changeRerolls(2)
}
},
+ {
+ name: "radiative equilibrium",
+ description: "for 10 seconds after receiving harm
increase damage by 200%",
+ isFieldTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 1,
+ frequencyDefault: 1,
+ allowed() {
+ return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "negative mass") && (build.isExperimentSelection || powerUps.research.count > 3)
+ },
+ requires: "negative mass, pilot wave",
+ effect() {
+ tech.isHarmDamage = true;
+ },
+ remove() {
+ tech.isHarmDamage = false;
+ }
+ },
{
name: "neutronium",
description: `reduce harm by 90% when your field is active
move and jump 33% slower`,
@@ -6223,7 +6242,7 @@ const tech = {
},
{
name: "bot manufacturing",
- description: `use molecular assembler and ${powerUps.orb.research(2)}
to build 3 random bots`,
+ description: `use ${powerUps.orb.research(2)} to build
3 random bots`,
isFieldTech: true,
maxCount: 1,
count: 0,
diff --git a/todo.txt b/todo.txt
index 35c9e3a..2ba44f6 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,22 +1,33 @@
******************************************************** NEXT PATCH **************************************************
-the level list now has 2 levels randomly removed to bring the total back to 13
- 15 level play session felt too long
+new boss: slashBoss - same as slash mob, but it's get invulnerability of course
-tech: invariant - use energy to pause time while placing your wormhole
+if you have upgraded bots then random bot will that type
+being inside slime reduces gravity by 50% through buoyancy
+difficulty increase for mobs harm is 2% lower per level
+boson composite no longer lets you pass through elevators and rotors
-reservoir level has wider platforms, and some other changes
-
-Zeno's paradox 83->85% harm reduction
-supply chain no longer gives 5% JUNK
-vector field renamed -> tensor field: also gives 7 research
+NAND gate damage 50 -> 55.5%
******************************************************** TODO ********************************************************
+if you have upgraded bots then random bot will that type
+ might have to nerf upgraded bots in the future, but let's try it out
+
+variant of Occam's razor - remove 50% of your tech for each removed get:
+ 2 bots?
+ 50 energy max
+
+animate going to next level?
+ door fills in with color that climbs up vertically through the door graphic the longer you stand on door
+ hold crouch on door? or automatically
+
+make ship mode more playable and a fun option for people with trackpads
joystick support?
make a new boss with similar movement to powerUpBossBaby
bossBaby power up boss has really smart movement
+ like slasher mob since it's kinda the best mob
reversed version of reservoir level, start at top and press buttons to lower slime
@@ -35,15 +46,6 @@ new platform element, spring
toggle to on when player touches platform
platform extends in any direction
-vanish element:
- grow as it returns?
-
-pull bullets back to player with crouch/field
- spores?
- extend to all bullets?
- write custom code based on bullet type
- bad for: laser, harpoon?, missile and grenade?
-
boss that gives nearby mobs invulnerability
invulnerability needs to toggle off and on
boss is only mildly aggressive
@@ -102,10 +104,6 @@ make a line of constrained mobs move like a snake
tech: basic research - heal power ups spawn as research power ups instead, and using research heals you (needs to be pretty low, like 3% health)
tech: maintenance - heals no longer spawn, but using research heals you 100%
-tech reversed regression - mobs take less damage after each time you hit them, but you get +100% damage
- maybe a gun tech only?
- what gun?
-
foam tech - make it move slower, last much longer, and push away other foam bullets
not sure about bouncing off walls, but that might be fun too
@@ -149,21 +147,11 @@ mob/boss that fires a laser at player, but give player time to avoid
they target where player was 1 second ago
they turn to face player?
-tech: open a new tab for n-gon, spawn things in the original game based on events in new game
- if you die in new die in original?
- new is n-gon classic?
- make a JUNK tech?
-if you die in original open a tab with a new n-gon that starts on a random level with a random load out. if you clear the level you come back to life in the original?
-
bug - death while paused crashes game?
tech rocket jump - jumping produces an explosion at your feet that lets you jump extra high, but does some damage
require electric reactive armor?
-animate going to next level?
- door fills in with color that climbs up vertically through the door graphic the longer you stand on door
- hold crouch on door? or automatically
-
Plasma Burner: upgrade for plasma torch, basically just a jet engine. does high damage, but short range, mostly for player movement.
maybe reduce gravity to really low then apply a vector away from mouse direction
@@ -357,6 +345,8 @@ n-gon outreach ideas
******************************************************** BUGS ********************************************************
+vanish element bug, crashes on touching element, happens for 1 person maybe with junk tech?
+
safari issues
once: can't pick up blocks
fixed on new map
@@ -409,11 +399,6 @@ is there a way to check if the player is stuck inside the map or block
******************************************************** LEVELS ********************************************************
-new late game level that is easier if you can: platform well, jump high, immune to slime, wormhole through walls, fly fast
- climb vertically to avoid rising slime
- populate with multiple boss mobs that can't drop tech
- bosses spawn in pairs
-
map: observatory
button controls rotation of telescope
laser beam shoots out of telescope