diff --git a/js/bullet.js b/js/bullet.js index dd63469..ae671f7 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -1688,7 +1688,7 @@ const b = { }); Composite.add(engine.world, bullet[me]); //add bullet to world }, - harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true) { + harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) { 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 }], { @@ -1696,7 +1696,7 @@ const b = { angle: angle, friction: 1, frictionAir: 0.4, - thrustMag: 0.1, + // thrustMag: 0.1, drain: tech.isRailEnergy ? 0.001 : 0.006, turnRate: isReturn ? 0.1 : 0.03, //0.015 drawStringControlMagnitude: 3000 + 5000 * Math.random(), @@ -1808,7 +1808,7 @@ const b = { if (m.energy < 0.05) { m.fireCDcycle = m.cycle + 120; //fire cooldown } else if (m.cycle + 25 * b.fireCDscale < m.fireCDcycle) { - m.fireCDcycle = m.cycle + 35 * b.fireCDscale //lower cd to 25 if it is above 25 + m.fireCDcycle = m.cycle + 25 * b.fireCDscale //lower cd to 25 if it is above 25 } //recoil on catching const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (input.down ? 0.0001 : 0.0002)) @@ -1828,7 +1828,7 @@ const b = { if (m.energy > this.drain) m.energy -= this.drain const sub = Vector.sub(this.position, m.pos) const rangeScale = 1 + 0.000001 * Vector.magnitude(sub) * Vector.magnitude(sub) //return faster when far from player - const returnForce = Vector.mult(Vector.normalise(sub), rangeScale * this.thrustMag * this.mass) + const returnForce = Vector.mult(Vector.normalise(sub), rangeScale * thrust * this.mass) this.force.x -= returnForce.x this.force.y -= returnForce.y this.grabPowerUp() @@ -1850,7 +1850,7 @@ const b = { Matter.Body.setPosition(powerUp[i], this.vertices[2]) powerUp[i].collisionFilter.category = 0 powerUp[i].collisionFilter.mask = 0 - this.thrustMag *= 0.6 + thrust *= 0.6 this.endCycle += 0.5 //it pulls back slower, so this prevents it from ending early break //just pull 1 power up if possible } @@ -1887,16 +1887,16 @@ const b = { Matter.Body.rotate(this, -this.turnRate); } } - this.force.x += this.thrustMag * this.mass * Math.cos(this.angle); - this.force.y += this.thrustMag * this.mass * Math.sin(this.angle); + this.force.x += thrust * this.mass * Math.cos(this.angle); + this.force.y += thrust * this.mass * Math.sin(this.angle); } this.draw() }, }); if (!isReturn && !target) { Matter.Body.setVelocity(bullet[me], { - x: m.Vx / 2 + 60 * Math.cos(bullet[me].angle), - y: m.Vy / 2 + 60 * Math.sin(bullet[me].angle) + x: m.Vx / 2 + 600 * thrust * Math.cos(bullet[me].angle), + y: m.Vy / 2 + 600 * thrust * Math.sin(bullet[me].angle) }); bullet[me].frictionAir = 0.002 bullet[me].do = function() { @@ -6790,7 +6790,7 @@ const b = { } //fire if ((!input.fire && this.charge > 0.6)) { - tech.harpoonDensity = 0.0065 //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed + // tech.harpoonDensity = 0.0065 //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) @@ -6800,25 +6800,27 @@ const b = { target: null } //push away blocks and mobs - const range = 1200 * this.charge + const range = 600 + 500 * 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 + mob[i].radius) { - const DEPTH = 100 + Math.min(range - DISTANCE + mob[i].radius, 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; + if (!mob[i].isUnblockable) { + const SUB = Vector.sub(mob[i].position, m.pos) + const DISTANCE = Vector.magnitude(SUB) + if (DISTANCE < range + mob[i].radius) { + const DEPTH = 100 + Math.min(range - DISTANCE + mob[i].radius, 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; - let dmg = m.dmgScale * (mob[i].isDropPowerUp ? 0.1 : 0.4) - simulation.drawList.push({ //add dmg to draw queue - x: mob[i].position.x, - y: mob[i].position.y, - radius: Math.log(dmg + 1.1) * 40 * mob[i].damageReduction + 3, - color: 'rgba(100, 0, 200, 0.2)', - time: 15 - }); - mob[i].damage(dmg); + let dmg = m.dmgScale * (mob[i].isDropPowerUp ? 350 : 1100) * tech.harpoonDensity * this.charge + simulation.drawList.push({ //add dmg to draw queue + x: mob[i].position.x, + y: mob[i].position.y, + radius: Math.log(dmg + 1.1) * 40 * mob[i].damageReduction + 3, + color: 'rgba(100, 0, 200, 0.4)', + time: 15 + }); + mob[i].damage(dmg); + } } } for (let i = 0, len = body.length; i < len; ++i) { //push away blocks when firing @@ -6841,13 +6843,26 @@ const b = { powerUp[i].force.y += FORCE.y - powerUp[i].mass * simulation.g * 1.5; //kick up a bit to give them some arc } } + //draw little dots near the edge of range + for (let i = 0, len = 10 + 25 * this.charge; i < len; i++) { + const unit = Vector.rotate({ x: 1, y: 0 }, 6.28 * Math.random()) + const where = Vector.add(m.pos, Vector.mult(unit, range * (0.6 + 0.3 * Math.random()))) + simulation.drawList.push({ + x: where.x, + y: where.y, + radius: 5 + 12 * Math.random(), + color: "rgba(100, 0, 200, 0.1)", + time: Math.floor(5 + 35 * Math.random()) + }); + } 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.0065 //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed + // tech.harpoonDensity = 0.0065 //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed const harpoonSize = tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1 + const thrust = 0.15 * (this.charge) if (tech.extraHarpoons) { let targetCount = 0 const SPREAD = 0.06 + 0.05 * (!input.down) @@ -6861,7 +6876,7 @@ const b = { if (dot > 0.95 - Math.min(dist * 0.00015, 0.3)) { //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 > -1) { // this.ammo-- - b.harpoon(where, input.down ? null : mob[i], angle, harpoonSize, false) //Vector.angle(Vector.sub(where, mob[i].position), { x: 0, y: 0 }) + b.harpoon(where, input.down ? null : mob[i], angle, harpoonSize, false, 35, false, thrust) //harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) { angle += SPREAD targetCount++ if (targetCount > tech.extraHarpoons) break @@ -6873,14 +6888,10 @@ const b = { if (targetCount < tech.extraHarpoons + 1) { const num = tech.extraHarpoons + 1 - targetCount for (let i = 0; i < num; i++) { - // if (this.ammo > -1) { - // this.ammo-- - b.harpoon(where, null, angle, harpoonSize, false) + b.harpoon(where, null, angle, harpoonSize, false, 35, false, thrust) angle += SPREAD - // } } } - // this.ammo++ //make up for the ammo used up in fire() simulation.updateGunHUD(); } else { //look for closest mob in player's LoS @@ -6895,7 +6906,7 @@ const b = { } } } - b.harpoon(where, input.down ? null : closest.target, m.angle, harpoonSize, false) + b.harpoon(where, closest.target, m.angle, harpoonSize, false, 35, false, thrust) } this.charge = 0; @@ -6909,13 +6920,18 @@ const b = { 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 + // const previousCharge = this.charge - this.charge = this.charge * smoothRate + 1 - smoothRate + //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)) + const rate = Math.sqrt(b.fireCDscale) * tech.railChargeRate * (tech.isCapacitor ? 0.6 : 1) * (input.down ? 0.8 : 1) + let smoothRate = Math.min(0.998, 0.94 + 0.05 * rate) + + + this.charge = 1 - smoothRate + this.charge * smoothRate if (m.energy > DRAIN) m.energy -= DRAIN + + // console.log((this.charge).toFixed(2)) // m.energy += (this.charge - previousCharge) * ((tech.isRailEnergy ? 0.5 : -0.3)) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen //draw magnetic field @@ -6936,9 +6952,11 @@ const b = { X, Y) } ctx.fillStyle = `rgba(50,0,100,0.05)`; + const magSize = 8 * this.charge * tech.railChargeRate ** 3 + const arcSize = 6 * this.charge * tech.railChargeRate ** 3 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()) + const MAG = magSize * i * i * (0.93 + 0.07 * Math.random()) + const ARC = arcSize * i * i * (0.93 + 0.07 * Math.random()) ctx.beginPath(); magField(MAG, ARC) magField(MAG, -ARC) @@ -6990,13 +7008,13 @@ const b = { } //look for closest mob in player's LoS const harpoonSize = (tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1) //* (input.down ? 0.7 : 1) - const totalCycles = 5 * (tech.isFilament ? 1 + 0.012 * Math.min(110, this.ammo) : 1) * Math.sqrt(harpoonSize) + const totalCycles = 6 * (tech.isFilament ? 1 + 0.012 * Math.min(110, this.ammo) : 1) * Math.sqrt(harpoonSize) if (tech.extraHarpoons && !input.down) { //multiple harpoons const SPREAD = 0.1 let angle = m.angle - SPREAD * tech.extraHarpoons / 2; const dir = { x: Math.cos(angle), y: Math.sin(angle) }; //make a vector for the player's direction of length 1; used in dot product - const range = 450 * (tech.isFilament ? 1 + 0.006 * Math.min(110, this.ammo) : 1) + const range = 450 * (tech.isFilament ? 1 + 0.012 * Math.min(110, this.ammo) : 1) let targetCount = 0 for (let i = 0, len = mob.length; i < len; ++i) { if (mob[i].alive && !mob[i].isBadTarget && !mob[i].shield && Matter.Query.ray(map, m.pos, mob[i].position).length === 0 && !mob[i].isInvulnerable) { @@ -7036,9 +7054,8 @@ const b = { } this.ammo++ //make up for the ammo used up in fire() simulation.updateGunHUD(); - m.fireCDcycle = m.cycle + 90 // cool down - } else { - //single harpoon + m.fireCDcycle = m.cycle + 90 // cool down is set when harpoon bullet returns to player + } else { //input.down makes a single harpoon with longer range 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 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 && !mob[i].isInvulnerable) { @@ -7055,7 +7072,7 @@ const b = { } else { b.harpoon(where, closest.target, m.angle, harpoonSize, true, totalCycles) } - m.fireCDcycle = m.cycle + 45 // cool down + m.fireCDcycle = m.cycle + 45 // cool down is set when harpoon bullet returns to player tech.harpoonDensity = 0.004 //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed } const recoil = Vector.mult(Vector.normalise(Vector.sub(where, m.pos)), input.down ? 0.015 : 0.035) diff --git a/js/engine.js b/js/engine.js index 6fdcd87..5944323 100644 --- a/js/engine.js +++ b/js/engine.js @@ -154,7 +154,7 @@ function collisionChecks(event) { m.damage(dmg); //normal damage } - if (tech.isCollisionRealitySwitch) { + if (tech.isCollisionRealitySwitch && m.alive) { m.switchWorlds() simulation.trails() simulation.makeTextLog(`simulation.amplitude = ${Math.random()}`); diff --git a/js/index.js b/js/index.js index 5b915d9..070d780 100644 --- a/js/index.js +++ b/js/index.js @@ -963,7 +963,7 @@ window.addEventListener("keyup", function(event) { }); window.addEventListener("keydown", function(event) { - console.log(event.code) + // console.log(event.code) switch (event.code) { case input.key.right: case "ArrowRight": diff --git a/js/level.js b/js/level.js index dbc96db..13e26b6 100644 --- a/js/level.js +++ b/js/level.js @@ -18,30 +18,31 @@ const level = { // simulation.enableConstructMode() //used to build maps in testing mode // simulation.isHorizontalFlipped = true // tech.giveTech("performance") - // level.difficultyIncrease(2 * 4) //30 is near max on hard //60 is near max on why + // level.difficultyIncrease(15 * 4) //30 is near max on hard //60 is near max on why // m.maxHealth = m.health = 100 // tech.isRerollDamage = true - // powerUps.research.changeRerolls(50) + // powerUps.research.changeRerolls(1000) // m.immuneCycle = Infinity //you can't take damage // tech.tech[297].frequency = 100 // m.couplingChange(5) - // m.setField("time dilation") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass pilot wave + // m.setField("plasma torch") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass pilot wave plasma torch // simulation.molecularMode = 2 // m.damage(0.1); // b.giveGuns("harpoon") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser - // b.guns[9].ammo = 10000 - // tech.giveTech("startle response") - // for (let i = 0; i < 1; ++i) tech.giveTech("junk DNA") + // b.guns[0].ammo = 10000 + // tech.giveTech("plasma ball") // tech.giveTech("dye laser") - // for (let i = 0; i < 1; ++i) tech.giveTech("grappling hook") - // for (let i = 0; i < 5; i++) tech.giveTech("laser-bot") + // for (let i = 0; i < 1; ++i) tech.giveTech("railgun") + // for (let i = 0; i < 3; ++i) tech.giveTech("Bitter electromagnet") + // for (let i = 0; i < 1; i++) tech.giveTech("capacitor bank") + // for (let i = 0; i < 9; i++) tech.giveTech("heuristics") // for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); // level.testing(); - // spawn.starter(1900, -500, 200) + // spawn.shooter(1900, -500, 200) // spawn.starter(1900, -500) // spawn.timeBoss(2538, -950) // for (let i = 0; i < 5; ++i) spawn.sniper(1000 + 5000 * Math.random(), -500 + 300 * Math.random()) @@ -66,7 +67,7 @@ const level = { // level.null() // localSettings.isHuman = true // tech.isNoDraftPause = false //disable pause - // mobs.mobDeaths = 200 + // mobs.mobDeaths = 200 //to prevent pacifist mode // for (let i = 0; i < 13; i++) level.nextLevel(); //jump to final boss // lore.unlockTesting(); @@ -101,6 +102,11 @@ const level = { b.inventoryGun = tech.buffedGun; simulation.switchGun(); } + if (tech.isGunChoice && Number.isInteger(tech.buffedGun) && b.inventory.length) { + var gun = b.guns[b.inventory[tech.buffedGun]].name + simulation.makeTextLog(`pigeonhole principle: +${(31 * Math.max(0, b.inventory.length)).toFixed(0)}% damage for ${gun}`, 600); + } + if (tech.isForeverDrones) { if (tech.isDroneRadioactive) { @@ -119,8 +125,7 @@ const level = { tech.healMaxEnergyBonus += 0.1 * powerUps.totalPowerUps //Math.min(0.02 * powerUps.totalPowerUps, 0.51) m.setMaxEnergy(); } - if (tech.isSwitchReality && powerUps.research.count > 0) { - powerUps.research.changeRerolls(-1); + if (tech.isSwitchReality) { simulation.makeTextLog(`simulation.amplitude = ${Math.random()}`); m.switchWorlds() simulation.trails() @@ -162,7 +167,8 @@ const level = { if (tech.isSpawnExitTech) { for (let i = 0; i < 2; i++) powerUps.spawn(level.exit.x + 10 * (Math.random() - 0.5), level.exit.y - 100 + 10 * (Math.random() - 0.5), "tech", false) //exit } - if (m.plasmaBall) m.plasmaBall.reset() + // if (m.plasmaBall) m.plasmaBall.reset() + if (m.plasmaBall) m.plasmaBall.fire() if (localSettings.entanglement && localSettings.entanglement.levelName === level.levels[level.onLevel]) { const flip = localSettings.entanglement.isHorizontalFlipped === simulation.isHorizontalFlipped ? 1 : -1 powerUps.directSpawn(flip * localSettings.entanglement.position.x, localSettings.entanglement.position.y, "entanglement", false); diff --git a/js/mob.js b/js/mob.js index 4759662..f460689 100644 --- a/js/mob.js +++ b/js/mob.js @@ -342,12 +342,6 @@ const mobs = { this.seePlayer.position.y = player.position.y; } }, - // alwaysSeePlayerIfRemember() { - // if (!m.isCloak && this.seePlayer.recall) { - // this.seePlayer.position.x = player.position.x; - // this.seePlayer.position.y = player.position.y; - // } - // }, seePlayerByHistory(depth = 30) { //depth max 60? limit of history if (!(simulation.cycle % this.seePlayerFreq)) { if (Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 && !m.isCloak) { @@ -1255,12 +1249,12 @@ const mobs = { } if (tech.isBotSpawnerReset) { for (let i = 0, len = bullet.length; i < len; i++) { - if (bullet[i].botType && bullet[i].endCycle !== Infinity) bullet[i].endCycle = simulation.cycle + 840 //14 seconds + if (bullet[i].botType && bullet[i].endCycle !== Infinity) bullet[i].endCycle = simulation.cycle + 780 //13 seconds } } if (Math.random() < tech.botSpawner) { b.randomBot(this.position, false) - bullet[bullet.length - 1].endCycle = simulation.cycle + 840 //14 seconds + bullet[bullet.length - 1].endCycle = simulation.cycle + 780 //13 seconds this.leaveBody = false; // no body since it turned into the bot } if (tech.isAddRemoveMaxHealth) { diff --git a/js/player.js b/js/player.js index 68bdf16..ff4a49b 100644 --- a/js/player.js +++ b/js/player.js @@ -2385,11 +2385,15 @@ const m = { if (this.circleRadius < this.radiusLimit) this.reset() }, reset() { + // console.log(this.circleRadius) const scale = 1 / m.plasmaBall.circleRadius Matter.Body.scale(m.plasmaBall, scale, scale); //grow + // console.log(this.circleRadius) + // this.circleRadius = 0 this.alpha = 0.7 this.isOn = false this.isPopping = false + // this.isAttached = true; }, do() { if (this.isOn) { diff --git a/js/spawn.js b/js/spawn.js index 097af74..80af8ce 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -297,7 +297,7 @@ const spawn = { me.showHealthBar = false; me.collisionFilter.category = 0; me.collisionFilter.mask = 0; //cat.player //| cat.body - me.chaseSpeed = 1.2 + 2 * Math.random() + me.chaseSpeed = 1.2 + 2.3 * Math.random() me.awake = function() { //chase player @@ -394,6 +394,9 @@ const spawn = { this.pushAway(); this.mode[this.totalModes].enter() //enter new mode this.totalModes++ + //spawn 6 mobs + me.mobType = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]; //fire a bullet from each vertex + for (let i = 0; i < 6; i++) me.spawnMobs(i) } ctx.beginPath(); //draw invulnerable let vertices = this.vertices; @@ -408,12 +411,21 @@ const spawn = { } } me.damageReductionDecay = function() { //slowly make the boss take more damage over time //damageReduction resets with each invulnerability phase - if (!(me.cycle % 60) && this.lastDamageCycle + 240 > this.cycle) this.damageReduction *= 1.015 //only decay once a second //only decay if the player has done damage in the last 4 seconds + if (!(me.cycle % 60) && this.lastDamageCycle + 240 > this.cycle) this.damageReduction *= 1.017 //only decay once a second //only decay if the player has done damage in the last 4 seconds + } + me.mobType = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)] + me.spawnMobs = function(index = 0) { + const vertex = me.vertices[index] + const unit = Vector.normalise(Vector.sub(me.position, vertex)) + const where = Vector.add(vertex, Vector.mult(unit, -30)) + spawn[me.mobType](where.x + 50 * (Math.random() - 0.5), where.y + 50 * (Math.random() - 0.5)); + const velocity = Vector.mult(Vector.perp(unit), -10) //give the mob a rotational velocity as if they were attached to a vertex + Matter.Body.setVelocity(mob[mob.length - 1], { x: me.velocity.x + velocity.x, y: me.velocity.y + velocity.y }); } me.maxMobs = 400 me.mode = [{ name: "boulders", - spawnRate: 120 - 6 * simulation.difficultyMode, + spawnRate: 170 - 6 * simulation.difficultyMode, do() { if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) { me.boulder(me.position.x, me.position.y + 250) @@ -423,19 +435,20 @@ const spawn = { exit() {}, }, { name: "mobs", - whoSpawn: spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)], - spawnRate: 240 - 20 * simulation.difficultyMode, + // whoSpawn: spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)], + spawnRate: 280 - 20 * simulation.difficultyMode, do() { if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) { me.torque += 0.000015 * me.inertia; //spin const index = Math.floor((me.cycle % (this.spawnRate * 6)) / this.spawnRate) //int from 0 to 5 - if (index === 0) this.whoSpawn = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]; //fire a bullet from each vertex - const vertex = me.vertices[index] - const unit = Vector.normalise(Vector.sub(me.position, vertex)) - const where = Vector.add(vertex, Vector.mult(unit, -30)) - spawn[this.whoSpawn](where.x + 50 * (Math.random() - 0.5), where.y + 50 * (Math.random() - 0.5)); - const velocity = Vector.mult(Vector.perp(unit), -18) //give the mob a rotational velocity as if they were attached to a vertex - Matter.Body.setVelocity(mob[mob.length - 1], { x: me.velocity.x + velocity.x, y: me.velocity.y + velocity.y }); + if (index === 0) me.mobType = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]; //fire a bullet from each vertex + me.spawnMobs(index) + // const vertex = me.vertices[index] + // const unit = Vector.normalise(Vector.sub(me.position, vertex)) + // const where = Vector.add(vertex, Vector.mult(unit, -30)) + // spawn[me.mobType](where.x + 50 * (Math.random() - 0.5), where.y + 50 * (Math.random() - 0.5)); + // const velocity = Vector.mult(Vector.perp(unit), -18) //give the mob a rotational velocity as if they were attached to a vertex + // Matter.Body.setVelocity(mob[mob.length - 1], { x: me.velocity.x + velocity.x, y: me.velocity.y + velocity.y }); } }, enter() {}, @@ -443,7 +456,7 @@ const spawn = { }, { name: "hoppers", - spawnRate: 420 - 16 * simulation.difficultyMode, + spawnRate: 480 - 16 * simulation.difficultyMode, do() { if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) { me.torque += 0.00002 * me.inertia; //spin @@ -457,6 +470,10 @@ const spawn = { y: me.velocity.y + velocity.y }); } + let where = { x: 600 - Math.random() * 100, y: -225 } + if (simulation.isHorizontalFlipped) where.x = -600 + Math.random() * 100 + spawn.hopBullet(where.x, where.y, 13 + Math.ceil(Math.random() * 8)); //hopBullet(x, y, radius = 10 + Math.ceil(Math.random() * 8)) + Matter.Body.setDensity(mob[mob.length - 1], 0.002); //normal is 0.001 } }, enter() {}, @@ -464,7 +481,7 @@ const spawn = { }, { name: "seekers", - spawnRate: 60 - 3 * simulation.difficultyMode, + spawnRate: 100 - 3 * simulation.difficultyMode, do() { if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) { //spawn seeker const index = Math.floor((me.cycle % 360) / 60) @@ -482,7 +499,7 @@ const spawn = { { name: "mines", bombCycle: 0, - bombInterval: 34 - 2 * simulation.difficultyMode, + bombInterval: 55 - 2 * simulation.difficultyMode, do() { const yOff = 120 this.bombCycle++ @@ -544,7 +561,7 @@ const spawn = { }, { name: "orbiters", - spawnRate: 30 - 2 * simulation.difficultyMode, + spawnRate: 42 - 2 * simulation.difficultyMode, do() { if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) { const speed = (0.01 + 0.0005 * simulation.difficultyMode) * ((Math.random() < 0.5) ? 0.85 : -1.15) @@ -602,7 +619,7 @@ const spawn = { { name: "black hole", eventHorizon: 0, - eventHorizonRadius: 2200, + eventHorizonRadius: 2100, eventHorizonCycle: 0, do() { this.eventHorizonCycle++ @@ -690,10 +707,10 @@ const spawn = { for (let i = 0; i < this.totalModes; i++) this.mode[i].do() } // this.cycle++; - // this.mode[0].do() + // this.mode[4].do() // this.mode[7].do() }; - me.spawnRate = 4800 - 30 * simulation.difficultyMode * simulation.difficultyMode + me.spawnRate = 5800 - 30 * simulation.difficultyMode * simulation.difficultyMode me.spawnBoss = function() { //if the fight lasts too long start spawning bosses if (!(me.cycle % this.spawnRate) && this.health < 1) { this.spawnRate = Math.max(300, this.spawnRate - 10 * simulation.difficultyMode * simulation.difficultyMode) //reduce the timer each time a boss spawns @@ -816,7 +833,7 @@ const spawn = { } }; } - me.lasers = function(where, angle, dmg = 0.13 * simulation.dmgScale) { + me.lasers = function(where, angle, dmg = 0.1 * simulation.dmgScale) { const vertexCollision = function(v1, v1End, domain) { for (let i = 0; i < domain.length; ++i) { let vertices = domain[i].vertices; @@ -1752,7 +1769,7 @@ const spawn = { me.seeAtDistance2 = 1400000; me.cellMassMax = 70 me.collisionFilter.mask = cat.player | cat.bullet //| cat.body | cat.map - Matter.Body.setDensity(me, 0.0002 + 0.00001 * simulation.difficulty) // normal density is 0.001 + Matter.Body.setDensity(me, 0.0001 + 0.00002 * simulation.difficulty) // normal density is 0.001 me.damageReduction = 0.17 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); //me.damageReductionGoal const k = 642 //k=r^2/m @@ -2542,13 +2559,13 @@ const spawn = { mobs.spawn(x, y, 6, radius, "transparent"); let me = mob[mob.length - 1]; me.stroke = "transparent"; //used for drawSneaker - me.eventHorizon = radius * 23; //required for blackhole + me.eventHorizon = radius * 27; //required for blackhole me.seeAtDistance2 = (me.eventHorizon + 400) * (me.eventHorizon + 400); //vision limit is event horizon - me.accelMag = 0.0001 * simulation.accelScale; + me.accelMag = 0.00012 * simulation.accelScale; me.frictionAir = 0.025; me.collisionFilter.mask = cat.player | cat.bullet //| cat.body me.memory = Infinity; - Matter.Body.setDensity(me, 0.008); //extra dense //normal is 0.001 //makes effective life much larger + Matter.Body.setDensity(me, 0.01); //extra dense //normal is 0.001 //makes effective life much larger me.do = function() { //keep it slow, to stop issues from explosion knock backs if (this.speed > 5) { @@ -2675,11 +2692,11 @@ const spawn = { me.stroke = "transparent"; //used for drawSneaker me.eventHorizon = 1100; //required for black hole me.seeAtDistance2 = (me.eventHorizon + 1200) * (me.eventHorizon + 1200); //vision limit is event horizon - me.accelMag = 0.00003 * simulation.accelScale; + me.accelMag = 0.00004 * simulation.accelScale; me.collisionFilter.mask = cat.player | cat.bullet //| cat.body // me.frictionAir = 0.005; me.memory = 1600; - Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger + Matter.Body.setDensity(me, 0.04); //extra dense //normal is 0.001 //makes effective life much larger me.onDeath = function() { //applying forces to player doesn't seem to work inside this method, not sure why powerUps.spawnBossPowerUp(this.position.x, this.position.y) diff --git a/js/tech.js b/js/tech.js index 32723e2..7b2709e 100644 --- a/js/tech.js +++ b/js/tech.js @@ -430,16 +430,11 @@ const tech = { { name: "pigeonhole principle", descriptionFunction() { - var info = "" + let info = "" if (this.count > 0 && Number.isInteger(tech.buffedGun) && b.inventory.length) { - var gun = b.guns[b.inventory[tech.buffedGun]].name - var info = `
this level: +${(31 * Math.max(0, b.inventory.length)).toFixed(0)}% damage for ${gun}` + let gun = b.guns[b.inventory[tech.buffedGun]].name + info = `
this level: +${(31 * Math.max(0, b.inventory.length)).toFixed(0)}% damage for ${gun}` } - - // return ` - // a gun is chosen to be improved each level - //
+${(31*b.inventory.length).toFixed(0)}% damage for ${gun} - //
damage scales by 31% per unequipped gun` return ` a new gun is chosen to be improved each level
+31% damage per gun for the chosen gun${info}` @@ -574,7 +569,7 @@ const tech = { { name: "cache", link: `cache`, - description: `${powerUps.orb.ammo()} give 1600% more ammo, but
you can't store any more ammo than that`, + description: `${powerUps.orb.ammo()} give 1500% more ammo, but
you can't store any more ammo than that`, // ammo powerups always max out your gun, // but the maximum ammo ti limited // description: `${powerUps.orb.ammo()} give 13x more ammo, but
you can't store any more ammo than that`, @@ -587,7 +582,7 @@ const tech = { }, requires: "not non-renewables", effect() { - tech.ammoCap = 16; + tech.ammoCap = 15; powerUps.ammo.effect() }, remove() { @@ -1049,7 +1044,7 @@ const tech = { }, { name: "anticorrelation", - description: "+100% damage
after not using your gun or field for 2 seconds", + description: "if your gun or field are unused for 2 seconds
+100% damage", maxCount: 1, count: 0, frequency: 1, @@ -1068,7 +1063,7 @@ const tech = { { name: "scrap bots", link: `scrap bots`, - description: "after mobs die you have a +33% chance
to build scrap bots that operate for 14 seconds", + description: "after mobs die you have a +33% chance
to build scrap bots that operate for 13 seconds", maxCount: 3, count: 0, frequency: 1, @@ -1088,7 +1083,7 @@ const tech = { { name: "scrap refit", link: `scrap refit`, - description: "after mobs die
reset scrap bots to 14 seconds of operation", + description: "after mobs die
reset scrap bots to 13 seconds of operation", maxCount: 1, count: 0, frequency: 3, @@ -3036,7 +3031,7 @@ const tech = { { name: "many-worlds", // description: "each level is an alternate reality, where you
find a tech at the start of each level", - description: `on each new level use ${powerUps.orb.research(1)} to enter an
alternate reality and spawn a tech power up`, + description: `on each new level enter an
alternate reality and spawn a tech power up`, maxCount: 1, count: 0, frequency: 1, @@ -3243,7 +3238,8 @@ const tech = { }, { name: "emergence", - description: "tech, fields, and guns have +2 choices
+3% JUNK to tech pool", + description: "tech, fields, and guns have +1 choice
+8% damage", + // description: "tech, fields, and guns have +2 choices
+3% JUNK to tech pool", maxCount: 9, count: 0, frequency: 1, @@ -3252,16 +3248,18 @@ const tech = { return !tech.isDeterminism }, requires: "not determinism", + damage: 1.08, effect() { - tech.extraChoices += 2; - this.refundAmount += tech.addJunkTechToPool(0.03) + tech.extraChoices += 1; + tech.damage *= this.damage + // this.refundAmount += tech.addJunkTechToPool(0.03) }, refundAmount: 0, remove() { tech.extraChoices = 0; - if (this.count > 0 && this.refundAmount > 0) { - tech.removeJunkTechFromPool(this.refundAmount) - this.refundAmount = 0 + if (this.count > 0) { + tech.damage /= this.damage + // if (this.refundAmount > 0) tech.removeJunkTechFromPool(this.refundAmount) } } }, @@ -4825,7 +4823,7 @@ const tech = { }, remove() { tech.infiniteWaveAmmo = 1 - if (this.count > 1 && b.guns[3].savedAmmo !== undefined) { + if (this.count > 0 && b.guns[3].savedAmmo !== undefined) { b.guns[3].ammo = b.guns[3].savedAmmo simulation.updateGunHUD(); } @@ -6188,9 +6186,31 @@ const tech = { tech.isCapacitor = false; } }, + { + name: "Bitter electromagnet", + descriptionFunction() { return `railgun charges +33% slower
+100% harpoon density and damage` }, + isGunTech: true, + maxCount: 3, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("harpoon") && tech.isRailGun + }, + requires: "harpoon, railgun", + effect() { + tech.railChargeRate *= 1.06 + tech.harpoonDensity += 0.0065 + }, + remove() { + tech.railChargeRate = 0.97; + tech.harpoonDensity = 0.0065 + } + }, { name: "railgun", - description: `+50% harpoon density, but they don't retract
+900% harpoon ammo per ${powerUps.orb.ammo(1)}`, + description: `harpoons can't retract, hold fire to charge
+50% harpoon density and damage`, + // description: `+900% harpoon ammo, but it can't retract
+50% harpoon density and damage`, isGunTech: true, maxCount: 1, count: 0, @@ -6414,7 +6434,6 @@ const tech = { }, remove() { tech.isHarpoonPowerUp = false - tech.harpoonDensity = 0.004 } }, { @@ -8260,6 +8279,39 @@ const tech = { }, remove() {} }, + { + name: "random", + link: `random`, + delay: 333, + descriptionFunction() { + const delay = 333 + const loop = () => { + if ((simulation.isChoosing) && m.alive && !build.isExperimentSelection) { + const dmg = Math.floor(33 * Math.random()) * 0.01 + this.text = `+${(dmg*100).toFixed(0).padStart(2, '0')}% damage` + this.damage = 1 + dmg + if (document.getElementById(`damage-JUNK-id${this.id}`)) document.getElementById(`damage-JUNK-id${this.id}`).innerHTML = this.text + setTimeout(() => { loop() }, delay); + } + } + setTimeout(() => { loop() }, delay); + this.id++ + return `${this.text}` + }, + maxCount: 3, + count: 0, + frequency: 1, + isJunk: true, + allowed() { return !build.isExperimentSelection }, + requires: "NOT EXPERIMENT MODE", + damage: 0, + effect() { + tech.damage *= this.damage + }, + remove() { + if (this.count > 0) tech.damage /= this.damage + } + }, { name: "boost", maxCount: 1, @@ -8267,9 +8319,7 @@ const tech = { frequency: 0, isJunk: true, isNonRefundable: true, - allowed() { - return !build.isExperimentSelection - }, + allowed() { return !build.isExperimentSelection }, requires: "NOT EXPERIMENT MODE", effect() { powerUps.spawnDelay("boost", this.spawnCount) @@ -8306,7 +8356,7 @@ const tech = { allowed: () => true, requires: "", effect() { - if (Math.random() < 0.1) tech.damage *= 7.77 + if (Math.random() < 0.1) tech.damage *= 8.77 }, remove() {} }, @@ -10066,7 +10116,7 @@ const tech = { allowed() { return m.isShipMode }, requires: "", effect() { - tech.damage *= 2 + tech.damage *= 3 m.look = () => { // const scale = 0; @@ -10984,4 +11034,5 @@ const tech = { isJunkDNA: null, buffedGun: 0, isGunChoice: null, + railChargeRate: null, } \ No newline at end of file diff --git a/todo.txt b/todo.txt index 3fd4bb9..652a4bf 100644 --- a/todo.txt +++ b/todo.txt @@ -1,20 +1,93 @@ ******************************************************** NEXT PATCH ************************************************** +harpoon + default fire rate is 10% higher + default harpoon range 15% higher +railgun + tech: Bitter electromagnet - 33% slower charge time for railgun, 100% more density and damage + area effect damage is increased 20%, scales with bitter electromagnet and total charge + charging longer increases harpoon velocity/damage by up to 30% + contributions to charge time are more uniform between: + crouching, fire rate, Bitter electromagnet, and capacitor bank + auto aims no longer disabled on crouch -plasma-bot does 15% more damage, but costs 2 research -fault tolerance 4->5 forever drones, but costs 2 research -surfactant 2->3 foam bots, but costs 2 research -missile-bot costs 1 research -shaped charge 4->3 research cost -renormalization 40->44% chance to refund research -exciton 18->16% chance to spawn -ground state 50->40% reduced energy regen -Bayesian statistics 3.8->3% damage per research, and spawns 3 research +emergence 2->1 extra choice, and +8% damage, and no added JUNK anymore +cache 16->15x ammo +many-worlds 1->0 research to enter an alternate reality on each new level -JUNK tech: startle response - if mobs are near boost damage, and lock mouse until you press escape +finalBoss + health decays a bit faster + spawns 6 mobs at each health threshold + spawns from the different modes are reduced + boss laser damage is 25% reduced + hoppers spawn from the slime tunnel + +JUNKtech: random - gives random +damage + +bug fixes *********************************************************** TODO ***************************************************** +tech: zombie - sporangium infect mobs, making them fight for you + infected mobs get a status debuff. when they die they return as zombie mob type + zombie mobs run code similar to drones + they inherit color, sides, radius from host + + +tech: sporangium that grow little trees + the trees have an area of effect damage for about 6-10 seconds + maybe something similar to radioactive drones, but maybe a few smaller shapes + +new bot type that makes phonon waves + name: phono-bot? + each bot has to generate it themselves, can't run code in gun.do + synergy with 2 resonance tech + not isotropic? I think no + synergy with bound? phase velocity, amplitude, propagation + +harpoon tech that makes auto aim work much better + +tech - super balls gain 20 seconds of time and are reset to original launch speed after hitting a mob + +railgun + magnetic pinch: harpoon does damage to nearby mobs + draw charge graphic on harpoon + use same code as the damage when fire effect + +hookBoss fires a hook that pulls player towards it + hook does a bit of damage + player targeted unless cloaking + also add effect to finalBoss + + +finalBoss + add synergies between modes: + new modes: + rotating quadrant immunity shield, can't take damage from that quadrant + maybe also attack player near that quadrant + but how to tell the angle of incoming damage + maybe a physics body like the shield but it only covers 1/3 of mob? + falling object warps to ceiling after hitting floor + doesn't end, player needs to kill it + slowly grows? + slow effect zones + random placement or place over player or both! + draw white dot and an outline of area of effect + expanding circle stroke, freeze effect triggers when stroke circle hits fill circle + after 1-2 seconds freeze player if in the zone + also freeze mobs + effect that makes player have to be close to boss + hook that tries to yank the player into hitting finalBoss + does damage + pulls player into center + counter with wormhole, negative mass + player targeted unless cloaking + + +mob status effect - emit - mobs fire lasers for a few seconds + tech: phosphorescence - mobs emit after being hit with laser beams + run canvas direct pixel editing while game is paused + (I tried it an it really hits performance hard) just update once every second? if it uses too much processing have a setting to toggle it off this might help get players to spend more time relaxing on the power up selection @@ -41,8 +114,6 @@ it would be nice if there was incentive to go slow when choosing tech so n-gon i make freeze and __ not cause death at 50% health, but just 600% extra damage for that bullet -new mob status effect - phosphorescence - mobs fire lasers for a few seconds after being hit with lasers - make a new coupling effect for perfect diamagnetism or standing wave make a faster smaller version of cell boss that also has map collisions @@ -50,32 +121,6 @@ make a faster smaller version of cell boss that also has map collisions laserMines need a copy of laser-bot method this is a very rare bug, so not a priority -finalBoss - add synergies between modes: - black hole can pull in bullets - laser can hurt bullets? maybe bad idea - old mode changes - mine color needs to be move vibrant - hoppers can hop out of the slime and the door on the sides - new modes: - rotating quadrant immunity shield, can't take damage from that quadrant - maybe also attack player near that quadrant - falling object warps to ceiling after hitting floor - doesn't end, player needs to kill it - slowly grows? - slow effect zones - random placement or place over player or both! - draw white dot and an outline of area of effect - expanding circle stroke, freeze effect triggers when stroke circle hits fill circle - after 1-2 seconds freeze player if in the zone - also freeze mobs - effect that makes player have to be close to boss - hook that tries to yank the player into hitting finalBoss - does damage - pulls player into center - counter with wormhole, negative mass - player targeted unless cloaking - JUNK tech description that changes similar to cards in inscription that changes based on mouse position can you tell if mouse is over card? @@ -1059,8 +1104,8 @@ possible names for tech lenticular lens: is an array of lenses, designed so that when viewed from slightly different angles, different parts of the image underneath are shown. p-zombie p-hacking JUNK tech - https://en.wikipedia.org/wiki/High-entropy_alloys - https://en.wikipedia.org/wiki/Refractory_metals + https://en.wikipedia.org/wiki/High-entropy_alloys high yield strength and low ductility, high temp resistance + https://en.wikipedia.org/wiki/Refractory_metals hard, high temp resistance https://en.wikipedia.org/wiki/Upper-atmospheric_lightning#Elves prion quine - self replicating protein Unitarity - https://en.wikipedia.org/wiki/Unitarity_(physics) - all probabilities add up to 1, calculations work the same forward and backwards in time