From 9e7e88c28d849638c7910454daf7e80bbcc50b72 Mon Sep 17 00:00:00 2001 From: landgreen Date: Sun, 14 Nov 2021 08:21:28 -0800 Subject: [PATCH] railgun -> harpoon tech railgun is now a tech for harpoon railgun tech: dielectric polarization has been removed unaaq increases the size not length of harpoons 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 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 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 --- .DS_Store | Bin 6148 -> 6148 bytes js/bullet.js | 1083 +++++++++++++++++++++++++++++--------------------- js/engine.js | 2 +- js/level.js | 19 +- js/lore.js | 6 +- js/player.js | 58 +-- js/spawn.js | 8 +- js/tech.js | 283 +++++++------ todo.txt | 44 +- 9 files changed, 865 insertions(+), 638 deletions(-) diff --git a/.DS_Store b/.DS_Store index f4b94a6aa62f3bd854578b09629f4ea5adb833e9..873fa016dfcd2108b29744a85672585f1205da44 100644 GIT binary patch delta 22 dcmZoMXffEJ#mw|YW3mpjFO%$t&DG4EA^=pz2T%Y2 delta 22 dcmZoMXffEJ#muxbZ?X=vFO%GY&DG4EA^=lC2MhoJ 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?