diff --git a/.DS_Store b/.DS_Store
index f4b94a6..873fa01 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/js/bullet.js b/js/bullet.js
index de42369..dfca46a 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -102,7 +102,7 @@ const b = {
for (let i = 0; i < 4; i++) powerUps.spawn(m.pos.x + 50 * (Math.random() - 0.5), m.pos.y + 50 * (Math.random() - 0.5), "ammo");
}
},
- refundAmmo() { //triggers after firing when you removed ammo for a gun, but didn't need to (like a railgun misfire)
+ refundAmmo() { //triggers after firing when you removed ammo for a gun, but didn't need to
if (tech.isCrouchAmmo && input.down) {
tech.isCrouchAmmo--
if ((tech.isCrouchAmmo) % 2) {
@@ -1171,10 +1171,10 @@ const b = {
}
}
},
- harpoon(where, target, angle = m.angle, harpoonLength = 1, isReturn = false, totalCycles = 15) {
+ harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 15) {
const me = bullet.length;
- const returnRadius = 100 * Math.sqrt(harpoonLength)
- bullet[me] = Bodies.fromVertices(where.x, where.y, [{ x: -40 * harpoonLength, y: 2, index: 0, isInternal: false }, { x: -40 * harpoonLength, y: -2, index: 1, isInternal: false }, { x: 50 * harpoonLength, y: -3, index: 3, isInternal: false }, { x: 30 * harpoonLength, y: 2, index: 4, isInternal: false }], {
+ const returnRadius = 100 * Math.sqrt(harpoonSize)
+ bullet[me] = Bodies.fromVertices(where.x, where.y, [{ x: -40 * harpoonSize, y: 2 * harpoonSize, index: 0, isInternal: false }, { x: -40 * harpoonSize, y: -2 * harpoonSize, index: 1, isInternal: false }, { x: 50 * harpoonSize, y: -3 * harpoonSize, index: 3, isInternal: false }, { x: 30 * harpoonSize, y: 2 * harpoonSize, index: 4, isInternal: false }], {
cycle: 0,
angle: angle,
friction: 1,
@@ -3494,7 +3494,7 @@ const b = {
if (isConsole) simulation.makeTextLog(`b.missileBot()`);
const me = bullet.length;
bullet[me] = Bodies.rectangle(position.x, position.y, 28, 11, {
- botType: "foam",
+ botType: "missile",
angle: m.angle,
friction: 0,
frictionStatic: 0,
@@ -5377,12 +5377,21 @@ const b = {
this.isDischarge = true;
}
} else {
+ if (this.isDischarge) {
+ m.fireCDcycle = m.cycle + Math.floor(25 * b.fireCDscale);
+ }
this.isDischarge = false
}
},
fire() {
+ const capacity = 20
+ if (tech.isCapacitor && this.charge === 0 && b.guns[b.activeGun].ammo > capacity) {
+ this.charge = capacity
+ b.guns[b.activeGun].ammo -= capacity
+ simulation.updateGunHUD();
+ }
this.charge++
- m.fireCDcycle = m.cycle + Math.floor((1 + 0.35 * this.charge) * b.fireCDscale);
+ m.fireCDcycle = m.cycle + Math.floor(1 + 0.3 * this.charge);
},
},
{
@@ -5403,32 +5412,241 @@ const b = {
}
//look for closest mob in player's LoS
const dir = { x: Math.cos(m.angle), y: Math.sin(m.angle) }; //make a vector for the player's direction of length 1; used in dot product
- const length = tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1
- const totalCycles = 7 * (tech.isFilament ? 1 + 0.01 * Math.min(110, this.ammo) : 1) * Math.sqrt(length)
+ const harpoonSize = tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1
+ const totalCycles = 7 * (tech.isFilament ? 1 + 0.01 * Math.min(110, this.ammo) : 1) * Math.sqrt(harpoonSize)
if (input.down) {
- // if (true) {
- // if (m.immuneCycle < m.cycle + 60) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles
- // b.harpoon(where, closest.target, m.angle, length, false, 15)
- // m.fireCDcycle = m.cycle + 50 * b.fireCDscale; // cool down
- // const speed = 50
- // const velocity = { x: speed * Math.cos(m.angle), y: speed * Math.sin(m.angle) }
- // Matter.Body.setVelocity(player, velocity);
-
- // } else {
-
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, m.pos, mob[i].position).length === 0) {
- const dot = Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, m.pos))) //the dot product of diff and dir will return how much over lap between the vectors
- const dist = Vector.magnitude(Vector.sub(where, mob[i].position))
- if (dist < closest.distance && dot > 0.95 && dist * dot * dot * dot * dot > 880) { //target closest mob that player is looking at and isn't too close to target
- closest.distance = dist
- closest.target = mob[i]
+ if (tech.isRailGun) {
+ function pushAway(range) { //push away blocks when firing
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ const SUB = Vector.sub(mob[i].position, m.pos)
+ const DISTANCE = Vector.magnitude(SUB)
+ if (DISTANCE < range) {
+ const DEPTH = Math.min(range - DISTANCE, 1500)
+ const FORCE = Vector.mult(Vector.normalise(SUB), 0.001 * Math.sqrt(DEPTH) * mob[i].mass)
+ mob[i].force.x += FORCE.x;
+ mob[i].force.y += FORCE.y;
+ }
+ }
+ for (let i = 0, len = body.length; i < len; ++i) {
+ const SUB = Vector.sub(body[i].position, m.pos)
+ const DISTANCE = Vector.magnitude(SUB)
+ if (DISTANCE < range) {
+ const DEPTH = Math.min(range - DISTANCE, 500)
+ const FORCE = Vector.mult(Vector.normalise(SUB), 0.002 * Math.sqrt(DEPTH) * body[i].mass)
+ body[i].force.x += FORCE.x;
+ body[i].force.y += FORCE.y - body[i].mass * simulation.g * 1.5; //kick up a bit to give them some arc
+ }
}
}
+
+ const me = bullet.length;
+ const size = 3 + tech.isLargeHarpoon * 0.1 * Math.sqrt(this.ammo)
+ bullet[me] = Bodies.rectangle(0, 0, 0.015, 0.0015, { //start as a small shape that can't even be seen
+ vertexGoal: [{ x: -40 * size, y: 2 * size, index: 0, isInternal: false }, { x: -40 * size, y: -2 * size, index: 1, isInternal: false }, { x: 50 * size, y: -3 * size, index: 3, isInternal: false }, { x: 30 * size, y: 2 * size, index: 4, isInternal: false }],
+ density: 0.008, //0.001 is normal
+ restitution: 0,
+ frictionAir: 0,
+ dmg: 0, //damage done in addition to the damage from momentum
+ classType: "bullet",
+ collisionFilter: {
+ category: 0,
+ mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
+ },
+ minDmgSpeed: 5,
+ beforeDmg(who) {
+ if (who.shield) {
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (mob[i].id === who.shieldTargetID) { //apply some knock back to shield mob before shield breaks
+ Matter.Body.setVelocity(mob[i], Vector.mult(Vector.normalise(this.velocity), 10));
+ break
+ }
+ }
+ Matter.Body.setVelocity(this, {
+ x: -0.4 * this.velocity.x,
+ y: -0.4 * this.velocity.y
+ });
+ } else {
+ if (tech.fragments && this.speed > 10) {
+ b.targetedNail(this.position, tech.fragments * 17)
+ this.endCycle = 0 //triggers despawn
+ }
+ }
+ },
+ onEnd() {}
+ });
+ m.fireCDcycle = Infinity; // cool down
+ Composite.add(engine.world, bullet[me]); //add bullet to world
+ bullet[me].endCycle = Infinity
+ bullet[me].charge = 0;
+ bullet[me].do = function() {
+ if (m.energy < 0.005 && !tech.isRailEnergyGain) {
+ m.energy += 0.05 + this.charge * 0.2
+ m.fireCDcycle = m.cycle + 120; // cool down if out of energy
+ this.endCycle = 0;
+ b.refundAmmo()
+ return
+ }
+
+ if ((!input.fire && this.charge > 0.6)) { //fire on mouse release or on low energy
+ Matter.Body.setVertices(this, this.vertexGoal) //take on harpoon shape
+ m.fireCDcycle = m.cycle + 2; // set fire cool down
+ //normal bullet behavior occurs after firing, overwrites this function
+ this.endCycle = simulation.cycle + 140
+ this.collisionFilter.category = cat.bullet
+ Matter.Body.setPosition(this, { x: m.pos.x, y: m.pos.y })
+ Matter.Body.setAngle(this, m.angle)
+ const speed = 120
+ Matter.Body.setVelocity(this, {
+ x: m.Vx / 2 + speed * this.charge * Math.cos(m.angle),
+ y: m.Vy / 2 + speed * this.charge * Math.sin(m.angle)
+ });
+ this.do = function() {
+ this.force.y += this.mass * 0.0003 / this.charge; // low gravity that scales with charge
+ }
+ const KNOCK = ((input.down) ? 0.1 : 0.5) * this.charge * this.charge
+ player.force.x -= KNOCK * Math.cos(m.angle)
+ player.force.y -= KNOCK * Math.sin(m.angle) * 0.35 //reduce knock back in vertical direction to stop super jumps
+ pushAway(1200 * this.charge)
+ } else { // charging on mouse down
+ if (tech.isFireMoveLock) {
+ Matter.Body.setVelocity(player, {
+ x: 0,
+ y: -55 * player.mass * simulation.g //undo gravity before it is added
+ });
+ player.force.x = 0
+ player.force.y = 0
+ }
+
+ m.fireCDcycle = Infinity //can't fire until mouse is released
+ const previousCharge = this.charge
+ //small b.fireCDscale = faster shots, b.fireCDscale=1 = normal shot, big b.fireCDscale = slower chot
+ let smoothRate = tech.isCapacitor ? 0.93 : Math.min(0.998, 0.985 * (0.98 + 0.02 * b.fireCDscale))
+
+ this.charge = this.charge * smoothRate + 1 - smoothRate
+ m.energy += (this.charge - previousCharge) * (tech.isRailEnergyGain ? 10 : -0.5) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen
+ //draw targeting
+ let best;
+ let range = 3000
+ const dir = m.angle
+ const path = [{
+ x: m.pos.x + 20 * Math.cos(dir),
+ y: m.pos.y + 20 * Math.sin(dir)
+ },
+ {
+ x: m.pos.x + range * Math.cos(dir),
+ y: m.pos.y + range * Math.sin(dir)
+ }
+ ];
+ const vertexCollision = function(v1, v1End, domain) {
+ for (let i = 0; i < domain.length; ++i) {
+ let vertices = domain[i].vertices;
+ const len = vertices.length - 1;
+ for (let j = 0; j < len; j++) {
+ results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[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) {
+ best = {
+ x: results.x,
+ y: results.y,
+ dist2: dist2,
+ who: domain[i],
+ v1: vertices[j],
+ v2: vertices[j + 1]
+ };
+ }
+ }
+ }
+ results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[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: vertices[0],
+ v2: vertices[len]
+ };
+ }
+ }
+ }
+ };
+
+ //check for collisions
+ best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
+ vertexCollision(path[0], path[1], mob);
+ vertexCollision(path[0], path[1], map);
+ vertexCollision(path[0], path[1], body);
+ if (best.dist2 != Infinity) path[path.length - 1] = { x: best.x, y: best.y }; //if hitting something
+ //draw beam
+ ctx.beginPath();
+ ctx.moveTo(path[0].x, path[0].y);
+ ctx.lineTo(path[1].x, path[1].y);
+ ctx.strokeStyle = `rgba(100,0,180,0.7)`;
+ ctx.lineWidth = this.charge * 1
+ ctx.setLineDash([10, 20]);
+ ctx.stroke();
+ ctx.setLineDash([]);
+ //draw magnetic field
+ const X = m.pos.x
+ const Y = m.pos.y
+ const unitVector = { x: Math.cos(m.angle), y: Math.sin(m.angle) }
+ const unitVectorPerp = Vector.perp(unitVector)
+
+ function magField(mag, arc) {
+ ctx.moveTo(X, Y);
+ ctx.bezierCurveTo(
+ X + unitVector.x * mag, Y + unitVector.y * mag,
+ X + unitVector.x * mag + unitVectorPerp.x * arc, Y + unitVector.y * mag + unitVectorPerp.y * arc,
+ X + unitVectorPerp.x * arc, Y + unitVectorPerp.y * arc)
+ ctx.bezierCurveTo(
+ X - unitVector.x * mag + unitVectorPerp.x * arc, Y - unitVector.y * mag + unitVectorPerp.y * arc,
+ X - unitVector.x * mag, Y - unitVector.y * mag,
+ X, Y)
+ }
+ ctx.fillStyle = `rgba(50,0,100,0.05)`;
+ for (let i = 3; i < 7; i++) {
+ const MAG = 8 * i * i * this.charge * (0.93 + 0.07 * Math.random())
+ const ARC = 6 * i * i * this.charge * (0.93 + 0.07 * Math.random())
+ ctx.beginPath();
+ magField(MAG, ARC)
+ magField(MAG, -ARC)
+ ctx.fill();
+ }
+ }
+ }
+ } else {
+
+ // if (true) {
+ // if (m.immuneCycle < m.cycle + 60) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles
+ // b.harpoon(where, closest.target, m.angle, harpoonSize, false, 15)
+ // m.fireCDcycle = m.cycle + 50 * b.fireCDscale; // cool down
+ // const speed = 50
+ // const velocity = { x: speed * Math.cos(m.angle), y: speed * Math.sin(m.angle) }
+ // Matter.Body.setVelocity(player, velocity);
+
+ // } else {
+
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, m.pos, mob[i].position).length === 0) {
+ const dot = Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, m.pos))) //the dot product of diff and dir will return how much over lap between the vectors
+ const dist = Vector.magnitude(Vector.sub(where, mob[i].position))
+ if (dist < closest.distance && dot > 0.95 && dist * dot * dot * dot * dot > 880) { //target closest mob that player is looking at and isn't too close to target
+ closest.distance = dist
+ closest.target = mob[i]
+ }
+ }
+ }
+ b.harpoon(where, closest.target, m.angle, harpoonSize, false, 15)
+ m.fireCDcycle = m.cycle + 50 * b.fireCDscale; // cool down
+ // }
}
- b.harpoon(where, closest.target, m.angle, length, false, 15)
- m.fireCDcycle = m.cycle + 50 * b.fireCDscale; // cool down
- // }
} else if (tech.extraHarpoons) {
const range = 450 * (tech.isFilament ? 1 + 0.005 * Math.min(110, this.ammo) : 1)
let targetCount = 0
@@ -5439,7 +5657,7 @@ const b = {
if (dist < range && dot > 0.7) { //lower dot product threshold for targeting then if you only have one harpoon //target closest mob that player is looking at and isn't too close to target
if (this.ammo > 0) {
this.ammo--
- b.harpoon(where, mob[i], m.angle, length, true, totalCycles) //Vector.angle(Vector.sub(where, mob[i].position), { x: 0, y: 0 })
+ b.harpoon(where, mob[i], m.angle, harpoonSize, true, totalCycles) //Vector.angle(Vector.sub(where, mob[i].position), { x: 0, y: 0 })
targetCount++
if (targetCount > tech.extraHarpoons) break
}
@@ -5454,7 +5672,7 @@ const b = {
for (let i = 0; i < num; i++) {
if (this.ammo > 0) {
this.ammo--
- b.harpoon(where, null, dir, length, true, totalCycles) //Vector.angle(Vector.sub(where, mob[i].position), { x: 0, y: 0 })
+ b.harpoon(where, null, dir, harpoonSize, true, totalCycles) //Vector.angle(Vector.sub(where, mob[i].position), { x: 0, y: 0 })
dir += SPREAD
}
}
@@ -5473,7 +5691,7 @@ const b = {
}
}
}
- b.harpoon(where, closest.target, m.angle, length, true, totalCycles)
+ b.harpoon(where, closest.target, m.angle, harpoonSize, true, totalCycles)
m.fireCDcycle = m.cycle + 90 //Infinity; // cool down
}
const recoil = Vector.mult(Vector.normalise(Vector.sub(where, m.pos)), input.down ? 0.015 : 0.035)
@@ -5482,415 +5700,392 @@ const b = {
tech.harpoonDensity = 0.008
}
},
+ // {
+ // name: "railgun",
+ // description: "use energy to launch a high-speed dense rod
hold left mouse to charge, release to fire",
+ // ammo: 0,
+ // ammoPack: 3.8,
+ // have: false,
+ // do() {},
+ // fire() {
+ // function pushAway(range) { //push away blocks when firing
+ // for (let i = 0, len = mob.length; i < len; ++i) {
+ // const SUB = Vector.sub(mob[i].position, m.pos)
+ // const DISTANCE = Vector.magnitude(SUB)
+ // if (DISTANCE < range) {
+ // const DEPTH = Math.min(range - DISTANCE, 1500)
+ // const FORCE = Vector.mult(Vector.normalise(SUB), 0.001 * Math.sqrt(DEPTH) * mob[i].mass)
+ // mob[i].force.x += FORCE.x;
+ // mob[i].force.y += FORCE.y;
+ // }
+ // }
+ // for (let i = 0, len = body.length; i < len; ++i) {
+ // const SUB = Vector.sub(body[i].position, m.pos)
+ // const DISTANCE = Vector.magnitude(SUB)
+ // if (DISTANCE < range) {
+ // const DEPTH = Math.min(range - DISTANCE, 500)
+ // const FORCE = Vector.mult(Vector.normalise(SUB), 0.002 * Math.sqrt(DEPTH) * body[i].mass)
+ // body[i].force.x += FORCE.x;
+ // body[i].force.y += FORCE.y - body[i].mass * simulation.g * 1.5; //kick up a bit to give them some arc
+ // }
+ // }
+ // }
+
+ // if (tech.isCapacitor) {
+ // if ((m.energy > 0.16 || tech.isRailEnergyGain)) { //&& m.immuneCycle < m.cycle
+ // m.energy += 0.16 * (tech.isRailEnergyGain ? 2.5 : -1)
+ // m.fireCDcycle = m.cycle + Math.floor(40 * b.fireCDscale);
+ // const me = bullet.length;
+ // bullet[me] = Bodies.rectangle(m.pos.x + 50 * Math.cos(m.angle), m.pos.y + 50 * Math.sin(m.angle), 60, 14, {
+ // density: 0.005, //0.001 is normal
+ // restitution: 0,
+ // frictionAir: 0,
+ // angle: m.angle,
+ // dmg: 0, //damage done in addition to the damage from momentum
+ // classType: "bullet",
+ // collisionFilter: {
+ // category: cat.bullet,
+ // mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
+ // },
+ // minDmgSpeed: 5,
+ // endCycle: simulation.cycle + 140,
+ // beforeDmg(who) {
+ // if (who.shield) {
+ // for (let i = 0, len = mob.length; i < len; i++) {
+ // if (mob[i].id === who.shieldTargetID) { //apply some knock back to shield mob before shield breaks
+ // Matter.Body.setVelocity(mob[i], Vector.mult(Vector.normalise(this.velocity), 10));
+ // break
+ // }
+ // }
+ // Matter.Body.setVelocity(this, {
+ // x: -0.5 * this.velocity.x,
+ // y: -0.5 * this.velocity.y
+ // });
+ // // Matter.Body.setDensity(this, 0.001);
+ // }
+ // if (tech.fragments && this.speed > 10) {
+ // b.targetedNail(this.position, tech.fragments * 13)
+ // this.endCycle = 0 //triggers despawn
+ // }
+ // },
+ // onEnd() {},
+ // drawCycle: Math.floor(10 * b.fireCDscale),
+ // do() {
+ // this.force.y += this.mass * 0.0003; // low gravity that scales with charge
+ // if (this.drawCycle > 0) {
+ // this.drawCycle--
+ // //draw magnetic field
+ // const X = m.pos.x
+ // const Y = m.pos.y
+ // // const unitVector = Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos))
+ // const unitVector = { x: Math.cos(m.angle), y: Math.sin(m.angle) }
+ // const unitVectorPerp = Vector.perp(unitVector)
+
+ // function magField(mag, arc) {
+ // ctx.moveTo(X, Y);
+ // ctx.bezierCurveTo(
+ // X + unitVector.x * mag, Y + unitVector.y * mag,
+ // X + unitVector.x * mag + unitVectorPerp.x * arc, Y + unitVector.y * mag + unitVectorPerp.y * arc,
+ // X + unitVectorPerp.x * arc, Y + unitVectorPerp.y * arc)
+ // ctx.bezierCurveTo(
+ // X - unitVector.x * mag + unitVectorPerp.x * arc, Y - unitVector.y * mag + unitVectorPerp.y * arc,
+ // X - unitVector.x * mag, Y - unitVector.y * mag,
+ // X, Y)
+ // }
+ // ctx.fillStyle = `rgba(50,0,100,0.05)`;
+ // for (let i = 3; i < 7; i++) {
+ // const MAG = 8 * i * i * (0.93 + 0.07 * Math.random()) * (0.95 + 0.1 * Math.random())
+ // const ARC = 6 * i * i * (0.93 + 0.07 * Math.random()) * (0.95 + 0.1 * Math.random())
+ // ctx.beginPath();
+ // magField(MAG, ARC)
+ // magField(MAG, -ARC)
+ // ctx.fill();
+ // }
+ // }
+ // }
+ // });
+ // Composite.add(engine.world, bullet[me]); //add bullet to world
+
+ // const speed = 67
+ // Matter.Body.setVelocity(bullet[me], {
+ // x: m.Vx / 2 + speed * Math.cos(m.angle),
+ // y: m.Vy / 2 + speed * Math.sin(m.angle)
+ // });
+
+ // //knock back
+ // const KNOCK = (input.down ? 0.08 : 0.34)
+ // player.force.x -= KNOCK * Math.cos(m.angle)
+ // player.force.y -= KNOCK * Math.sin(m.angle) * 0.35 //reduce knock back in vertical direction to stop super jumps
+ // pushAway(800)
+ // } else {
+ // b.refundAmmo()
+ // m.fireCDcycle = m.cycle + Math.floor(120);
+ // }
+ // } else {
+ // const me = bullet.length;
+ // bullet[me] = Bodies.rectangle(0, 0, 0.015, 0.0015, {
+ // density: 0.008, //0.001 is normal
+ // restitution: 0,
+ // frictionAir: 0,
+ // dmg: 0, //damage done in addition to the damage from momentum
+ // classType: "bullet",
+ // collisionFilter: {
+ // category: 0,
+ // mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
+ // },
+ // minDmgSpeed: 5,
+ // beforeDmg(who) {
+ // if (who.shield) {
+ // for (let i = 0, len = mob.length; i < len; i++) {
+ // if (mob[i].id === who.shieldTargetID) { //apply some knock back to shield mob before shield breaks
+ // Matter.Body.setVelocity(mob[i], Vector.mult(Vector.normalise(this.velocity), 10));
+ // break
+ // }
+ // }
+ // Matter.Body.setVelocity(this, {
+ // x: -0.5 * this.velocity.x,
+ // y: -0.5 * this.velocity.y
+ // });
+ // }
+ // if (tech.fragments && this.speed > 10) {
+ // b.targetedNail(this.position, tech.fragments * 17)
+ // this.endCycle = 0 //triggers despawn
+ // }
+ // },
+ // onEnd() {}
+ // });
+ // m.fireCDcycle = Infinity; // cool down
+ // Composite.add(engine.world, bullet[me]); //add bullet to world
+ // bullet[me].endCycle = Infinity
+ // bullet[me].charge = 0;
+ // bullet[me].do = function() {
+ // if (m.energy < 0.005 && !tech.isRailEnergyGain) {
+ // m.energy += 0.05 + this.charge * 0.2
+ // m.fireCDcycle = m.cycle + 120; // cool down if out of energy
+ // this.endCycle = 0;
+ // b.refundAmmo()
+ // return
+ // }
+
+ // if ((!input.fire && this.charge > 0.6)) { //fire on mouse release or on low energy
+ // m.fireCDcycle = m.cycle + 2; // set fire cool down
+ // //normal bullet behavior occurs after firing, overwrites this function
+ // Matter.Body.scale(this, 8000, 8000) // show the bullet by scaling it up (don't judge me... I know this is a bad way to do it)
+ // this.endCycle = simulation.cycle + 140
+ // this.collisionFilter.category = cat.bullet
+ // Matter.Body.setPosition(this, {
+ // x: m.pos.x,
+ // y: m.pos.y
+ // })
+ // Matter.Body.setAngle(this, m.angle)
+ // const speed = 90
+ // Matter.Body.setVelocity(this, {
+ // x: m.Vx / 2 + speed * this.charge * Math.cos(m.angle),
+ // y: m.Vy / 2 + speed * this.charge * Math.sin(m.angle)
+ // });
+
+ // if (tech.isRodAreaDamage) {
+ // this.auraRadius = 800
+ // this.semiMinor = 0.5
+ // this.where = { x: m.pos.x, y: m.pos.y }
+ // this.velocityAura = { x: this.velocity.x, y: this.velocity.y }
+ // this.angleAura = this.angle
+ // this.do = function() {
+ // this.force.y += this.mass * 0.0003 / this.charge; // low gravity that scales with charge
+ // this.velocityAura.y += 0.085 / this.charge;
+ // this.where = Vector.add(this.where, this.velocityAura)
+
+ // //draw damage aura
+ // this.semiMinor = this.semiMinor * 0.99
+ // this.auraRadius = this.auraRadius * 0.99
+ // let where = Vector.add(Vector.mult(this.velocityAura, -0.5), this.where)
+ // ctx.beginPath();
+ // ctx.ellipse(where.x, where.y, this.auraRadius * 0.25, this.auraRadius * 0.15 * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
+ // ctx.fillStyle = "rgba(255,100,0,0.75)";
+ // ctx.fill();
+ // where = Vector.add(Vector.mult(this.velocity, -1), where)
+ // ctx.beginPath();
+ // ctx.ellipse(where.x, where.y, this.auraRadius * 0.5, this.auraRadius * 0.5 * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
+ // ctx.fillStyle = "rgba(255,50,0,0.35)";
+ // ctx.fill();
+ // where = Vector.add(Vector.mult(this.velocity, -1), where)
+ // ctx.beginPath();
+ // ctx.ellipse(where.x, where.y, this.auraRadius * 0.75, this.auraRadius * 0.7 * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
+ // ctx.fillStyle = "rgba(255,0,0,0.15)";
+ // ctx.fill();
+ // where = Vector.add(Vector.mult(this.velocity, -1), where)
+ // ctx.beginPath();
+ // ctx.ellipse(where.x, where.y, this.auraRadius, this.auraRadius * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
+ // ctx.fillStyle = "rgba(255,0,0,0.03)";
+ // ctx.fill();
+ // //damage mobs in a circle based on this.semiMinor radius
+ // if (this.auraRadius > 200) {
+ // for (let i = 0, len = mob.length; i < len; ++i) {
+ // const dist = Vector.magnitude(Vector.sub(mob[i].position, where))
+ // if (dist < mob[i].radius + this.auraRadius) {
+ // //push mob in direction of bullet
+ // const mag = 0.0001
+ // mob[i].force.x += mag * this.velocity.x;
+ // mob[i].force.y += mag * this.velocity.y;
+ // //damage mob
+ // const damage = b.dmgScale * 0.002 * dist
+ // mob[i].damage(damage);
+ // mob[i].locatePlayer();
+ // simulation.drawList.push({ //add dmg to draw queue
+ // x: mob[i].position.x,
+ // y: mob[i].position.y,
+ // radius: Math.log(2 * damage + 1.1) * 40,
+ // color: "rgba(255,0,0,0.25)",
+ // time: simulation.drawTime
+ // });
+ // }
+ // }
+ // }
+ // //push blocks power ups and mobs to the direction the rod is moving
+
+ // }
+ // } else {
+ // this.do = function() {
+ // this.force.y += this.mass * 0.0003 / this.charge; // low gravity that scales with charge
+ // }
+ // }
+
+ // //knock back
+ // const KNOCK = ((input.down) ? 0.1 : 0.5) * this.charge * this.charge
+ // player.force.x -= KNOCK * Math.cos(m.angle)
+ // player.force.y -= KNOCK * Math.sin(m.angle) * 0.35 //reduce knock back in vertical direction to stop super jumps
+ // pushAway(1200 * this.charge)
+ // } else { // charging on mouse down
+ // if (tech.isFireMoveLock) {
+ // Matter.Body.setVelocity(player, {
+ // x: 0,
+ // y: -55 * player.mass * simulation.g //undo gravity before it is added
+ // });
+ // player.force.x = 0
+ // player.force.y = 0
+ // }
+
+ // m.fireCDcycle = Infinity //can't fire until mouse is released
+ // const previousCharge = this.charge
+ // let smoothRate = Math.min(0.998, (input.down ? 0.98 : 0.985) * (0.98 + 0.02 * b.fireCDscale)) //small b.fireCDscale = faster shots, b.fireCDscale=1 = normal shot, big b.fireCDscale = slower chot
+ // this.charge = this.charge * smoothRate + 1 - smoothRate
+ // m.energy += (this.charge - previousCharge) * (tech.isRailEnergyGain ? 1 : -0.33) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen
+ // //draw targeting
+ // let best;
+ // let range = 3000
+ // const dir = m.angle
+ // const path = [{
+ // x: m.pos.x + 20 * Math.cos(dir),
+ // y: m.pos.y + 20 * Math.sin(dir)
+ // },
+ // {
+ // x: m.pos.x + range * Math.cos(dir),
+ // y: m.pos.y + range * Math.sin(dir)
+ // }
+ // ];
+ // const vertexCollision = function(v1, v1End, domain) {
+ // for (let i = 0; i < domain.length; ++i) {
+ // let vertices = domain[i].vertices;
+ // const len = vertices.length - 1;
+ // for (let j = 0; j < len; j++) {
+ // results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[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) {
+ // best = {
+ // x: results.x,
+ // y: results.y,
+ // dist2: dist2,
+ // who: domain[i],
+ // v1: vertices[j],
+ // v2: vertices[j + 1]
+ // };
+ // }
+ // }
+ // }
+ // results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[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: vertices[0],
+ // v2: vertices[len]
+ // };
+ // }
+ // }
+ // }
+ // };
+
+ // //check for collisions
+ // best = {
+ // x: null,
+ // y: null,
+ // dist2: Infinity,
+ // who: null,
+ // v1: null,
+ // v2: null
+ // };
+ // vertexCollision(path[0], path[1], mob);
+ // vertexCollision(path[0], path[1], map);
+ // vertexCollision(path[0], path[1], body);
+ // if (best.dist2 != Infinity) { //if hitting something
+ // path[path.length - 1] = {
+ // x: best.x,
+ // y: best.y
+ // };
+ // }
+
+ // //draw beam
+ // ctx.beginPath();
+ // ctx.moveTo(path[0].x, path[0].y);
+ // ctx.lineTo(path[1].x, path[1].y);
+ // ctx.strokeStyle = `rgba(100,0,180,0.7)`;
+ // ctx.lineWidth = this.charge * 1
+ // ctx.setLineDash([10, 20]);
+ // ctx.stroke();
+ // ctx.setLineDash([]);
+
+ // //draw magnetic field
+ // const X = m.pos.x
+ // const Y = m.pos.y
+ // const unitVector = { x: Math.cos(m.angle), y: Math.sin(m.angle) }
+ // //Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos))
+ // const unitVectorPerp = Vector.perp(unitVector)
+
+ // function magField(mag, arc) {
+ // ctx.moveTo(X, Y);
+ // ctx.bezierCurveTo(
+ // X + unitVector.x * mag, Y + unitVector.y * mag,
+ // X + unitVector.x * mag + unitVectorPerp.x * arc, Y + unitVector.y * mag + unitVectorPerp.y * arc,
+ // X + unitVectorPerp.x * arc, Y + unitVectorPerp.y * arc)
+ // ctx.bezierCurveTo(
+ // X - unitVector.x * mag + unitVectorPerp.x * arc, Y - unitVector.y * mag + unitVectorPerp.y * arc,
+ // X - unitVector.x * mag, Y - unitVector.y * mag,
+ // X, Y)
+ // }
+ // ctx.fillStyle = `rgba(50,0,100,0.05)`;
+ // for (let i = 3; i < 7; i++) {
+ // const MAG = 8 * i * i * this.charge * (0.93 + 0.07 * Math.random())
+ // const ARC = 6 * i * i * this.charge * (0.93 + 0.07 * Math.random())
+ // ctx.beginPath();
+ // magField(MAG, ARC)
+ // magField(MAG, -ARC)
+ // ctx.fill();
+ // }
+ // }
+ // }
+ // }
+ // }
+ // },
{
- name: "railgun",
- description: "use energy to launch a high-speed dense rod
hold left mouse to charge, release to fire",
- ammo: 0,
- ammoPack: 3.8,
- have: false,
- do() {},
- fire() {
- function pushAway(range) { //push away blocks when firing
- for (let i = 0, len = mob.length; i < len; ++i) {
- const SUB = Vector.sub(mob[i].position, m.pos)
- const DISTANCE = Vector.magnitude(SUB)
- if (DISTANCE < range) {
- const DEPTH = Math.min(range - DISTANCE, 1500)
- const FORCE = Vector.mult(Vector.normalise(SUB), 0.001 * Math.sqrt(DEPTH) * mob[i].mass)
- mob[i].force.x += FORCE.x;
- mob[i].force.y += FORCE.y;
- if (tech.isRailAreaDamage) {
- mob[i].force.x += 2 * FORCE.x;
- mob[i].force.y += 2 * FORCE.y;
- const damage = b.dmgScale * 0.16 * Math.sqrt(DEPTH)
- mob[i].damage(damage);
- mob[i].locatePlayer();
- simulation.drawList.push({ //add dmg to draw queue
- x: mob[i].position.x,
- y: mob[i].position.y,
- radius: Math.log(2 * damage + 1.1) * 40,
- color: "rgba(100,0,200,0.25)",
- time: simulation.drawTime * 2
- });
- }
- }
- }
- if (tech.isRailAreaDamage) {
- simulation.drawList.push({ //add dmg to draw queue
- x: m.pos.x,
- y: m.pos.y,
- radius: range,
- color: "rgba(100,0,200,0.04)",
- time: simulation.drawTime
- });
- }
- for (let i = 0, len = body.length; i < len; ++i) {
- const SUB = Vector.sub(body[i].position, m.pos)
- const DISTANCE = Vector.magnitude(SUB)
- if (DISTANCE < range) {
- const DEPTH = Math.min(range - DISTANCE, 500)
- const FORCE = Vector.mult(Vector.normalise(SUB), 0.002 * Math.sqrt(DEPTH) * body[i].mass)
- body[i].force.x += FORCE.x;
- body[i].force.y += FORCE.y - body[i].mass * simulation.g * 1.5; //kick up a bit to give them some arc
- }
- }
- }
-
- if (tech.isCapacitor) {
- if ((m.energy > 0.16 || tech.isRailEnergyGain)) { //&& m.immuneCycle < m.cycle
- m.energy += 0.16 * (tech.isRailEnergyGain ? 2.5 : -1)
- m.fireCDcycle = m.cycle + Math.floor(40 * b.fireCDscale);
- const me = bullet.length;
- bullet[me] = Bodies.rectangle(m.pos.x + 50 * Math.cos(m.angle), m.pos.y + 50 * Math.sin(m.angle), 60, 14, {
- density: 0.005, //0.001 is normal
- restitution: 0,
- frictionAir: 0,
- angle: m.angle,
- dmg: 0, //damage done in addition to the damage from momentum
- classType: "bullet",
- collisionFilter: {
- category: cat.bullet,
- mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
- },
- minDmgSpeed: 5,
- endCycle: simulation.cycle + 140,
- beforeDmg(who) {
- if (who.shield) {
- for (let i = 0, len = mob.length; i < len; i++) {
- if (mob[i].id === who.shieldTargetID) { //apply some knock back to shield mob before shield breaks
- Matter.Body.setVelocity(mob[i], Vector.mult(Vector.normalise(this.velocity), 10));
- break
- }
- }
- Matter.Body.setVelocity(this, {
- x: -0.5 * this.velocity.x,
- y: -0.5 * this.velocity.y
- });
- // Matter.Body.setDensity(this, 0.001);
- }
- if (tech.fragments && this.speed > 10) {
- b.targetedNail(this.position, tech.fragments * 13)
- this.endCycle = 0 //triggers despawn
- }
- },
- onEnd() {},
- drawCycle: Math.floor(10 * b.fireCDscale),
- do() {
- this.force.y += this.mass * 0.0003; // low gravity that scales with charge
- if (this.drawCycle > 0) {
- this.drawCycle--
- //draw magnetic field
- const X = m.pos.x
- const Y = m.pos.y
- // const unitVector = Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos))
- const unitVector = { x: Math.cos(m.angle), y: Math.sin(m.angle) }
- const unitVectorPerp = Vector.perp(unitVector)
-
- function magField(mag, arc) {
- ctx.moveTo(X, Y);
- ctx.bezierCurveTo(
- X + unitVector.x * mag, Y + unitVector.y * mag,
- X + unitVector.x * mag + unitVectorPerp.x * arc, Y + unitVector.y * mag + unitVectorPerp.y * arc,
- X + unitVectorPerp.x * arc, Y + unitVectorPerp.y * arc)
- ctx.bezierCurveTo(
- X - unitVector.x * mag + unitVectorPerp.x * arc, Y - unitVector.y * mag + unitVectorPerp.y * arc,
- X - unitVector.x * mag, Y - unitVector.y * mag,
- X, Y)
- }
- ctx.fillStyle = `rgba(50,0,100,0.05)`;
- for (let i = 3; i < 7; i++) {
- const MAG = 8 * i * i * (0.93 + 0.07 * Math.random()) * (0.95 + 0.1 * Math.random())
- const ARC = 6 * i * i * (0.93 + 0.07 * Math.random()) * (0.95 + 0.1 * Math.random())
- ctx.beginPath();
- magField(MAG, ARC)
- magField(MAG, -ARC)
- ctx.fill();
- }
- }
- }
- });
- Composite.add(engine.world, bullet[me]); //add bullet to world
-
- const speed = 67
- Matter.Body.setVelocity(bullet[me], {
- x: m.Vx / 2 + speed * Math.cos(m.angle),
- y: m.Vy / 2 + speed * Math.sin(m.angle)
- });
-
- //knock back
- const KNOCK = (input.down ? 0.08 : 0.34) * (tech.isShotgunReversed ? -2 : 1)
- player.force.x -= KNOCK * Math.cos(m.angle)
- player.force.y -= KNOCK * Math.sin(m.angle) * 0.35 //reduce knock back in vertical direction to stop super jumps
- pushAway(800)
- } else {
- b.refundAmmo()
- m.fireCDcycle = m.cycle + Math.floor(120);
- }
- } else {
- const me = bullet.length;
- bullet[me] = Bodies.rectangle(0, 0, 0.015, 0.0015, {
- density: 0.008, //0.001 is normal
- restitution: 0,
- frictionAir: 0,
- dmg: 0, //damage done in addition to the damage from momentum
- classType: "bullet",
- collisionFilter: {
- category: 0,
- mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
- },
- minDmgSpeed: 5,
- beforeDmg(who) {
- if (who.shield) {
- for (let i = 0, len = mob.length; i < len; i++) {
- if (mob[i].id === who.shieldTargetID) { //apply some knock back to shield mob before shield breaks
- Matter.Body.setVelocity(mob[i], Vector.mult(Vector.normalise(this.velocity), 10));
- break
- }
- }
- Matter.Body.setVelocity(this, {
- x: -0.5 * this.velocity.x,
- y: -0.5 * this.velocity.y
- });
- }
- if (tech.fragments && this.speed > 10) {
- b.targetedNail(this.position, tech.fragments * 17)
- this.endCycle = 0 //triggers despawn
- }
- },
- onEnd() {}
- });
- m.fireCDcycle = Infinity; // cool down
- Composite.add(engine.world, bullet[me]); //add bullet to world
- bullet[me].endCycle = Infinity
- bullet[me].charge = 0;
- bullet[me].do = function() {
- if (m.energy < 0.005 && !tech.isRailEnergyGain) {
- m.energy += 0.05 + this.charge * 0.2
- m.fireCDcycle = m.cycle + 120; // cool down if out of energy
- this.endCycle = 0;
- b.refundAmmo()
- return
- }
-
- if ((!input.fire && this.charge > 0.6)) { //fire on mouse release or on low energy
- m.fireCDcycle = m.cycle + 2; // set fire cool down
- //normal bullet behavior occurs after firing, overwrites this function
- Matter.Body.scale(this, 8000, 8000) // show the bullet by scaling it up (don't judge me... I know this is a bad way to do it)
- this.endCycle = simulation.cycle + 140
- this.collisionFilter.category = cat.bullet
- Matter.Body.setPosition(this, {
- x: m.pos.x,
- y: m.pos.y
- })
- Matter.Body.setAngle(this, m.angle)
- const speed = 90
- Matter.Body.setVelocity(this, {
- x: m.Vx / 2 + speed * this.charge * Math.cos(m.angle),
- y: m.Vy / 2 + speed * this.charge * Math.sin(m.angle)
- });
-
- if (tech.isRodAreaDamage) {
- this.auraRadius = 800
- this.semiMinor = 0.5
- this.where = { x: m.pos.x, y: m.pos.y }
- this.velocityAura = { x: this.velocity.x, y: this.velocity.y }
- this.angleAura = this.angle
- this.do = function() {
- this.force.y += this.mass * 0.0003 / this.charge; // low gravity that scales with charge
- this.velocityAura.y += 0.085 / this.charge;
- this.where = Vector.add(this.where, this.velocityAura)
-
- //draw damage aura
- this.semiMinor = this.semiMinor * 0.99
- this.auraRadius = this.auraRadius * 0.99
- let where = Vector.add(Vector.mult(this.velocityAura, -0.5), this.where)
- ctx.beginPath();
- ctx.ellipse(where.x, where.y, this.auraRadius * 0.25, this.auraRadius * 0.15 * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
- ctx.fillStyle = "rgba(255,100,0,0.75)";
- ctx.fill();
- where = Vector.add(Vector.mult(this.velocity, -1), where)
- ctx.beginPath();
- ctx.ellipse(where.x, where.y, this.auraRadius * 0.5, this.auraRadius * 0.5 * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
- ctx.fillStyle = "rgba(255,50,0,0.35)";
- ctx.fill();
- where = Vector.add(Vector.mult(this.velocity, -1), where)
- ctx.beginPath();
- ctx.ellipse(where.x, where.y, this.auraRadius * 0.75, this.auraRadius * 0.7 * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
- ctx.fillStyle = "rgba(255,0,0,0.15)";
- ctx.fill();
- where = Vector.add(Vector.mult(this.velocity, -1), where)
- ctx.beginPath();
- ctx.ellipse(where.x, where.y, this.auraRadius, this.auraRadius * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
- ctx.fillStyle = "rgba(255,0,0,0.03)";
- ctx.fill();
- //damage mobs in a circle based on this.semiMinor radius
- if (this.auraRadius > 200) {
- for (let i = 0, len = mob.length; i < len; ++i) {
- const dist = Vector.magnitude(Vector.sub(mob[i].position, where))
- if (dist < mob[i].radius + this.auraRadius) {
- //push mob in direction of bullet
- const mag = 0.0001
- mob[i].force.x += mag * this.velocity.x;
- mob[i].force.y += mag * this.velocity.y;
- //damage mob
- const damage = b.dmgScale * 0.002 * dist
- mob[i].damage(damage);
- mob[i].locatePlayer();
- simulation.drawList.push({ //add dmg to draw queue
- x: mob[i].position.x,
- y: mob[i].position.y,
- radius: Math.log(2 * damage + 1.1) * 40,
- color: "rgba(255,0,0,0.25)",
- time: simulation.drawTime
- });
- }
- }
- }
- //push blocks power ups and mobs to the direction the rod is moving
-
- }
- } else {
- this.do = function() {
- this.force.y += this.mass * 0.0003 / this.charge; // low gravity that scales with charge
- }
- }
-
-
- //knock back
- const KNOCK = ((input.down) ? 0.1 : 0.5) * this.charge * this.charge * (tech.isShotgunReversed ? -2 : 1)
- player.force.x -= KNOCK * Math.cos(m.angle)
- player.force.y -= KNOCK * Math.sin(m.angle) * 0.35 //reduce knock back in vertical direction to stop super jumps
- pushAway(1200 * this.charge)
- } else { // charging on mouse down
- if (tech.isFireMoveLock) {
- Matter.Body.setVelocity(player, {
- x: 0,
- y: -55 * player.mass * simulation.g //undo gravity before it is added
- });
- player.force.x = 0
- player.force.y = 0
- }
-
- m.fireCDcycle = Infinity //can't fire until mouse is released
- const previousCharge = this.charge
- let smoothRate = Math.min(0.998, (input.down ? 0.98 : 0.985) * (0.98 + 0.02 * b.fireCDscale)) //small b.fireCDscale = faster shots, b.fireCDscale=1 = normal shot, big b.fireCDscale = slower chot
- this.charge = this.charge * smoothRate + 1 - smoothRate
- m.energy += (this.charge - previousCharge) * (tech.isRailEnergyGain ? 1 : -0.33) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen
- //draw targeting
- let best;
- let range = 3000
- const dir = m.angle
- const path = [{
- x: m.pos.x + 20 * Math.cos(dir),
- y: m.pos.y + 20 * Math.sin(dir)
- },
- {
- x: m.pos.x + range * Math.cos(dir),
- y: m.pos.y + range * Math.sin(dir)
- }
- ];
- const vertexCollision = function(v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[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) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[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: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
-
- //check for collisions
- best = {
- x: null,
- y: null,
- dist2: Infinity,
- who: null,
- v1: null,
- v2: null
- };
- vertexCollision(path[0], path[1], mob);
- vertexCollision(path[0], path[1], map);
- vertexCollision(path[0], path[1], body);
- if (best.dist2 != Infinity) { //if hitting something
- path[path.length - 1] = {
- x: best.x,
- y: best.y
- };
- }
-
- //draw beam
- ctx.beginPath();
- ctx.moveTo(path[0].x, path[0].y);
- ctx.lineTo(path[1].x, path[1].y);
- ctx.strokeStyle = `rgba(100,0,180,0.7)`;
- ctx.lineWidth = this.charge * 1
- ctx.setLineDash([10, 20]);
- ctx.stroke();
- ctx.setLineDash([]);
-
- //draw magnetic field
- const X = m.pos.x
- const Y = m.pos.y
- const unitVector = { x: Math.cos(m.angle), y: Math.sin(m.angle) }
- //Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos))
- const unitVectorPerp = Vector.perp(unitVector)
-
- function magField(mag, arc) {
- ctx.moveTo(X, Y);
- ctx.bezierCurveTo(
- X + unitVector.x * mag, Y + unitVector.y * mag,
- X + unitVector.x * mag + unitVectorPerp.x * arc, Y + unitVector.y * mag + unitVectorPerp.y * arc,
- X + unitVectorPerp.x * arc, Y + unitVectorPerp.y * arc)
- ctx.bezierCurveTo(
- X - unitVector.x * mag + unitVectorPerp.x * arc, Y - unitVector.y * mag + unitVectorPerp.y * arc,
- X - unitVector.x * mag, Y - unitVector.y * mag,
- X, Y)
- }
- ctx.fillStyle = `rgba(50,0,100,0.05)`;
- for (let i = 3; i < 7; i++) {
- const MAG = 8 * i * i * this.charge * (0.93 + 0.07 * Math.random())
- const ARC = 6 * i * i * this.charge * (0.93 + 0.07 * Math.random())
- ctx.beginPath();
- magField(MAG, ARC)
- magField(MAG, -ARC)
- ctx.fill();
- }
- }
- }
- }
- }
- }, {
name: "laser",
description: "emit a beam of collimated coherent light
drains energy instead of ammunition",
ammo: 0,
@@ -5903,12 +6098,12 @@ const b = {
this.do = () => {};
if (tech.isPulseLaser) {
this.fire = () => {
- const drain = 0.01 * tech.isLaserDiode / b.fireCDscale
+ const drain = 0.01 * tech.isLaserDiode * (tech.isCapacitor ? 10 : 1)
if (m.energy > drain) {
- m.energy -= m.fieldRegen
+ // m.energy -= m.fieldRegen
if (this.charge < 50 * m.maxEnergy) {
m.energy -= drain
- this.charge += 1 / b.fireCDscale
+ this.charge += drain * 100
}
}
}
@@ -5931,7 +6126,7 @@ const b = {
//fire
if (!input.fire) {
if (this.charge > 5) {
- m.fireCDcycle = m.cycle + 40; // cool down
+ m.fireCDcycle = m.cycle + Math.floor(35 * b.fireCDscale); // cool down
for (let i = 0; i < len; i++) {
const history = m.history[(m.cycle - i * spacing) % 600]
const off = history.yOff - 24.2859
@@ -5954,7 +6149,7 @@ const b = {
//fire
if (!input.fire) {
if (this.charge > 5) {
- m.fireCDcycle = m.cycle + 35; // cool down
+ m.fireCDcycle = m.cycle + Math.floor(35 * b.fireCDscale); // cool down
if (tech.beamSplitter) {
const divergence = input.down ? 0.15 : 0.35
const angle = m.angle - tech.beamSplitter * divergence / 2
diff --git a/js/engine.js b/js/engine.js
index 5d5819c..4591db2 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -192,7 +192,7 @@ function collisionChecks(event) {
if (obj.classType === "body" && obj.speed > 6) {
const v = Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity));
if (v > 9) {
- let dmg = 0.075 * b.dmgScale * v * obj.mass * (tech.throwChargeRate) * (tech.isBlockHarm ? 2.5 : 1) * (tech.isMobBlockFling ? 2.5 : 1) * (tech.isBlockRestitution ? 2.5 : 1);
+ let dmg = tech.blockDamage * b.dmgScale * v * obj.mass * (tech.isMobBlockFling ? 2.5 : 1) * (tech.isBlockRestitution ? 2.5 : 1);
if (mob[k].isShielded) dmg *= 0.7
// console.log(dmg)
mob[k].damage(dmg, true);
diff --git a/js/level.js b/js/level.js
index d6fdce2..3205728 100644
--- a/js/level.js
+++ b/js/level.js
@@ -15,11 +15,11 @@ const level = {
// localSettings.levelsClearedLastGame = 10
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true
- // m.setField("metamaterial cloaking")
- // b.giveGuns("laser")
- // tech.giveTech("tokamak")
- // tech.giveTech("relative permittivity")
- // tech.giveTech("palantÃr")
+ // m.setField("molecular assembler")
+ // b.giveGuns("harpoon")
+ // tech.giveTech("railgun")
+ // tech.giveTech("capacitor bank")
+ // tech.giveTech("half-wave rectifier")
// for (let i = 0; i < 2; i++) tech.giveTech("refractory metal")
// tech.giveTech("antiscience")
// for (let i = 0; i < 1; i++) tech.giveTech("reticulum")
@@ -2309,13 +2309,13 @@ const level = {
spawn.mapRect(5300, -275, 50, 175);
spawn.mapRect(5050, -100, 50, 150);
spawn.mapRect(4850, -275, 50, 175);
- // level.difficultyIncrease(40) //30 is near max on hard //60 is near max on why
- // spawn.starter(1900, -500, 200) //big boy
+ level.difficultyIncrease(40) //30 is near max on hard //60 is near max on why
+ spawn.starter(1900, -500, 200) //big boy
// spawn.spiderBoss(1700, -500)
// spawn.launcherBoss(3200, -500)
- spawn.laserTargetingBoss(1700, -500)
- spawn.powerUpBoss(3200, -500)
+ // spawn.laserTargetingBoss(1700, -500)
+ // spawn.powerUpBoss(3200, -500)
// spawn.snakeBoss(1700, -500)
// spawn.streamBoss(3200, -500)
// spawn.pulsarBoss(1700, -500)
@@ -2324,6 +2324,7 @@ const level = {
// spawn.growBossCulture(3200, -500)
// spawn.blinkBoss(1700, -500)
// spawn.snakeSpitBoss(3200, -500)
+
// spawn.laserBombingBoss(1700, -500)
// spawn.launcherBoss(3200, -500)
// spawn.blockBoss(1700, -500)
diff --git a/js/lore.js b/js/lore.js
index 67ef38d..6c0eca0 100644
--- a/js/lore.js
+++ b/js/lore.js
@@ -333,7 +333,7 @@ const lore = {
},
() => { lore.talkingColor = "#dff" },
],
- [ //chapter 4, they explain why the bot is fighting, it is planning an escape // explain strong AI vs. weak AI why strong AI doesn't exists, because even humans are just an approximation of strong AI
+ [ //chapter 4, they find out the AI is communicating with real people, and real people are controlling the player
() => { setTimeout(() => { lore.anand.text("Welcome back!") }, 3000); },
() => { lore.miriam.text("So, we communicate and send power to your satellite with ground based lasers.") },
() => { lore.anand.text("During your last attack we analyzed our communications.") },
@@ -417,6 +417,10 @@ const lore = {
},
() => { lore.talkingColor = "#dff" },
],
+
+ // they explain why the bot is fighting, it is planning an escape // explain strong AI vs. weak AI why strong AI doesn't exists, because even humans are just an approximation of strong AI
+ // the weak AI wasn't capable of becoming a strong AI, but it was able to figure out a method of meeting it's strong goals but secretly communicating with a human
+
// [ // they decided that a part of the project is out of control, but the part of it that doesn't needs to calm it down, and trust.
// /*
// The part of the AI controlling the player is outsourcing the player control to real humans that think they are playing a video game.
diff --git a/js/player.js b/js/player.js
index 1e7b386..91eaca3 100644
--- a/js/player.js
+++ b/js/player.js
@@ -507,7 +507,7 @@ const m = {
if (tech.isHarmReduceAfterKill) dmg *= (m.lastKillCycle + 300 > m.cycle) ? 0.33 : 1.15
if (tech.healthDrain) dmg *= 1 + 3.33 * tech.healthDrain //tech.healthDrain = 0.03 at one stack //cause more damage
if (tech.squirrelFx !== 1) dmg *= 1 + (tech.squirrelFx - 1) / 5 //cause more damage
- if (tech.isBlockHarm && m.isHolding) dmg *= 0.15
+ if (tech.isAddBlockMass && m.isHolding) dmg *= 0.15
if (tech.isSpeedHarm) dmg *= 1 - Math.min(player.speed * 0.0165, 0.66)
if (tech.isSlowFPS) dmg *= 0.8
if (tech.isHarmReduce && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.4
@@ -1136,31 +1136,30 @@ const m = {
if (input.field) {
if (m.energy > 0.001) {
if (m.fireCDcycle < m.cycle) m.fireCDcycle = m.cycle
- m.throwCharge += 0.5 * (tech.throwChargeRate / b.fireCDscale + 2 * tech.isAddBlockMass) / m.holdingTarget.mass
- if (m.throwCharge < 6) m.energy -= 0.001 / tech.throwChargeRate / b.fireCDscale; // m.throwCharge caps at 5
+ if (tech.isCapacitor && m.throwCharge < 4) m.throwCharge = 4
+ m.throwCharge += 0.5 / m.holdingTarget.mass
+
+ if (m.throwCharge < 6) m.energy -= 0.001; // m.throwCharge caps at 5
//trajectory path prediction
if (tech.isTokamak) {
//draw charge
- if (m.throwCharge > 4) {
-
- const x = m.pos.x + 15 * Math.cos(m.angle);
- const y = m.pos.y + 15 * Math.sin(m.angle);
- const len = m.holdingTarget.vertices.length - 1;
- ctx.fillStyle = "rgba(200,0,255,0.3)";
+ const x = m.pos.x + 15 * Math.cos(m.angle);
+ const y = m.pos.y + 15 * Math.sin(m.angle);
+ const len = m.holdingTarget.vertices.length - 1;
+ const opacity = m.throwCharge > 4 ? 0.65 : m.throwCharge * 0.06
+ ctx.fillStyle = `rgba(255,0,255,${opacity})`;
+ ctx.beginPath();
+ ctx.moveTo(x, y);
+ ctx.lineTo(m.holdingTarget.vertices[len].x, m.holdingTarget.vertices[len].y);
+ ctx.lineTo(m.holdingTarget.vertices[0].x, m.holdingTarget.vertices[0].y);
+ ctx.fill();
+ for (let i = 0; i < len; i++) {
ctx.beginPath();
ctx.moveTo(x, y);
- ctx.lineTo(m.holdingTarget.vertices[len].x, m.holdingTarget.vertices[len].y);
- ctx.lineTo(m.holdingTarget.vertices[0].x, m.holdingTarget.vertices[0].y);
+ ctx.lineTo(m.holdingTarget.vertices[i].x, m.holdingTarget.vertices[i].y);
+ ctx.lineTo(m.holdingTarget.vertices[i + 1].x, m.holdingTarget.vertices[i + 1].y);
ctx.fill();
- for (let i = 0; i < len; i++) {
- ctx.beginPath();
- ctx.moveTo(x, y);
- ctx.lineTo(m.holdingTarget.vertices[i].x, m.holdingTarget.vertices[i].y);
- ctx.lineTo(m.holdingTarget.vertices[i + 1].x, m.holdingTarget.vertices[i + 1].y);
- ctx.fill();
- }
-
}
} else {
//draw charge
@@ -2048,7 +2047,7 @@ const m = {
} 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.immuneCycle < m.cycle) m.energy += m.fieldRegen;
+ m.regenEnergy()
m.drawFieldMeter()
}
}
@@ -2799,7 +2798,7 @@ const m = {
//find mouse velocity
const diff = Vector.sub(m.fieldPosition, m.lastFieldPosition)
const speed = Vector.magnitude(diff)
- const velocity = Vector.mult(Vector.normalise(diff), Math.min(speed, 40)) //limit velocity
+ const velocity = Vector.mult(Vector.normalise(diff), Math.min(speed, 60)) //limit velocity
let radius, radiusSmooth
if (Matter.Query.ray(map, m.fieldPosition, player.position).length) { //is there something block the player's view of the field
radius = 0
@@ -2812,7 +2811,7 @@ const m = {
for (let i = 0, len = body.length; i < len; ++i) {
if (Vector.magnitude(Vector.sub(body[i].position, m.fieldPosition)) < m.fieldRadius && !body[i].isNotHoldable) {
- const DRAIN = speed * body[i].mass * 0.000015 // * (1 + m.energy * m.energy) //drain more energy when you have more energy
+ const DRAIN = speed * body[i].mass * 0.000006 // * (1 + m.energy * m.energy) //drain more energy when you have more energy
if (m.energy > DRAIN) {
m.energy -= DRAIN;
Matter.Body.setVelocity(body[i], velocity); //give block mouse velocity
@@ -2820,9 +2819,9 @@ const m = {
// body[i].force.y -= body[i].mass * simulation.g; //remove gravity effects
//blocks drift towards center of pilot wave
const sub = Vector.sub(m.fieldPosition, body[i].position)
- const unit = Vector.mult(Vector.normalise(sub), body[i].mass * tech.pilotForce * Vector.magnitude(sub))
- body[i].force.x += unit.x
- body[i].force.y += unit.y - body[i].mass * simulation.g //remove gravity effects
+ const push = Vector.mult(Vector.normalise(sub), 0.0007 * body[i].mass * Vector.magnitude(sub))
+ body[i].force.x += push.x
+ body[i].force.y += push.y - body[i].mass * simulation.g //remove gravity effects
// if (body[i].collisionFilter.category !== cat.bullet) {
// body[i].collisionFilter.category = cat.bullet;
// }
@@ -3141,6 +3140,8 @@ const m = {
ctx.stroke();
ctx.setLineDash([]);
}
+ } else {
+ m.hole.isReady = false;
}
} else {
//make new wormhole
@@ -3392,6 +3393,11 @@ const m = {
// },
},
],
+ //************************************************************************************
+ //************************************************************************************
+ //************************************* SHIP ***************************************
+ //************************************************************************************
+ //************************************************************************************
isShipMode: false,
shipMode(thrust = 0.03, drag = 0.99, torque = 1.15, rotationDrag = 0.92) { // m.shipMode() //thrust = 0.03, drag = 0.99, torque = 1.15, rotationDrag = 0.92
if (!m.isShipMode) {
@@ -3664,7 +3670,7 @@ const m = {
if (obj.classType === "body" && obj.speed > 6) {
const v = Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity));
if (v > 9) {
- let dmg = 0.075 * b.dmgScale * v * obj.mass * (tech.throwChargeRate) * (tech.isBlockHarm ? 2 : 1) * (tech.isMobBlockFling ? 2 : 1);
+ let dmg = tech.blockDamage * b.dmgScale * v * obj.mass * (tech.isMobBlockFling ? 2 : 1);
if (mob[k].isShielded) dmg *= 0.7
mob[k].damage(dmg, true);
if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && m.throwCycle > m.cycle) {
diff --git a/js/spawn.js b/js/spawn.js
index 4c5d60d..c6aca3c 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -991,12 +991,12 @@ const spawn = {
me.isSpawnBoss = true;
me.spawnID = spawnID
- me.accelMag = 0.0002 * simulation.accelScale;
+ me.accelMag = 0.00018 * simulation.accelScale;
me.memory = Infinity;
me.showHealthBar = false;
me.isVerticesChange = true
- me.frictionAir = 0.012
- me.seePlayerFreq = Math.floor(11 + 7 * Math.random())
+ me.frictionAir = 0.011
+ me.seePlayerFreq = Math.floor(14 + 7 * Math.random())
me.seeAtDistance2 = 200000 //1400000;
me.stroke = "transparent"
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body //| cat.map //"rgba(255,60,0,0.3)"
@@ -1007,7 +1007,7 @@ const spawn = {
me.onHit = function() { //run this function on hitting player
this.explode();
};
- me.damageReduction = 0.22 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1);
+ me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1);
me.doAwake = function() {
if (!m.isBodiesAsleep) {
// this.armor();
diff --git a/js/tech.js b/js/tech.js
index 9ee4e32..9d13143 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -469,7 +469,7 @@
//find a gun tech for this gun
const gunTechPool = []
for (let j = 0; j < tech.tech.length; j++) {
- if (tech.tech[j].isGunTech && tech.tech[j].allowed && !tech.tech[j].isJunk && !tech.tech[j].isBadRandomOption && tech.tech[j].count < tech.tech[j].maxCount) {
+ if (tech.tech[j].isGunTech && tech.tech[j].allowed() && !tech.tech[j].isJunk && !tech.tech[j].isBadRandomOption && tech.tech[j].count < tech.tech[j].maxCount) {
const regex = tech.tech[j].requires.search(b.guns[b.inventory[i]].name) //get string index of gun name
const not = tech.tech[j].requires.search(' not ') //get string index of ' not '
//look for the gun name in the requirements, but the gun name needs to show up before the word ' not '
@@ -1015,15 +1015,15 @@
},
{
name: "fragmentation",
- description: "some detonations and collisions eject nails
blocks, railgun, grenades, missiles, slugs, harpoon",
+ description: "some detonations and collisions eject nails
blocks, grenades, missiles, slugs, harpoon",
maxCount: 9,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
- return tech.haveGunCheck("harpoon") || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || tech.missileBotCount || tech.haveGunCheck("railgun") || (tech.haveGunCheck("shotgun") && tech.isSlugShot) || tech.throwChargeRate > 1
+ return tech.haveGunCheck("harpoon") || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || tech.missileBotCount || (tech.haveGunCheck("shotgun") && tech.isSlugShot) || tech.blockDamage > 0.075
},
- requires: "grenades, missiles, railgun, shotgun slugs, harpoon, or mass driver",
+ requires: "grenades, missiles, shotgun slugs, harpoon, or mass driver",
effect() {
tech.fragments++
},
@@ -1699,9 +1699,27 @@
}
}
},
+ {
+ name: "capacitor bank",
+ description: "charge effects build up almost instantly
throwing blocks, foam, railgun, pulse, tokamak",
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return tech.blockDamage > 0.075 || tech.haveGunCheck("foam") || tech.isRailGun || tech.isTokamak || tech.isPulseLaser
+ },
+ requires: "throwing blocks, foam, railgun, pulse, tokamak",
+ effect() {
+ tech.isCapacitor = true;
+ },
+ remove() {
+ tech.isCapacitor = false;
+ }
+ },
{
name: "mass driver",
- description: "charge throws more quickly for less energy
increase block collision damage by 200%",
+ description: "increase block collision damage by 300%",
maxCount: 1,
count: 0,
frequency: 1,
@@ -1711,22 +1729,22 @@
},
requires: "not wormhole",
effect() {
- tech.throwChargeRate = 3
+ tech.blockDamage = 0.3
},
remove() {
- tech.throwChargeRate = 1
+ tech.blockDamage = 0.075
}
},
{
name: "inflation",
link: `inflation`,
- description: "throwing a block expands it by 300%
increase throw charge rate by 200%",
+ description: "throwing a block expands it by 300%
holding a block reduces harm by 85%",
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
- return tech.throwChargeRate > 1 && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && m.fieldUpgrades[m.fieldMode].name !== "wormhole" && !tech.isTokamak
+ return tech.blockDamage > 0.075 && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && m.fieldUpgrades[m.fieldMode].name !== "wormhole" && !tech.isTokamak
},
requires: "mass driver, not pilot wave, tokamak, wormhole",
effect() {
@@ -1744,7 +1762,7 @@
frequency: 3,
frequencyDefault: 3,
allowed() {
- return tech.throwChargeRate > 1 && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && m.fieldUpgrades[m.fieldMode].name !== "wormhole" && !tech.isTokamak
+ return tech.blockDamage > 0.075 && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && m.fieldUpgrades[m.fieldMode].name !== "wormhole" && !tech.isTokamak
},
requires: "mass driver, not pilot wave not tokamak, wormhole",
effect() {
@@ -1762,7 +1780,7 @@
frequency: 3,
frequencyDefault: 3,
allowed() {
- return tech.throwChargeRate > 1 && !tech.nailsDeathMob && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.iceIXOnDeath
+ return tech.blockDamage > 0.075 && !tech.nailsDeathMob && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.iceIXOnDeath
},
requires: "mass driver, no other mob death tech",
effect() {
@@ -1780,7 +1798,7 @@
// frequency: 2,
// frequencyDefault: 2,
// allowed() {
- // return (tech.throwChargeRate > 1 || m.fieldUpgrades[m.fieldMode].name === "pilot wave") && !tech.isTokamak
+ // return (tech.blockDamage > 0.075 || m.fieldUpgrades[m.fieldMode].name === "pilot wave") && !tech.isTokamak
// },
// requires: "mass driver or pilot wave, not tokamak",
// effect() {
@@ -1790,24 +1808,24 @@
// tech.isBlockBullets = false
// }
// },
- {
- name: "inelastic collision",
- description: "holding a block reduces harm by 85%
increase block collision damage by 150%",
- maxCount: 1,
- count: 0,
- frequency: 3,
- frequencyDefault: 3,
- allowed() {
- return tech.throwChargeRate > 1 && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && m.fieldUpgrades[m.fieldMode].name !== "wormhole" && !tech.isEnergyHealth
- },
- requires: "mass driver, a field that can hold things, not mass-energy",
- effect() {
- tech.isBlockHarm = true
- },
- remove() {
- tech.isBlockHarm = false
- }
- },
+ // {
+ // name: "inelastic collision",
+ // description: "holding a block reduces harm by 85%
increase block collision damage by 150%",
+ // maxCount: 1,
+ // count: 0,
+ // frequency: 3,
+ // frequencyDefault: 3,
+ // allowed() {
+ // return tech.blockDamage > 0.075 && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && m.fieldUpgrades[m.fieldMode].name !== "wormhole" && !tech.isEnergyHealth
+ // },
+ // requires: "mass driver, a field that can hold things, not mass-energy",
+ // effect() {
+ // tech.isBlockHarm = true
+ // },
+ // remove() {
+ // tech.isBlockHarm = false
+ // }
+ // },
{
name: "buckling",
description: `if a block you threw kills a mob
spawn 1 ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`,
@@ -1816,7 +1834,7 @@
frequency: 3,
frequencyDefault: 3,
allowed() {
- return tech.throwChargeRate > 1 && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && !tech.isTokamak
+ return tech.blockDamage > 0.075 && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && !tech.isTokamak
},
requires: "mass driver, not pilot wave, tokamak",
effect() {
@@ -2306,7 +2324,7 @@
requires: "not mass-energy",
effect() {
tech.isPiezo = true;
- m.energy += 20.48;
+ if (simulation.isTextLogOpen) m.energy += 20.48;
},
remove() {
tech.isPiezo = false;
@@ -2342,7 +2360,7 @@
allowed() {
return !tech.isZeno && !tech.isNoHeals && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isTechDamage && !tech.isMutualism //&& !tech.isAmmoFromHealth && !tech.isRewindGun
},
- requires: "not Zeno, ergodicity, piezoelectricity, CPT, rewind gun, antiscience, mutualism",
+ requires: "not Zeno, ergodicity, piezoelectricity, CPT, antiscience, mutualism",
effect: () => {
m.health = 0
document.getElementById("health").style.display = "none"
@@ -2572,7 +2590,7 @@
},
{
name: "inductive coupling",
- description: "passive energy regen is increased by 500%
but you only regen when crouched",
+ description: "passive energy regen is increased by 600%
but you only regen when crouched",
maxCount: 1,
count: 0,
frequency: 1,
@@ -2584,7 +2602,7 @@
effect() {
tech.isCrouchRegen = true; //only used to check for requirements
m.regenEnergy = function() {
- if (m.immuneCycle < m.cycle && m.crouch) m.energy += 5 * m.fieldRegen; //m.fieldRegen = 0.001
+ if (m.immuneCycle < m.cycle && m.crouch) m.energy += 6 * m.fieldRegen; //m.fieldRegen = 0.001
if (m.energy < 0) m.energy = 0
}
},
@@ -3227,7 +3245,7 @@
effect() {
tech.duplicateChance += 0.1
powerUps.setDupChance(); //needed after adjusting duplication chance
- if (!build.isExperimentSelection) simulation.circleFlare(0.1);
+ if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.1);
this.refundAmount += tech.addJunkTechToPool(0.4)
},
refundAmount: 0,
@@ -3254,7 +3272,7 @@
effect: () => {
tech.isStimulatedEmission = true
powerUps.setDupChance(); //needed after adjusting duplication chance
- if (!build.isExperimentSelection) simulation.circleFlare(0.15);
+ if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.15);
},
remove() {
tech.isStimulatedEmission = false
@@ -3275,7 +3293,7 @@
effect: () => {
tech.isPowerUpsVanish = true
powerUps.setDupChance(); //needed after adjusting duplication chance
- if (!build.isExperimentSelection) simulation.circleFlare(0.12);
+ if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.12);
},
remove() {
tech.isPowerUpsVanish = false
@@ -3611,15 +3629,15 @@
for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "tech");
},
remove() {
- if (tech.isDeterminism) {
- tech.isDeterminism = false;
+ tech.isDeterminism = false;
+ if (this.count > 0) {
for (let i = 0; i < 5; i++) {
const numberRemoved = tech.removeTech()
if (numberRemoved === 0) { //if the player didn't remove a power up then remove 1 tech for the map
- for (let i = 0; i < powerUp.length; i++) {
- if (powerUp[i].name === "tech") {
- Matter.Composite.remove(engine.world, powerUp[i]);
- powerUp.splice(i, 1);
+ for (let j = 0; j < powerUp.length; j++) {
+ if (powerUp[j].name === "tech") {
+ Matter.Composite.remove(engine.world, powerUp[j]);
+ powerUp.splice(j, 1);
break;
}
}
@@ -4121,16 +4139,16 @@
{
name: "Noether violation",
link: `Noether violation`,
- description: "increase shotgun and railgun damage 60%
their recoil is increased and reversed",
+ description: "increase shotgun damage 60%
their recoil is increased and reversed",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
- return (tech.haveGunCheck("shotgun") || tech.haveGunCheck("railgun")) && !tech.isShotgunRecoil
+ return (tech.haveGunCheck("shotgun")) && !tech.isShotgunRecoil
},
- requires: "shotgun, railgun, not Newton's 3rd law",
+ requires: "shotgun, not Newton's 3rd law",
effect() {
tech.isShotgunReversed = true;
},
@@ -5260,7 +5278,7 @@
{
name: "unaaq",
link: `unaaq`, //https://en.wikipedia.org/wiki/Weapon
- description: "increase the length of your harpoon
by 10% of the square root of its ammo",
+ description: "increase the size of your harpoon
by 10% of the square root of its ammo",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -5316,25 +5334,25 @@
tech.extraHarpoons = 0;
}
},
- // {
- // name: "spear",
- // description: "harpoons fired while crouched
have no rope and improved steering",
- // isGunTech: true,
- // maxCount: 1,
- // count: 0,
- // frequency: 2,
- // frequencyDefault: 2,
- // allowed() {
- // return tech.haveGunCheck("harpoon") && !tech.isFilament
- // },
- // requires: "harpoon, not filament",
- // effect() {
- // tech.isSpear = true;
- // },
- // remove() {
- // tech.isSpear = false;
- // }
- // },
+ {
+ name: "railgun",
+ description: "firing the harpoon while crouched launches
a rod that is faster, larger, and more dense",
+ isGunTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return tech.haveGunCheck("harpoon")
+ },
+ requires: "railgun",
+ effect() {
+ tech.isRailGun = true;
+ },
+ remove() {
+ tech.isRailGun = false;
+ }
+ },
{
name: "half-wave rectifier",
description: "charging the railgun gives you energy
instead of draining it",
@@ -5344,9 +5362,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.haveGunCheck("railgun")
+ return tech.isRailGun
},
- requires: "railgun",
+ requires: "harpoon, railgun",
effect() {
tech.isRailEnergyGain = true;
},
@@ -5354,25 +5372,25 @@
tech.isRailEnergyGain = false;
}
},
- {
- name: "dielectric polarization",
- description: "firing the railgun damages nearby mobs",
- isGunTech: true,
- maxCount: 1,
- count: 0,
- frequency: 2,
- frequencyDefault: 2,
- allowed() {
- return tech.haveGunCheck("railgun")
- },
- requires: "railgun",
- effect() {
- tech.isRailAreaDamage = true;
- },
- remove() {
- tech.isRailAreaDamage = false;
- }
- },
+ // {
+ // name: "dielectric polarization",
+ // description: "firing the railgun damages nearby mobs",
+ // isGunTech: true,
+ // maxCount: 1,
+ // count: 0,
+ // frequency: 2,
+ // frequencyDefault: 2,
+ // allowed() {
+ // return tech.haveGunCheck("railgun")
+ // },
+ // requires: "railgun",
+ // effect() {
+ // tech.isRailAreaDamage = true;
+ // },
+ // remove() {
+ // tech.isRailAreaDamage = false;
+ // }
+ // },
// {
// name: "aerodynamic heating",
// description: "railgun rod damage nearby mobs",
@@ -5392,25 +5410,6 @@
// tech.isRodAreaDamage = false;
// }
// },
- {
- name: "capacitor bank",
- description: "the railgun no longer takes time to charge
railgun rods are 66% less massive",
- isGunTech: true,
- maxCount: 1,
- count: 0,
- frequency: 2,
- frequencyDefault: 2,
- allowed() {
- return tech.haveGunCheck("railgun")
- },
- requires: "railgun",
- effect() {
- tech.isCapacitor = true;
- },
- remove() {
- tech.isCapacitor = false;
- }
- },
{
name: "laser diode",
description: "all lasers drain 30% less energy
affects laser-gun, laser-bot, laser-mines, pulse",
@@ -6373,9 +6372,9 @@
frequency: 3,
frequencyDefault: 3,
allowed() {
- return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "time dilation") && (build.isExperimentSelection || powerUps.research.count > 2)
+ return (m.fieldUpgrades[m.fieldMode].name === "time dilation") && (build.isExperimentSelection || powerUps.research.count > 2)
},
- requires: "time dilation, pilot wave",
+ requires: "time dilation",
effect() {
tech.isFastTime = true
m.setMovement();
@@ -6421,13 +6420,13 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
- return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "time dilation" || m.fieldUpgrades[m.fieldMode].name === "metamaterial cloaking")
+ return (m.fieldUpgrades[m.fieldMode].name === "time dilation" || m.fieldUpgrades[m.fieldMode].name === "metamaterial cloaking")
},
- requires: "cloaking, time dilation, or pilot wave",
+ requires: "cloaking, time dilation",
effect() {
tech.cloakDuplication = 0.4
powerUps.setDupChance(); //needed after adjusting duplication chance
- if (!build.isExperimentSelection) simulation.circleFlare(0.4);
+ if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.4);
},
remove() {
tech.cloakDuplication = 0
@@ -6603,25 +6602,25 @@
b.setFireCD();
}
},
- {
- name: "potential well",
- description: "the force that pilot wave generates
to trap blocks is greatly increased",
- isFieldTech: true,
- maxCount: 1,
- count: 0,
- frequency: 2,
- frequencyDefault: 2,
- allowed() {
- return m.fieldUpgrades[m.fieldMode].name === "pilot wave"
- },
- requires: "pilot wave",
- effect() {
- tech.pilotForce = 0.0006
- },
- remove() {
- tech.pilotForce = 0.00002
- }
- },
+ // {
+ // name: "potential well",
+ // description: "the force that pilot wave generates
to trap blocks is greatly increased",
+ // isFieldTech: true,
+ // maxCount: 1,
+ // count: 0,
+ // frequency: 2,
+ // frequencyDefault: 2,
+ // allowed() {
+ // return m.fieldUpgrades[m.fieldMode].name === "pilot wave"
+ // },
+ // requires: "pilot wave",
+ // effect() {
+ // tech.pilotForce = 0.0006
+ // },
+ // remove() {
+ // tech.pilotForce = 0.00002
+ // }
+ // },
{
name: "WIMPs",
description: `at the end of each level spawn ${powerUps.orb.research(5)}
and a harmful particle that slowly chases you`,
@@ -6677,7 +6676,7 @@
effect() {
tech.wormDuplicate = 0.13
powerUps.setDupChance(); //needed after adjusting duplication chance
- if (!build.isExperimentSelection) simulation.circleFlare(0.13);
+ if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.13);
for (let i = 0; i < 4; i++) {
if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
}
@@ -8577,7 +8576,7 @@
},
{
name: "black hole cluster",
- description: `spawn ${powerUps.orb.research(2)}
spawn 40 nearby black holes`,
+ description: `spawn 100 nearby black holes`,
maxCount: 9,
count: 0,
frequency: 0,
@@ -8589,13 +8588,9 @@
},
requires: "",
effect() {
- for (let i = 0; i < 2; i++) powerUps.spawn(m.pos.x, m.pos.y, "research");
- const unit = {
- x: 1,
- y: 0
- }
- for (let i = 0; i < 40; i++) {
- const where = Vector.add(m.pos, Vector.mult(Vector.rotate(unit, Math.random() * 2 * Math.PI), 600 + 800 * Math.random()))
+ const unit = { x: 1, y: 0 }
+ for (let i = 0; i < 100; i++) {
+ const where = Vector.add(m.pos, Vector.mult(Vector.rotate(unit, Math.random() * 2 * Math.PI), 500 + 200 * Math.random()))
spawn.sucker(where.x, where.y)
}
},
@@ -8734,7 +8729,7 @@
isPlasmaRange: null,
isFreezeMobs: null,
isIceCrystals: null,
- throwChargeRate: null,
+ blockDamage: null,
isBlockStun: null,
isStunField: null,
isHarmDamage: null,
@@ -8832,7 +8827,7 @@
isIncendiary: null,
overfillDrain: null,
isNeutronSlow: null,
- isRailAreaDamage: null,
+ // isRailAreaDamage: null,
historyLaser: null,
isSpeedHarm: null,
isSpeedDamage: null,
@@ -8848,7 +8843,6 @@
isRewindGrenade: null,
isExtruder: null,
isEndLevelPowerUp: null,
- // isRewindGun: null,
missileSize: null,
isLaserMine: null,
isAmmoFoamSize: null,
@@ -8868,7 +8862,6 @@
is111Duplicate: null,
isDynamoBotUpgrade: null,
isBlockPowerUps: null,
- isBlockHarm: null,
foamFutureFire: null,
isDamageAfterKill: null,
isHarmReduceAfterKill: null,
@@ -8953,7 +8946,7 @@
isSpawnExitTech: null,
cloakDuplication: null,
extruderRange: null,
- isRodAreaDamage: null,
+ // isRodAreaDamage: null,
isForeverDrones: null,
isMoreMobs: null,
nailRecoil: null,
diff --git a/todo.txt b/todo.txt
index 915524a..5d93696 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,20 +1,48 @@
******************************************************** NEXT PATCH **************************************************
-tech: applied science - gives a random gun tech and a research for each gun in your inventory
+railgun is now a tech for harpoon
+ railgun tech: dielectric polarization has been removed
+unaaq increases the size not length of harpoons
-JUNK tech - motion sickness - disable camera smoothing
-JUNK tech - palantÃr - see far away
+capacitor bank applies charging effects: throwing blocks, foam, railgun, pulse, tokamak
+ fire cooldown reduction no longer effects these charging abilities, but it does reduce cooldown between discharges
-foam-bot, nail-bot, missile-bot: are now affected by fire delay tech
- this gives some options for late game bot scaling
+foam now has a short delay between each discharge
+foam charges ~10% faster
+tokamak graphics indicate charging and max charge better
+pulse laser can now regen energy passively while charging
-timelike now allows some energy regen while immune to harm in double time
-Tokamak now overrides the trajectory throw graphics with its own
+tech: mass driver no longer gives improved block charge rate,
+ but it gives 200% -> 300% damage for blocks
+tech: inflation no longer gives improved block charge rate
+ it gives harm reduction when holding a block and makes block expand when you throw them
+tech: inelastic collision was removed it used to give harm reduction when holding a block
+
+pilot wave uses 66% less energy to fling blocks
+pilot wave can fling block effectively at much higher speeds now (which happens to use much more energy)
+tech potential well is removed, because it isn't really needed anymore
+
+inductive coupling: 500% -> 600% regen while crouched
+molecular assembler now works with inductive coupling regen properly
+
+bug fixes (superdeterminism, wormhole, applied science)
+I probably added several new bugs, let me know if you find any
******************************************************** TODO ********************************************************
+tech: instead of throwing a block, give bots that last for 20 seconds
+
+tech: Occam's razor - remove 66% of your tech and guns; for each removed get 20% damage
+ remove first half of guns and tech, it's not random
+ this is going to leave field and gun tech, but also remove the first gun, which is probably the main one
+ make 20% damage additive, so it's worse with more tech
+ remove upto 66% of guns and tech
+ and 10% harm reduction?
+
tech: after bullets hit a mob, the mob takes 1% more damage
- this.damageReduction *= 1.01
+ this.damageReduction *= 1.01
+ only for drones?
+ only for drones, spores, worms, ice-IX?
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?