From 33fe8faff9120e28eac0a0fba3f488d80acdd63b Mon Sep 17 00:00:00 2001 From: landgreen Date: Sat, 19 Feb 2022 13:21:33 -0800 Subject: [PATCH] railgun tech railgun - harpoon charge fires and no longer retracts, get 8x ammo from power ups railgun has auto-targeting, like harpoon the aiming graphic is gone disables filament, reticulum, toggling unlocks capacitor bank mobs do 2% less harm to player player does 0.5% more damage per level Zeno's paradox removes 1/10 -> 1/12 -> 1/14 (7%) health every 5 seconds drone gun gets 10% more ammo harpoon damage reduced by 15% random bots have a 100% -> 66% chance to match your upgraded bot type phonon has 1/8 -> 1/9 less ammo than matter wave Penrose process gain 63 -> 53 energy when wormhole eats blocks transdimensional spores makes 20% fewer spores when wormhole eats blocks bugfixes --- .DS_Store | Bin 6148 -> 6148 bytes js/bullet.js | 726 ++++++++++++++++++++++++++----------------- js/level.js | 29 +- js/player.js | 8 +- js/simulation.js | 3 +- js/spawn.js | 17 +- js/tech.js | 790 ++++++++++++++++++++++++----------------------- todo.txt | 54 +++- 8 files changed, 907 insertions(+), 720 deletions(-) diff --git a/.DS_Store b/.DS_Store index 697f9d7241c02a026c70e4f44929cb5965060813..293fb187b851b9d7cc2f568fb39f92d21e4c7339 100644 GIT binary patch delta 114 zcmZoMXffEJ$`rT#c|HRJ0}F#5LpnnyLrHGFi%U{YeiBfOo dVHlj8pIZRb!@yeSFu9p&In(EW%{t6CL;&P$BTE1P delta 114 zcmZoMXffEJ$`n^urNF?zz`~%%kj{|FP?DSP;*yk;p9B=+;Nm#&*zVL}M^yO~yz&JZ dhQZ1CxdlKy46L>nCO0!JXF8{|S%>+C2mp`u9(Di# diff --git a/js/bullet.js b/js/bullet.js index 750bbaf..7ba90f4 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -1241,7 +1241,7 @@ const b = { }, minDmgSpeed: 0, lookFrequency: Math.floor(7 + Math.random() * 3), - density: 0.001, //0.001 is normal for blocks, 0.005 is normal for harpoon, 0.035 when buffed + density: 0.001, //0.001 is normal for blocks, 0.008 is normal for harpoon, 0.008*6 when buffed beforeDmg(who) { if (tech.isShieldPierce && who.isShielded) { //disable shields who.isShielded = false @@ -1343,7 +1343,7 @@ const b = { Composite.add(engine.world, bullet[me]); //add bullet to world }, - harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 15) { + harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35) { const me = bullet.length; 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 }], { @@ -1355,16 +1355,16 @@ const b = { turnRate: isReturn ? 0.1 : 0.03, //0.015 drawStringControlMagnitude: 3000 + 5000 * Math.random(), drawStringFlip: (Math.round(Math.random()) ? 1 : -1), - dmg: 7, //damage done in addition to the damage from momentum + dmg: 6, //damage done in addition to the damage from momentum classType: "bullet", endCycle: simulation.cycle + totalCycles * 2.5 + 15, collisionFilter: { category: cat.bullet, mask: tech.isShieldPierce ? cat.map | cat.body | cat.mob | cat.mobBullet : cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield, }, - minDmgSpeed: 0, + minDmgSpeed: 4, lookFrequency: Math.floor(7 + Math.random() * 3), - density: tech.harpoonDensity, //0.001 is normal for blocks, 0.005 is normal for harpoon, 0.035 when buffed + density: tech.harpoonDensity, //0.001 is normal for blocks, 0.006 is normal for harpoon, 0.006*6 when buffed beforeDmg(who) { if (tech.isShieldPierce && who.isShielded) { //disable shields who.isShielded = false @@ -1406,7 +1406,7 @@ const b = { this.caughtPowerUp.effect(); Matter.Composite.remove(engine.world, this.caughtPowerUp); powerUp.splice(index, 1); - if (tech.isHarpoonPowerUp) tech.harpoonDensity = 0.008 * 6 //0.006 is normal + if (tech.isHarpoonPowerUp) tech.harpoonDensity = 0.006 * 6 //0.006 is normal } else { this.dropCaughtPowerUp() } @@ -1509,7 +1509,7 @@ const b = { this.force.x -= returnForce.x this.force.y -= returnForce.y this.frictionAir = 0.002 - this.do = () => { this.force.y += this.mass * 0.001; } + this.do = () => { if (this.speed < 20) this.force.y += 0.0005 * this.mass; } this.dropCaughtPowerUp() } else { //return to player this.do = this.returnToPlayer @@ -1522,7 +1522,7 @@ const b = { } } else if (this.cycle > 30) { this.frictionAir = 0.003 - this.do = () => { this.force.y += this.mass * 0.003; } + this.do = () => { if (this.speed < 20) this.force.y += 0.0005 * this.mass; } } if (target) { //rotate towards the target @@ -1583,7 +1583,7 @@ const b = { }); bullet[me].frictionAir = 0.002 bullet[me].do = function() { - this.force.y += this.mass * 0.001; //gravity + if (this.speed < 20) this.force.y += 0.0005 * this.mass; this.draw(); } } @@ -3492,43 +3492,66 @@ const b = { } }, randomBot(where = player.position, isKeep = true, isLaser = true) { - if (tech.isNailBotUpgrade) { //check for upgrades first - b.nailBot(where, isKeep) - if (isKeep) tech.nailBotCount++; - } else if (tech.isFoamBotUpgrade) { - b.foamBot(where, isKeep) - if (isKeep) tech.foamBotCount++; - } else if (tech.isBoomBotUpgrade) { - b.boomBot(where, isKeep) - if (isKeep) tech.boomBotCount++; - } else if (tech.isLaserBotUpgrade) { - b.laserBot(where, isKeep) - if (isKeep) tech.laserBotCount++; - } else if (tech.isOrbitBotUpgrade) { - b.orbitBot(where, isKeep); - if (isKeep) tech.orbitBotCount++; - } else if (tech.isDynamoBotUpgrade) { - b.dynamoBot(where, isKeep) - if (isKeep) tech.dynamoBotCount++; - } else if (Math.random() < 0.166 && isLaser) { //random - b.laserBot(where, isKeep) - if (isKeep) tech.laserBotCount++; - } else if (Math.random() < 0.2) { - b.dynamoBot(where, isKeep) - if (isKeep) tech.dynamoBotCount++; - } else if (Math.random() < 0.25) { - b.orbitBot(where, isKeep); - if (isKeep) tech.orbitBotCount++; - } else if (Math.random() < 0.33) { - b.nailBot(where, isKeep) - if (isKeep) tech.nailBotCount++; - } else if (Math.random() < 0.5) { - b.foamBot(where, isKeep) - if (isKeep) tech.foamBotCount++; - } else { - b.boomBot(where, isKeep) - if (isKeep) tech.boomBotCount++; + if (Math.random() < 0.5) { //chance to match scrap bot to your upgrade + if (tech.isNailBotUpgrade) { //check for upgrades first + b.nailBot(where, isKeep) + if (isKeep) tech.nailBotCount++; + } else if (tech.isFoamBotUpgrade) { + b.foamBot(where, isKeep) + if (isKeep) tech.foamBotCount++; + } else if (tech.isBoomBotUpgrade) { + b.boomBot(where, isKeep) + if (isKeep) tech.boomBotCount++; + } else if (tech.isLaserBotUpgrade) { + b.laserBot(where, isKeep) + if (isKeep) tech.laserBotCount++; + } else if (tech.isOrbitBotUpgrade) { + b.orbitBot(where, isKeep); + if (isKeep) tech.orbitBotCount++; + } else if (tech.isDynamoBotUpgrade) { + b.dynamoBot(where, isKeep) + if (isKeep) tech.dynamoBotCount++; + } else if (Math.random() < 0.166 && isLaser) { //random + b.laserBot(where, isKeep) + if (isKeep) tech.laserBotCount++; + } else if (Math.random() < 0.2) { + b.dynamoBot(where, isKeep) + if (isKeep) tech.dynamoBotCount++; + } else if (Math.random() < 0.25) { + b.orbitBot(where, isKeep); + if (isKeep) tech.orbitBotCount++; + } else if (Math.random() < 0.33) { + b.nailBot(where, isKeep) + if (isKeep) tech.nailBotCount++; + } else if (Math.random() < 0.5) { + b.foamBot(where, isKeep) + if (isKeep) tech.foamBotCount++; + } else { + b.boomBot(where, isKeep) + if (isKeep) tech.boomBotCount++; + } + } else { //else don't match scrap bot to upgrade + if (Math.random() < 0.166 && isLaser) { //random + b.laserBot(where, isKeep) + if (isKeep) tech.laserBotCount++; + } else if (Math.random() < 0.2) { + b.dynamoBot(where, isKeep) + if (isKeep) tech.dynamoBotCount++; + } else if (Math.random() < 0.25) { + b.orbitBot(where, isKeep); + if (isKeep) tech.orbitBotCount++; + } else if (Math.random() < 0.33) { + b.nailBot(where, isKeep) + if (isKeep) tech.nailBotCount++; + } else if (Math.random() < 0.5) { + b.foamBot(where, isKeep) + if (isKeep) tech.foamBotCount++; + } else { + b.boomBot(where, isKeep) + if (isKeep) tech.boomBotCount++; + } } + }, setDynamoBotDelay() { //reorder orbital bot positions around a circle @@ -5481,8 +5504,8 @@ const b = { name: "drones", description: "deploy drones that crash into mobs
crashes reduce their lifespan by 1 second", ammo: 0, - ammoPack: 14.5, - defaultAmmoPack: 14.5, + ammoPack: 16, + defaultAmmoPack: 16, have: false, do() {}, fire() { @@ -5581,10 +5604,148 @@ const b = { name: "harpoon", description: "fire a self-steering harpoon that uses energy
to retract and refund its ammo cost", ammo: 0, - ammoPack: 0.3, + ammoPack: 0.6, //update this in railgun tech have: false, + fire() {}, do() {}, - fire() { + chooseFireMethod() { + if (tech.isRailGun) { + this.do = this.railDo + this.fire = this.railFire + } else { + this.do = () => {} + this.fire = this.harpoonFire + } + }, + charge: 0, + railDo() { + if (this.charge > 0) { + //exit railgun charging without firing + if (m.energy < 0.005 && !tech.isRailEnergyGain) { + m.energy += 0.025 + this.charge * 0.11 + m.fireCDcycle = m.cycle + 120; // cool down if out of energy + this.endCycle = 0; + this.charge = 0 + b.refundAmmo() + return + } + //fire + if ((!input.fire && this.charge > 0.6)) { + const where = { + x: m.pos.x + 30 * Math.cos(m.angle), + y: m.pos.y + 30 * Math.sin(m.angle) + } + const closest = { + distance: 10000, + target: null + } + //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 harpoonSize = tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1 + 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.88) { //target closest mob that player is looking at and isn't too close to target + closest.distance = dist + closest.target = mob[i] + } + } + } + tech.harpoonDensity = 0.01 //0.001 is normal for blocks, 0.006 is normal for harpoon, 0.006*6 when buffed + b.harpoon(where, closest.target, m.angle, harpoonSize, false) + + //push away blocks and mobs + const range = 1200 * this.charge + for (let i = 0, len = mob.length; i < len; ++i) { //push away mobs when firing + 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.0015 * 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) { //push away blocks when firing + 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.003 * 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 + } + } + for (let i = 0, len = powerUp.length; i < len; ++i) { //push away blocks when firing + const SUB = Vector.sub(powerUp[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) * powerUp[i].mass) + powerUp[i].force.x += FORCE.x; + powerUp[i].force.y += FORCE.y - powerUp[i].mass * simulation.g * 1.5; //kick up a bit to give them some arc + } + } + + const recoil = Vector.mult(Vector.normalise(Vector.sub(where, m.pos)), input.down ? 0.03 : 0.06) + player.force.x -= recoil.x + player.force.y -= recoil.y + tech.harpoonDensity = 0.006 //0.001 is normal for blocks, 0.006 is normal for harpoon, 0.006*6 when buffed + + this.charge = 0; + } else { //charging + 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 = m.cycle + 10 //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.85 : Math.min(0.998, 0.985 * (0.98 + 0.02 * b.fireCDscale)) + if (input.down) smoothRate *= 0.995 + + this.charge = this.charge * smoothRate + 1 - smoothRate + m.energy += (this.charge - previousCharge) * (tech.isRailEnergyGain ? 0.8 : -0.3) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen + + //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(); + } + } + } + }, + railFire() { + m.fireCDcycle = m.cycle + 10 //can't fire until mouse is released + this.charge += 0.00001 + }, + harpoonFire() { const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) @@ -5595,247 +5756,10 @@ 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 harpoonSize = tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1 + const harpoonSize = (tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1) //* (input.down ? 0.7 : 1) const totalCycles = 7 * (tech.isFilament ? 1 + 0.01 * Math.min(110, this.ammo) : 1) * Math.sqrt(harpoonSize) - if (input.down) { //railgun - // if (true) { - 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; - bullet[me] = Bodies.rectangle(0, 0, 0.015, 0.0015, { //start as a small shape that can't even be seen - vertexGoal: [{ 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 }], - density: 0.03, //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 (tech.isShieldPierce && who.isShielded) { //disable shields - who.isShielded = false - requestAnimationFrame(() => { who.isShielded = true }); - } - if (who.shield && !tech.isShieldPierce) { - 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 * 13) - 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 - // if (tech.isDarts) { - // for (let i = 0; i < 5; i++) { - // b.dart(where, m.angle + 0.1 * i) - // b.dart(where, m.angle - 0.1 * i) - // } - // } - 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) { //grappling hook, not working really - // // 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 - // } - } else if (tech.extraHarpoons) { + if (tech.extraHarpoons && !input.down) { const range = 450 * (tech.isFilament ? 1 + 0.005 * Math.min(110, this.ammo) : 1) let targetCount = 0 for (let i = 0, len = mob.length; i < len; ++i) { @@ -5879,14 +5803,234 @@ const b = { } } } - b.harpoon(where, closest.target, m.angle, harpoonSize, true, totalCycles) + b.harpoon(where, closest.target, m.angle, harpoonSize, !input.down, 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) player.force.x -= recoil.x player.force.y -= recoil.y - tech.harpoonDensity = 0.008 - } + tech.harpoonDensity = 0.006 //0.001 is normal for blocks, 0.006 is normal for harpoon, 0.006*6 when buffed + }, + // railGun2() { + // const where = { + // x: m.pos.x + 30 * Math.cos(m.angle), + // y: m.pos.y + 30 * Math.sin(m.angle) + // } + // const closest = { + // distance: 10000, + // target: null + // } + // //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 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) + + // 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; + // bullet[me] = Bodies.rectangle(0, 0, 0.015, 0.0015, { //start as a small shape that can't even be seen + // vertexGoal: [{ 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 }], + // density: 0.03, //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 (tech.isShieldPierce && who.isShielded) { //disable shields + // who.isShielded = false + // requestAnimationFrame(() => { who.isShielded = true }); + // } + // if (who.shield && !tech.isShieldPierce) { + // 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 * 13) + // 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) || (!input.down && !tech.isRailGun)) { + // 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.85 : 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 ? 1 : -0.25) //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(); + // } + // } + // } + // }, }, { name: "mine", description: "toss a proximity mine that sticks to walls
refund undetonated mines on exiting a level", //fires nails at mobs within range diff --git a/js/level.js b/js/level.js index adeff64..7d348e2 100644 --- a/js/level.js +++ b/js/level.js @@ -17,20 +17,20 @@ const level = { // simulation.isHorizontalFlipped = true // m.setField("time dilation") // b.giveGuns("harpoon") - // for (let i = 0; i < 100; i++) tech.giveTech("slow light") - // tech.giveTech("tungsten carbide") + // tech.giveTech("unaaq") + // tech.giveTech("railgun") + // tech.giveTech("capacitor bank") + // tech.giveTech("half-wave rectifier") + // for (let i = 0; i < 1; i++) tech.giveTech("reticulum") // for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech"); - // tech.giveTech("tinsellated flagella") // for (let i = 0; i < 3; i++) tech.giveTech("undefined") - // tech.giveTech("decoherence") // for (let i = 10; i < tech.tech.length; i++) { tech.tech[i].isBanished = true } // powerUps.research.changeRerolls(100000) - // for (let i = 0; i < 1; i++) tech.giveTech("reticulum") // for (let i = 0; i < 2; i++) tech.giveTech("laser-bot") // tech.tech[297].frequency = 100 // m.immuneCycle = Infinity //you can't take damage - // level.difficultyIncrease(15) //30 is near max on hard //60 is near max on why + // level.difficultyIncrease(8) //30 is near max on hard //60 is near max on why // simulation.enableConstructMode() //used to build maps in testing mode // level.reactor(); // level.testing(); //not in rotation, used for testing @@ -128,30 +128,29 @@ const level = { m.dmgScale = 1; //damage done by player decreases each level simulation.accelScale = 1 //mob acceleration increases each level simulation.CDScale = 1 //mob CD time decreases each level - simulation.dmgScale = 0.375 * simulation.difficulty //damage done by mobs increases each level + simulation.dmgScale = Math.max(0.1, 0.35 * simulation.difficulty) //damage done by mobs scales with total levels simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale; }, difficultyIncrease(num = 1) { for (let i = 0; i < num; i++) { simulation.difficulty++ - m.dmgScale *= 0.92; //damage done by player decreases each level + m.dmgScale *= 0.925; //damage done by player decreases each level if (simulation.accelScale < 6) simulation.accelScale *= 1.025 //mob acceleration increases each level if (simulation.CDScale > 0.15) simulation.CDScale *= 0.965 //mob CD time decreases each level } - simulation.dmgScale = 0.375 * simulation.difficulty //damage done by mobs scales with total levels + simulation.dmgScale = Math.max(0.1, 0.35 * simulation.difficulty) //damage done by mobs scales with total levels simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale; // console.log(`CD = ${simulation.CDScale}`) }, difficultyDecrease(num = 1) { //used in easy mode for simulation.reset() for (let i = 0; i < num; i++) { simulation.difficulty-- - m.dmgScale /= 0.92; //damage done by player decreases each level + m.dmgScale /= 0.925; //damage done by player decreases each level if (simulation.accelScale > 1) simulation.accelScale /= 1.025 //mob acceleration increases each level if (simulation.CDScale < 1) simulation.CDScale /= 0.965 //mob CD time decreases each level } if (simulation.difficulty < 1) simulation.difficulty = 0; - simulation.dmgScale = 0.375 * simulation.difficulty //damage done by mobs scales with total levels - if (simulation.dmgScale < 0.1) simulation.dmgScale = 0.1; + simulation.dmgScale = Math.max(0.1, 0.35 * simulation.difficulty) //damage done by mobs scales with total levels simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) }, difficultyText() { @@ -2701,11 +2700,11 @@ const level = { if (!isSpawnedBoss) { isSpawnedBoss = true if (Math.random() < 0.33) { - for (let i = 0, len = Math.min(simulation.difficulty / 20, 5); i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false); + for (let i = 0, len = Math.min(simulation.difficulty / 20, 6); i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false); } else if (Math.random() < 0.5) { - for (let i = 0, len = Math.min(simulation.difficulty / 10, 10); i < len; ++i) spawn.sprayBoss(2400 - 150 * i, -225, 30, false) + for (let i = 0, len = Math.min(simulation.difficulty / 9, 8); i < len; ++i) spawn.sprayBoss(2400 - 150 * i, -225, 30, false) } else { - for (let i = 0, len = Math.min(simulation.difficulty / 8, 10); i < len; ++i) spawn.mineBoss(1950, -250, 50, false); + for (let i = 0, len = Math.min(simulation.difficulty / 6, 10); i < len; ++i) spawn.mineBoss(1950, -250, 50, false); } // for (let i = 0, len = 3 + simulation.difficulty / 20; i < len; ++i) spawn.mantisBoss(1487 + 300 * i, -1525, 35, false) } diff --git a/js/player.js b/js/player.js index df503f0..164af9e 100644 --- a/js/player.js +++ b/js/player.js @@ -2970,9 +2970,9 @@ const m = { Matter.Composite.remove(engine.world, body[i]); body.splice(i, 1); m.fieldRange *= 0.8 - if (tech.isWormholeEnergy) m.energy += 0.63 + if (tech.isWormholeEnergy) m.energy += 0.53 if (tech.isWormholeSpores) { //pandimensional spermia - for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) { + for (let i = 0, len = Math.ceil(2.5 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) { if (tech.isSporeWorm) { b.worm(Vector.add(m.hole.pos2, Vector.rotate({ x: m.fieldRange * 0.4, @@ -3004,9 +3004,9 @@ const m = { body.splice(i, 1); m.fieldRange *= 0.8 // if (tech.isWormholeEnergy && m.energy < m.maxEnergy * 2) m.energy = m.maxEnergy * 2 - if (tech.isWormholeEnergy && m.immuneCycle < m.cycle) m.energy += 0.63 + if (tech.isWormholeEnergy && m.immuneCycle < m.cycle) m.energy += 0.53 if (tech.isWormholeSpores) { //pandimensional spermia - for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) { + for (let i = 0, len = Math.ceil(2.5 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) { if (tech.isSporeWorm) { b.worm(Vector.add(m.hole.pos1, Vector.rotate({ x: m.fieldRange * 0.4, diff --git a/js/simulation.js b/js/simulation.js index 30b116a..a5a2f49 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -652,6 +652,7 @@ const simulation = { if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod() if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod() if (b.guns[i].name === "super balls") b.guns[i].chooseFireMethod() + if (b.guns[i].name === "harpoon") b.guns[i].chooseFireMethod() } tech.dynamoBotCount = 0; tech.nailBotCount = 0; @@ -949,7 +950,7 @@ const simulation = { if (!(m.cycle % 420)) { //once every 7 seconds if (tech.isZeno) { - m.health *= 0.9167 //remove 1/12 + m.health *= 0.93 //remove 7% m.displayHealth(); } if (tech.cyclicImmunity && m.immuneCycle < m.cycle + tech.cyclicImmunity) m.immuneCycle = m.cycle + tech.cyclicImmunity; //player is immune to damage for 60 cycles diff --git a/js/spawn.js b/js/spawn.js index 7c1e786..a4c3098 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -3532,7 +3532,7 @@ const spawn = { me.isBoss = true; me.inertia = Infinity; //no rotation // me.accelMag = 0.00008 + 0.00007 * simulation.accelScale; - me.burstFireFreq = 20 + Math.floor(20 * simulation.CDScale) + me.burstFireFreq = 22 + Math.floor(22 * simulation.CDScale) me.burstTotalPhases = 4 + Math.floor(2 / simulation.CDScale) me.noFireTotalCycles = 390 me.frictionStatic = 0; @@ -3602,10 +3602,10 @@ const spawn = { } } if (this.phaseCycle > -1) { - Matter.Body.rotate(this, 0.08) + Matter.Body.rotate(this, 0.02) for (let i = 0, len = this.vertices.length; i < len; i++) { //fire a bullet from each vertex spawn.sniperBullet(this.vertices[i].x, this.vertices[i].y, 8, 4); - const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[i])), -26) + const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[i])), -20) Matter.Body.setVelocity(mob[mob.length - 1], { x: velocity.x, y: velocity.y @@ -3683,10 +3683,10 @@ const spawn = { // this.isInvulnerable = true // this.damageReduction = 0 } else { - if (Math.abs(this.velocity.y) < 10) { + if (Math.abs(this.velocity.y) < 11) { Matter.Body.setVelocity(this, { x: this.velocity.x, y: this.velocity.y * 1.03 }); } - if (Math.abs(this.velocity.x) < 7) { + if (Math.abs(this.velocity.x) < 8) { Matter.Body.setVelocity(this, { x: this.velocity.x * 1.03, y: this.velocity.y }); } } @@ -3729,6 +3729,7 @@ const spawn = { me.explodeRange = 200 + 150 * Math.random() me.isExploding = false me.countDown = Math.ceil(4 * Math.random()) + me.isInvulnerable = true //not actually invulnerable, just prevents block + ice-9 interaction // me.onHit = function() { // this.isExploding = true @@ -3749,9 +3750,9 @@ const spawn = { this.death(); //hit player if (Vector.magnitude(Vector.sub(this.position, player.position)) < this.explodeRange) { - m.damage(0.008 * simulation.dmgScale); - const DRAIN = 0.08 * (tech.isRadioactiveResistance ? 0.25 : 1) - if (m.energy > DRAIN) m.energy -= DRAIN + m.damage(0.01 * simulation.dmgScale * (tech.isRadioactiveResistance ? 0.25 : 1)); + m.energy -= 0.1 * (tech.isRadioactiveResistance ? 0.25 : 1) + if (m.energy < 0) m.energy = 0 } // mob[i].isInvulnerable = false //make mineBoss not invulnerable ? const range = this.explodeRange + 50 //mines get a slightly larger range to explode diff --git a/js/tech.js b/js/tech.js index 91ad327..f3af3fb 100644 --- a/js/tech.js +++ b/js/tech.js @@ -2454,7 +2454,7 @@ const tech = { }, { name: "Zeno's paradox", - description: "reduce harm by 85%, but every 5 seconds
remove 1/12 of your current health", + description: "reduce harm by 85%, but every 5 seconds
remove 7% of your current health", // description: "every 5 seconds remove 1/10 of your health
reduce harm by 90%", maxCount: 1, count: 0, @@ -3654,25 +3654,6 @@ const tech = { tech.isNeedleIce = false } }, - { - name: "ceramics", - description: `needles and harpoons pierce shields
directly damaging shielded mobs`, - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.haveGunCheck("harpoon") || (tech.isNeedles || tech.isNeedleShot) - }, - requires: "nail gun, needle gun, needle-shot, harpoon", - effect() { - tech.isShieldPierce = true - }, - remove() { - tech.isShieldPierce = false - } - }, { name: "nanowires", description: `needles tunnel through blocks and map
increase needle damage by 20%`, @@ -4218,6 +4199,25 @@ const tech = { tech.isIceShot = false; } }, + { + name: "incendiary ammunition", + description: "shotgun, super balls, and drones
are loaded with explosives", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return ((m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isDroneTeleport || tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isForeverDrones && !tech.isDroneRadioactive && !tech.isDroneTeleport) || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot + }, + requires: "super balls, basic or slug shotgun, drones, not irradiated drones or burst drones", + effect() { + tech.isIncendiary = true + }, + remove() { + tech.isIncendiary = false; + } + }, { name: "supertemporal", link: `supertemporal`, @@ -4409,8 +4409,8 @@ const tech = { for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "matter wave") { b.guns[i].chooseFireMethod() - b.guns[i].ammoPack = b.guns[i].defaultAmmoPack / 8 - b.guns[i].ammo = Math.ceil(b.guns[i].ammo / 8); + b.guns[i].ammoPack = b.guns[i].defaultAmmoPack / 9 + b.guns[i].ammo = Math.ceil(b.guns[i].ammo / 9); simulation.updateGunHUD(); break } @@ -4423,7 +4423,7 @@ const tech = { tech.isLongitudinal = false; b.guns[i].chooseFireMethod() b.guns[i].ammoPack = b.guns[i].defaultAmmoPack - b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 8); + b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 9); simulation.updateGunHUD(); break } @@ -4512,6 +4512,164 @@ const tech = { } } }, + { + name: "iridium-192", + description: "explosions release gamma radiation
100% more damage, but over 4 seconds", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.explosiveRadius === 1 && !tech.isSmallExplosion && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isTokamak) + }, + requires: "an explosive damage source, not ammonium nitrate or nitroglycerin", + effect: () => { + tech.isExplodeRadio = true; //iridium-192 + }, + remove() { + tech.isExplodeRadio = false; + } + }, + { + name: "fragmentation", + description: "some detonations and collisions eject nails
blocks, grenades, missiles, slugs, harpoon", + isGunTech: true, + 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("shotgun") && tech.isSlugShot) || tech.blockDamage > 0.075 + }, + requires: "grenades, missiles, shotgun slugs, harpoon, or mass driver", + effect() { + tech.fragments++ + }, + remove() { + tech.fragments = 0 + } + }, + { + name: "ammonium nitrate", + description: "increase explosive damage by 27%
increase explosive radius by 27%", + isGunTech: true, + maxCount: 9, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() + }, + requires: "an explosive damage source, not iridium-192", + effect: () => { + tech.explosiveRadius += 0.27; + }, + remove() { + tech.explosiveRadius = 1; + } + }, + { + name: "nitroglycerin", + description: "increase explosive damage by 66%
decrease explosive radius by 33%", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() + }, + requires: "an explosive damage source, not iridium-192", + effect: () => { + tech.isSmallExplosion = true; + }, + remove() { + tech.isSmallExplosion = false; + } + }, + { + name: "acetone peroxide", + description: "increase explosive radius by 80%, but
you take 200% more harm from explosions", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + isBadRandomOption: true, + allowed() { + return tech.hasExplosiveDamageCheck() + }, + requires: "an explosive damage source", + effect: () => { + tech.isExplosionHarm = true; + }, + remove() { + tech.isExplosionHarm = false; + } + }, + { + name: "shock wave", + description: "explosions stun mobs for 1-2 seconds
decrease explosive damage by 30%", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() + }, + requires: "an explosive damage source, not iridium-192", + effect() { + tech.isExplosionStun = true; + }, + remove() { + tech.isExplosionStun = false; + } + }, + { + name: "controlled explosion", + description: `use ${powerUps.orb.research(3)} to dynamically reduce all
explosions until they do no harm`, + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return !tech.isImmuneExplosion && (build.isExperimentSelection || powerUps.research.count > 2) && (tech.haveGunCheck("missiles") || tech.isMissileField || tech.missileBotCount > 0 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb)) + }, + requires: "an explosive damage source, not electric reactive armor", + effect: () => { + tech.isSmartRadius = true; + for (let i = 0; i < 3; i++) { + if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) + } + }, + remove() { + tech.isSmartRadius = false; + if (this.count > 0) powerUps.research.changeRerolls(3) + } + }, + { + name: "electric reactive armor", + // description: "explosions do no harm
while your energy is above 98%", + description: "harm from explosions is passively reduced
by 5% for every 10 stored energy", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return !tech.isSmartRadius && !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() + }, + requires: "an explosive damage source, not iridium-192", + effect: () => { + tech.isImmuneExplosion = true; + }, + remove() { + tech.isImmuneExplosion = false; + } + }, { name: "MIRV", description: "fire +1 missile and grenade
decrease explosion radius up to 10%", @@ -4671,183 +4829,6 @@ const tech = { tech.isRadioactiveResistance = false } }, - { - name: "iridium-192", - description: "explosions release gamma radiation
100% more damage, but over 4 seconds", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.explosiveRadius === 1 && !tech.isSmallExplosion && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isTokamak) - }, - requires: "an explosive damage source, not ammonium nitrate or nitroglycerin", - effect: () => { - tech.isExplodeRadio = true; //iridium-192 - }, - remove() { - tech.isExplodeRadio = false; - } - }, - { - name: "ammonium nitrate", - description: "increase explosive damage by 27%
increase explosive radius by 27%", - isGunTech: true, - maxCount: 9, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() - }, - requires: "an explosive damage source, not iridium-192", - effect: () => { - tech.explosiveRadius += 0.27; - }, - remove() { - tech.explosiveRadius = 1; - } - }, - { - name: "nitroglycerin", - description: "increase explosive damage by 66%
decrease explosive radius by 33%", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() - }, - requires: "an explosive damage source, not iridium-192", - effect: () => { - tech.isSmallExplosion = true; - }, - remove() { - tech.isSmallExplosion = false; - } - }, - { - name: "acetone peroxide", - description: "increase explosive radius by 80%, but
you take 200% more harm from explosions", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - isBadRandomOption: true, - allowed() { - return tech.hasExplosiveDamageCheck() - }, - requires: "an explosive damage source", - effect: () => { - tech.isExplosionHarm = true; - }, - remove() { - tech.isExplosionHarm = false; - } - }, - { - name: "shock wave", - description: "explosions stun mobs for 1-2 seconds
decrease explosive damage by 30%", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 1, - frequencyDefault: 1, - allowed() { - return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() - }, - requires: "an explosive damage source, not iridium-192", - effect() { - tech.isExplosionStun = true; - }, - remove() { - tech.isExplosionStun = false; - } - }, - { - name: "controlled explosion", - description: `use ${powerUps.orb.research(3)} to dynamically reduce all
explosions until they do no harm`, - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return !tech.isImmuneExplosion && (build.isExperimentSelection || powerUps.research.count > 2) && (tech.haveGunCheck("missiles") || tech.isMissileField || tech.missileBotCount > 0 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb)) - }, - requires: "an explosive damage source, not electric reactive armor", - effect: () => { - tech.isSmartRadius = true; - for (let i = 0; i < 3; i++) { - if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) - } - }, - remove() { - tech.isSmartRadius = false; - if (this.count > 0) powerUps.research.changeRerolls(3) - } - }, - { - name: "electric reactive armor", - // description: "explosions do no harm
while your energy is above 98%", - description: "harm from explosions is passively reduced
by 5% for every 10 stored energy", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return !tech.isSmartRadius && !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() - }, - requires: "an explosive damage source, not iridium-192", - effect: () => { - tech.isImmuneExplosion = true; - }, - remove() { - tech.isImmuneExplosion = false; - } - }, - { - name: "incendiary ammunition", - description: "shotgun, super balls, and drones
are loaded with explosives", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 1, - frequencyDefault: 1, - allowed() { - return ((m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isDroneTeleport || tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isForeverDrones && !tech.isDroneRadioactive && !tech.isDroneTeleport) || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot - }, - requires: "super balls, basic or slug shotgun, drones, not irradiated drones or burst drones", - effect() { - tech.isIncendiary = true - }, - remove() { - tech.isIncendiary = false; - } - }, - { - name: "fragmentation", - description: "some detonations and collisions eject nails
blocks, grenades, missiles, slugs, harpoon", - isGunTech: true, - 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("shotgun") && tech.isSlugShot) || tech.blockDamage > 0.075 - }, - requires: "grenades, missiles, shotgun slugs, harpoon, or mass driver", - effect() { - tech.fragments++ - }, - remove() { - tech.fragments = 0 - } - }, { name: "booby trap", description: "drop a mine after picking up a power up
+53% JUNK to the potential tech pool", @@ -5108,41 +5089,6 @@ const tech = { tech.isBulletsLastLonger = 1; } }, - { - name: "fault tolerance", - description: "spawn 8 drones that last forever
remove your drone gun", - isGunTech: true, - isRemoveGun: true, - maxCount: 1, - count: 0, - frequency: 1, - frequencyDefault: 1, - allowed() { - return tech.haveGunCheck("drones", false) && !tech.isDroneRespawn && tech.isBulletsLastLonger === 1 - }, - requires: "drones, not drone repair, anti-shear topology", - effect() { - const num = 8 - tech.isForeverDrones += num - if (tech.haveGunCheck("drones", false)) b.removeGun("drones") - //spawn drones - if (tech.isDroneRadioactive) { - for (let i = 0; i < num * 0.25; i++) { - b.droneRadioactive({ x: m.pos.x + 30 * (Math.random() - 0.5), y: m.pos.y + 30 * (Math.random() - 0.5) }, 5) - bullet[bullet.length - 1].endCycle = Infinity - } - } else { - for (let i = 0; i < num; i++) { - b.drone({ x: m.pos.x + 30 * (Math.random() - 0.5), y: m.pos.y + 30 * (Math.random() - 0.5) }, 5) - bullet[bullet.length - 1].endCycle = Infinity - } - } - }, - remove() { - tech.isForeverDrones = 0 - if (this.count && !tech.haveGunCheck("drones", false)) b.giveGuns("drones") - } - }, { name: "reduced tolerances", link: `reduced tolerances`, @@ -5328,23 +5274,71 @@ const tech = { } }, { - name: "capacitor bank", - // description: "charge effects build up almost instantly
throwing blocks, foam, railgun, pulse, tokamak", - descriptionFunction() { return `charge effects build up almost instantly
throwing blocks, ${tech.haveGunCheck("foam", false) ? "foam" : "foam"}, ${tech.haveGunCheck("harpoon", false) ? "railgun" : "railgun"}, ${tech.isPulseLaser ? "pulse" : "pulse"}, ${tech.isTokamak ? "tokamak" : "tokamak"}` }, + name: "fault tolerance", + description: "spawn 8 drones that last forever
remove your drone gun", isGunTech: true, + isRemoveGun: true, maxCount: 1, count: 0, - frequency: 2, - frequencyDefault: 2, + frequency: 1, + frequencyDefault: 1, allowed() { - return tech.blockDamage > 0.075 || tech.haveGunCheck("foam") || tech.isTokamak || tech.isPulseLaser + return tech.haveGunCheck("drones", false) && !tech.isDroneRespawn && tech.isBulletsLastLonger === 1 }, - requires: "throwing blocks, foam, pulse, tokamak", + requires: "drones, not drone repair, anti-shear topology", effect() { - tech.isCapacitor = true; + const num = 8 + tech.isForeverDrones += num + if (tech.haveGunCheck("drones", false)) b.removeGun("drones") + //spawn drones + if (tech.isDroneRadioactive) { + for (let i = 0; i < num * 0.25; i++) { + b.droneRadioactive({ x: m.pos.x + 30 * (Math.random() - 0.5), y: m.pos.y + 30 * (Math.random() - 0.5) }, 5) + bullet[bullet.length - 1].endCycle = Infinity + } + } else { + for (let i = 0; i < num; i++) { + b.drone({ x: m.pos.x + 30 * (Math.random() - 0.5), y: m.pos.y + 30 * (Math.random() - 0.5) }, 5) + bullet[bullet.length - 1].endCycle = Infinity + } + } }, remove() { - tech.isCapacitor = false; + tech.isForeverDrones = 0 + if (this.count && !tech.haveGunCheck("drones", false)) b.giveGuns("drones") + } + }, + { + name: "surfactant", + description: "trade your foam gun for 2 foam-bots
and upgrade all bots to foam
", + isGunTech: true, + isRemoveGun: true, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + isBot: true, + isBotTech: true, + isNonRefundable: true, + requires: "foam gun, NOT EXPERIMENT MODE, bot upgrades, fractionation, quantum foam", + allowed() { + return tech.haveGunCheck("foam", false) && !b.hasBotUpgrade() && !tech.isAmmoFoamSize && !tech.foamFutureFire + }, + effect() { + tech.giveTech("foam-bot upgrade") + for (let i = 0; i < 2; i++) { + b.foamBot() + tech.foamBotCount++; + } + simulation.makeTextLog(`tech.isFoamBotUpgrade = true`) + if (tech.haveGunCheck("foam", false)) b.removeGun("foam") + }, + remove() { + // if (this.count) { + // b.clearPermanentBots(); + // b.respawnBots(); + // if (!tech.haveGunCheck("foam")) b.giveGuns("foam") + // } } }, { @@ -5464,152 +5458,63 @@ const tech = { } }, { - name: "surfactant", - description: "trade your foam gun for 2 foam-bots
and upgrade all bots to foam
", + name: "capacitor bank", + // description: "charge effects build up almost instantly
throwing blocks, foam, railgun, pulse, tokamak", + descriptionFunction() { return `charge effects build up almost instantly
throwing blocks, ${tech.haveGunCheck("foam", false) ? "foam" : "foam"}, ${tech.isRailGun ? "railgun" : "railgun"}, ${tech.isPulseLaser ? "pulse" : "pulse"}, ${tech.isTokamak ? "tokamak" : "tokamak"}` }, isGunTech: true, - isRemoveGun: true, maxCount: 1, count: 0, - frequency: 1, - frequencyDefault: 1, - isBot: true, - isBotTech: true, - isNonRefundable: true, - requires: "foam gun, NOT EXPERIMENT MODE, bot upgrades, fractionation, quantum foam", + frequency: 2, + frequencyDefault: 2, allowed() { - return tech.haveGunCheck("foam", false) && !b.hasBotUpgrade() && !tech.isAmmoFoamSize && !tech.foamFutureFire + return tech.blockDamage > 0.075 || tech.isRailGun || tech.haveGunCheck("foam") || tech.isTokamak || tech.isPulseLaser }, + requires: "throwing blocks, railgun, foam, pulse, tokamak", effect() { - tech.giveTech("foam-bot upgrade") - for (let i = 0; i < 2; i++) { - b.foamBot() - tech.foamBotCount++; + tech.isCapacitor = true; + }, + remove() { + tech.isCapacitor = false; + } + }, + { + name: "railgun", + description: `harpoons are 66% denser, but don't retract
gain 600% more harpoon ammo per ${powerUps.orb.ammo(1)}`, + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.extraHarpoons && !tech.isHarpoonPowerUp + }, + requires: "harpoon, not filament, reticulum, toggling harpoon", + ammoBonus: 6, + effect() { + tech.isRailGun = true; + for (i = 0, len = b.guns.length; i < len; i++) { //find which gun + if (b.guns[i].name === "harpoon") { + b.guns[i].chooseFireMethod() + b.guns[i].ammoPack = this.ammoBonus; + b.guns[i].ammo = b.guns[i].ammo * this.ammoBonus; + simulation.updateGunHUD(); + break + } } - simulation.makeTextLog(`tech.isFoamBotUpgrade = true`) - if (tech.haveGunCheck("foam", false)) b.removeGun("foam") }, remove() { - // if (this.count) { - // b.clearPermanentBots(); - // b.respawnBots(); - // if (!tech.haveGunCheck("foam")) b.giveGuns("foam") - // } - } - }, - { - name: "filament", - description: "increase the length of your harpoon's rope
by 1% per harpoon ammo", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.haveGunCheck("harpoon") - }, - requires: "harpoon", - effect() { - tech.isFilament = true; - }, - remove() { - tech.isFilament = false; - } - }, - { - name: "unaaq", - link: `unaaq`, //https://en.wikipedia.org/wiki/Weapon - description: "increase the size of your harpoon
by 10% of the square root of harpoon ammo", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.haveGunCheck("harpoon") - }, - requires: "harpoon", - effect() { - tech.isLargeHarpoon = true; - }, - remove() { - tech.isLargeHarpoon = false; - } - }, - { - name: "toggling harpoon", - description: "increase the damage of your next harpoon
by 600% after using it to collect a power up", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.haveGunCheck("harpoon") - }, - requires: "harpoon", - effect() { - tech.isHarpoonPowerUp = true - }, - remove() { - tech.isHarpoonPowerUp = false - tech.harpoonDensity = 0.008 - } - }, - { - name: "reticulum", - description: "fire +1 harpoon, but energy cost
to retract also increases", - isGunTech: true, - maxCount: 9, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.haveGunCheck("harpoon") - }, - requires: "harpoon", - effect() { - tech.extraHarpoons++; - }, - remove() { - tech.extraHarpoons = 0; - } - }, - // { - // 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: "harpoons drain no energy as they retract
crouch firing harpoon generates energy", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.haveGunCheck("harpoon") - }, - requires: "railgun", - effect() { - tech.isRailEnergyGain = true; - }, - remove() { - tech.isRailEnergyGain = false; + if (tech.isRailGun) { + tech.isRailGun = false; + for (i = 0, len = b.guns.length; i < len; i++) { //find which gun + if (b.guns[i].name === "harpoon") { + b.guns[i].chooseFireMethod() + b.guns[i].ammoPack = 0.6; + b.guns[i].ammo = Math.ceil(b.guns[i].ammo / this.ammoBonus); + simulation.updateGunHUD(); + break + } + } + } } }, // { @@ -5650,6 +5555,122 @@ const tech = { // tech.isRodAreaDamage = false; // } // }, + { + name: "half-wave rectifier", + description: "harpoons drain no energy as they retract
crouch firing harpoon generates energy", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("harpoon") + }, + requires: "railgun", + effect() { + tech.isRailEnergyGain = true; + }, + remove() { + tech.isRailEnergyGain = false; + } + }, + { + name: "ceramics", + description: `needles and harpoons pierce shields
directly damaging shielded mobs`, + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("harpoon") || (tech.isNeedles || tech.isNeedleShot) + }, + requires: "nail gun, needle gun, needle-shot, harpoon", + effect() { + tech.isShieldPierce = true + }, + remove() { + tech.isShieldPierce = false + } + }, + { + name: "unaaq", + link: `unaaq`, //https://en.wikipedia.org/wiki/Weapon + description: "increase the size of your harpoon
by 10% of the square root of harpoon ammo", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("harpoon") + }, + requires: "harpoon", + effect() { + tech.isLargeHarpoon = true; + }, + remove() { + tech.isLargeHarpoon = false; + } + }, + { + name: "filament", + description: "increase the length of your harpoon's rope
by 1% per harpoon ammo", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("harpoon") && !tech.isRailGun + }, + requires: "harpoon", + effect() { + tech.isFilament = true; + }, + remove() { + tech.isFilament = false; + } + }, + { + name: "toggling harpoon", + description: "increase the damage of your next harpoon
by 600% after using it to collect a power up", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("harpoon") && !tech.isRailGun + }, + requires: "harpoon", + effect() { + tech.isHarpoonPowerUp = true + }, + remove() { + tech.isHarpoonPowerUp = false + tech.harpoonDensity = 0.006 + } + }, + { + name: "reticulum", + description: "fire +1 harpoon, but energy cost
to retract also increases", + isGunTech: true, + maxCount: 9, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("harpoon") && !tech.isRailGun + }, + requires: "harpoon", + effect() { + tech.extraHarpoons++; + }, + remove() { + tech.extraHarpoons = 0; + } + }, { name: "optical amplifier", description: "gain 3 random laser guntech
laser only turns off if you have no energy", @@ -6954,7 +6975,7 @@ const tech = { }, { name: "virtual particles", - description: `use ${powerUps.orb.research(4)}to exploit your wormhole for a
13% chance to duplicate spawned power ups`, + description: `use ${powerUps.orb.research(4)}to exploit your wormhole for a
12% chance to duplicate spawned power ups`, isFieldTech: true, maxCount: 1, count: 0, @@ -6965,7 +6986,7 @@ const tech = { }, requires: "wormhole", effect() { - tech.wormDuplicate = 0.13 + tech.wormDuplicate = 0.12 powerUps.setDupChance(); //needed after adjusting duplication chance if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.13); for (let i = 0; i < 4; i++) { @@ -6980,7 +7001,7 @@ const tech = { }, { name: "Penrose process", - description: "after a block falls into a wormhole
you gain 63 energy", + description: "after a block falls into a wormhole
you gain 53 energy", isFieldTech: true, maxCount: 1, count: 0, @@ -9309,4 +9330,5 @@ const tech = { extraSuperBalls: null, isTimeCrystals: null, isGroundState: null, + isRailGun: null } \ No newline at end of file diff --git a/todo.txt b/todo.txt index 530b9fe..bb9cea6 100644 --- a/todo.txt +++ b/todo.txt @@ -1,29 +1,47 @@ ******************************************************** NEXT PATCH ************************************************** -new reactor boss - mineBoss - 1/3 chance for 1 of 3 different bosses to spawn on the reactor level +tech railgun - harpoon charge fires and no longer retracts, get 8x ammo from power ups + railgun has auto-targeting, like harpoon + the aiming graphic is gone + disables filament, reticulum, toggling + unlocks capacitor bank -harpoon starts with 10->3 ammo, and still gets 1 ammo per powerUpx -network effect damage per bot 7->6% -perimeter defense harm reduction 8->7% +mobs do 2% less harm to player +player does 0.5% more damage per level +Zeno's paradox removes 1/10 -> 1/12 -> 1/14 (7%) health every 5 seconds +drone gun gets 10% more ammo -bug fix decoherence +harpoon damage reduced by 15% +random bots have a 100% -> 66% chance to match your upgraded bot type +phonon has 1/8 -> 1/9 less ammo than matter wave +Penrose process gain 63 -> 53 energy when wormhole eats blocks +transdimensional spores makes 20% fewer spores when wormhole eats blocks + +bugfixes ******************************************************** TODO ******************************************************** +tech: when this tech is ejected spawn one of every power up type + JUNK tech? + +railgun feels like a downgrade from harpoon + buff railgun + increase harpoon size + nerf harpoon + shrink crouch mode harpoon size + + +try to get grappling hook working again + +bug - does any url sharing work? + +setting to remove UI, except health bar + except active gun? to see ammo + checkbox in pause and in settings + +damage for each different bot type you have disables bot upgrades? -improve rail gun / use ammo to crouch fire style for harpoon - spend ammo to get some tech - ammo cost on reticulum - spend ammo to make harpoon radioactive - tech disables filament and unaaq? probably don't need to - give rail gun the auto targeting - improve auto-target with a tech? - you already tried this and target probably can't get better - try to get grappling hook working again - tech doing damage refunds up to 50% of damage take in last 10 seconds use history[] to manage this? @@ -42,7 +60,9 @@ make a seed/hash system that controls only the tech/guns/fields shown tech upgrade to anthropic principle to make it trigger at 50% life and 0% once per map -JUNK tech: https://bindingofisaacrebirth.fandom.com/wiki/Damocles +tech: spontaneous collapse - very low chance of something to occur + JUNK tech + https://bindingofisaacrebirth.fandom.com/wiki/Damocles cloaking field doesn't show energy over max