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?