diff --git a/.DS_Store b/.DS_Store index 95d2850..8deaa58 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/js/bullet.js b/js/bullet.js index 43c794c..1a9937a 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -2039,8 +2039,8 @@ const b = { friction: 0.05, frictionAir: 0, restitution: 1, - dmg: 0.24, //damage done in addition to the damage from momentum - lookFrequency: 80 + Math.floor(23 * Math.random()), + dmg: 0.24 + 0.12 * tech.isDroneTeleport, //damage done in addition to the damage from momentum + lookFrequency: 70 + Math.floor(17 * Math.random()), endCycle: simulation.cycle + Math.floor((950 + 420 * Math.random()) * tech.isBulletsLastLonger * tech.droneCycleReduction) + 140 + RADIUS * 5, classType: "bullet", collisionFilter: { @@ -2110,11 +2110,24 @@ const b = { } } } + //blink towards mobs + if (tech.isDroneTeleport && this.lockedOn) { + const sub = Vector.sub(this.lockedOn.position, this.position); + const distMag = Vector.magnitude(sub); + const unit = Vector.normalise(sub) + Matter.Body.setVelocity(this, Vector.mult(unit, Math.max(20, this.speed * 1.5))); + ctx.beginPath(); + ctx.moveTo(this.position.x, this.position.y); + Matter.Body.translate(this, Vector.mult(unit, Math.min(350, distMag - this.lockedOn.radius + 10))); + ctx.lineTo(this.position.x, this.position.y); + ctx.lineWidth = RADIUS * 2; + ctx.strokeStyle = "rgba(0,0,0,0.5)"; + ctx.stroke(); + } //power ups if (!this.isImproved && !simulation.isChoosing && !tech.isExtraMaxEnergy) { if (this.lockedOn) { - //grab, but don't lock onto nearby power up - for (let i = 0, len = powerUp.length; i < len; ++i) { + for (let i = 0, len = powerUp.length; i < len; ++i) { //grab, but don't lock onto nearby power up if ( Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) && @@ -2223,8 +2236,8 @@ const b = { inertia: Infinity, friction: 0, frictionAir: 0, - restitution: 0.8 + 0.199 * Math.random(), - dmg: 0.24, //damage done in addition to the damage from momentum + restitution: 0.4 + 0.199 * Math.random(), + dmg: 0, //0.24 damage done in addition to the damage from momentum and radiation lookFrequency: 120 + Math.floor(23 * Math.random()), endCycle: simulation.cycle + Math.floor((900 + 120 * Math.random()) * tech.isBulletsLastLonger / tech.droneRadioDamage) + 140 + RADIUS * 5, classType: "bullet", @@ -2239,7 +2252,7 @@ const b = { deathCycles: 110 + RADIUS * 5, isImproved: false, radioRadius: 0, - maxRadioRadius: 355 + Math.floor(150 * Math.random()), + maxRadioRadius: 300 + Math.floor(100 * Math.random()), beforeDmg(who) { const unit = Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), -20) //move away from target after hitting Matter.Body.setVelocity(this, { @@ -2247,10 +2260,10 @@ const b = { y: unit.y }); this.lockedOn = null - if (this.endCycle > simulation.cycle + this.deathCycles) { - this.endCycle -= 60 - if (simulation.cycle + this.deathCycles > this.endCycle) this.endCycle = simulation.cycle + this.deathCycles - } + // if (this.endCycle > simulation.cycle + this.deathCycles) { + // this.endCycle -= 60 + // if (simulation.cycle + this.deathCycles > this.endCycle) this.endCycle = simulation.cycle + this.deathCycles + // } }, onEnd() { if (tech.isDroneRespawn) { @@ -2280,7 +2293,7 @@ const b = { //aoe damage to mobs for (let i = 0, len = mob.length; i < len; i++) { if (Vector.magnitude(Vector.sub(mob[i].position, this.position)) < this.radioRadius + mob[i].radius) { - let dmg = b.dmgScale * 0.06 * tech.droneRadioDamage //neutron bombs dmg = 0.09 + let dmg = b.dmgScale * 0.1 * tech.droneRadioDamage //neutron bombs dmg = 0.09 if (Matter.Query.ray(map, mob[i].position, this.position).length > 0) dmg *= 0.25 //reduce damage if a wall is in the way if (mob[i].shield) dmg *= 3 // to make up for the /5 that shields normally take mob[i].damage(dmg); @@ -2695,12 +2708,7 @@ const b = { } for (let i = 0, len = totalPermanentBots - totalTechToConvert; i < len; i++) tech.tech[index].effect(); //also convert any permanent bots that didn't come from a tech //in experiment mode set the unselect color for bot tech that was converted - if (build.isExperimentSelection) { - - - - - } + // if (build.isExperimentSelection) { } }, clearPermanentBots() { for (let i = 0; i < bullet.length; i++) { @@ -3991,7 +3999,10 @@ const b = { propagationRate: 20, waves: [], //used in longitudinal mode chooseFireMethod() { //set in simulation.startGame - if (tech.isLongitudinal) { + if (tech.is360Longitudinal) { + this.fire = this.fire360Longitudinal + this.do = this.do360Longitudinal + } else if (tech.isLongitudinal) { this.fire = this.fireLongitudinal this.do = this.doLongitudinal } else { @@ -4000,10 +4011,94 @@ const b = { } }, do() {}, - doLongitudinal() { - ctx.strokeStyle = "rgba(0,0,0,0.2)" //"000"; - ctx.lineWidth = 2 + do360Longitudinal() { + ctx.strokeStyle = "rgba(0,0,0,0.6)" //"000"; + ctx.lineWidth = 2 * tech.wavePacketDamage ctx.beginPath(); + const end = 75 * Math.sqrt(tech.isBulletsLastLonger) * tech.waveBeamSpeed / Math.sqrt(tech.waveReflections * 0.5) //should equal about 1060 + const damage = 2 * b.dmgScale * tech.wavePacketDamage * tech.waveBeamDamage //damage is lower for large radius mobs, since they feel the waves longer + + for (let i = this.waves.length - 1; i > -1; i--) { + //draw wave + ctx.moveTo(this.waves[i].position.x + this.waves[i].radius, this.waves[i].position.y) + ctx.arc(this.waves[i].position.x, this.waves[i].position.y, this.waves[i].radius, 0, 2 * Math.PI); + // collisions + if (!m.isBodiesAsleep) { + for (let j = 0, len = mob.length; j < len; j++) { + const dist = Vector.magnitude(Vector.sub(this.waves[i].position, mob[j].position)) + const r = mob[j].radius + 30 + if (dist + r > this.waves[i].radius && dist - r < this.waves[i].radius) { + //make them shake around + if (!mob[j].isBadTarget) { + mob[j].force.x += 0.01 * (Math.random() - 0.5) * mob[j].mass + mob[j].force.y += 0.01 * (Math.random() - 0.5) * mob[j].mass + } + if (!mob[j].isShielded) { + Matter.Body.setVelocity(mob[j], { //friction + x: mob[j].velocity.x * 0.93, + y: mob[j].velocity.y * 0.93 + }); + //draw vibes + let vertices = mob[j].vertices; + const vibe = 50 + mob[j].radius * 0.15 + ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); + for (let k = 1; k < vertices.length; k++) { + ctx.lineTo(vertices[k].x + vibe * (Math.random() - 0.5), vertices[k].y + vibe * (Math.random() - 0.5)); + } + ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); + //damage + mob[j].locatePlayer(); + mob[j].damage(damage / Math.sqrt(mob[j].radius)); + } + } + } + for (let j = 0, len = body.length; j < len; j++) { + const dist = Vector.magnitude(Vector.sub(this.waves[i].position, body[j].position)) + const r = 20 + if (dist + r > this.waves[i].radius && dist - r < this.waves[i].radius) { + //make them shake around + body[j].force.x += 0.01 * (Math.random() - 0.5) * body[j].mass + body[j].force.y += (0.01 * (Math.random() - 0.5) - simulation.g * 0.25) * body[j].mass //remove force of gravity + //draw vibes + let vertices = body[j].vertices; + const vibe = 25 + ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); + for (let k = 1; k < vertices.length; k++) { + ctx.lineTo(vertices[k].x + vibe * (Math.random() - 0.5), vertices[k].y + vibe * (Math.random() - 0.5)); + } + ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); + } + } + this.waves[i].radius += tech.waveBeamSpeed * this.waves[i].expanding //expand / move + } + // if (this.waves[i].radius > end) this.waves.splice(i, 1) //end + if (this.waves[i].radius > end) { + this.waves[i].expanding = -1 + this.waves[i].reflection-- + if (this.waves[i].reflection < 1) this.waves.splice(i, 1) //end + } else if (this.waves[i].radius < 25) { + this.waves[i].expanding = 1 + this.waves[i].reflection-- + if (this.waves[i].reflection < 1) this.waves.splice(i, 1) //end + } + } + ctx.stroke(); + }, + fire360Longitudinal() { + m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 3 : 8) * b.fireCDscale); // cool down + this.waves.push({ + position: { x: m.pos.x, y: m.pos.y, }, + radius: 25, + reflection: tech.waveReflections, + expanding: true + }) + }, + doLongitudinal() { + ctx.strokeStyle = "rgba(0,0,0,0.6)" //"000"; + ctx.lineWidth = 2 * tech.wavePacketDamage + ctx.beginPath(); + const end = 125 * tech.isBulletsLastLonger * tech.waveBeamSpeed / Math.sqrt(tech.waveReflections * 0.5) //should equal about 1767 + const damage = 2 * b.dmgScale * tech.wavePacketDamage * tech.waveBeamDamage //damage is lower for large radius mobs, since they feel the waves longer for (let i = this.waves.length - 1; i > -1; i--) { const v1 = Vector.add(this.waves[i].position, Vector.mult(this.waves[i].unit1, this.waves[i].radius)) @@ -4018,23 +4113,25 @@ const b = { for (let j = 0; j < hits.length; j++) { const who = hits[j].body //make them shake around - who.force.x += 0.01 * (Math.random() - 0.5) * who.mass - who.force.y += 0.01 * (Math.random() - 0.5) * who.mass - Matter.Body.setVelocity(who, { //friction - x: who.velocity.x * 0.95, - y: who.velocity.y * 0.95 - }); - - let vertices = who.vertices; - const vibe = 50 + who.radius * 0.15 - ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); - for (let j = 1; j < vertices.length; j++) { - ctx.lineTo(vertices[j].x + vibe * (Math.random() - 0.5), vertices[j].y + vibe * (Math.random() - 0.5)); + if (!who.isBadTarget) { + who.force.x += 0.01 * (Math.random() - 0.5) * who.mass + who.force.y += 0.01 * (Math.random() - 0.5) * who.mass + } + if (!who.isShielded) { + Matter.Body.setVelocity(who, { //friction + x: who.velocity.x * 0.95, + y: who.velocity.y * 0.95 + }); + let vertices = who.vertices; + const vibe = 50 + who.radius * 0.15 + ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); + for (let j = 1; j < vertices.length; j++) { + ctx.lineTo(vertices[j].x + vibe * (Math.random() - 0.5), vertices[j].y + vibe * (Math.random() - 0.5)); + } + ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); + who.locatePlayer(); + who.damage(damage / Math.sqrt(who.radius)); } - ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); - const damage = 1.9 * b.dmgScale * tech.waveBeamDamage * tech.wavePacketDamage / Math.sqrt(who.radius) //damage is lower for large radius mobs, since they feel the waves longer - who.locatePlayer(); - who.damage(damage); } hits = Matter.Query.ray(body, v1, v2, 50) //Matter.Query.ray(bodies, startPoint, endPoint, [rayWidth]) @@ -4052,11 +4149,19 @@ const b = { } ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); } - ctx.stroke(); //draw vibes + // ctx.stroke(); //draw vibes - this.waves[i].radius += tech.waveBeamSpeed * 2 //expand / move + this.waves[i].radius += tech.waveBeamSpeed * 2 * this.waves[i].expanding //expand / move + } + if (this.waves[i].radius > end) { + this.waves[i].expanding = -1 + this.waves[i].reflection-- + if (this.waves[i].reflection < 1) this.waves.splice(i, 1) //end + } else if (this.waves[i].radius < 25) { + this.waves[i].expanding = 1 + this.waves[i].reflection-- + if (this.waves[i].reflection < 1) this.waves.splice(i, 1) //end } - if (this.waves[i].radius > 1800 * tech.isBulletsLastLonger) this.waves.splice(i, 1) //end } ctx.stroke(); }, @@ -4072,7 +4177,9 @@ const b = { unit1: { x: Math.cos(m.angle - halfArc), y: Math.sin(m.angle - halfArc) }, //used for collision unit2: { x: Math.cos(m.angle + halfArc), y: Math.sin(m.angle + halfArc) }, //used for collision arc: halfArc * 2, - radius: 25 + radius: 25, + reflection: tech.waveReflections, + expanding: 1 }) }, doTransverse() { @@ -4082,7 +4189,7 @@ const b = { } }, fireTransverse() { - totalCycles = Math.floor(4.3 * tech.wavePacketLength * tech.waveReflections * tech.isBulletsLastLonger) + totalCycles = Math.floor(4.3 * 35 * tech.waveReflections * tech.isBulletsLastLonger / Math.sqrt(tech.waveReflections * 0.5)) const me = bullet.length; bullet[me] = Bodies.polygon(m.pos.x + 25 * Math.cos(m.angle), m.pos.y + 25 * Math.sin(m.angle), 5, 4, { angle: m.angle, @@ -4091,7 +4198,7 @@ const b = { inertia: Infinity, frictionAir: 0, slow: 0, - amplitude: (m.crouch ? 5 : 10) * ((this.wavePacketCycle % 2) ? -1 : 1) * Math.sin((this.wavePacketCycle + 1) * tech.wavePacketFrequency), // + amplitude: (m.crouch ? 5 : 10) * ((this.wavePacketCycle % 2) ? -1 : 1) * Math.sin((this.wavePacketCycle + 1) * 0.088), //0.0968 //0.1012 //0.11 //0.088 //shorten wave packet minDmgSpeed: 0, dmg: b.dmgScale * tech.waveBeamDamage * tech.wavePacketDamage, //also control damage when you divide by mob.mass classType: "bullet", @@ -4176,7 +4283,7 @@ const b = { const transverse = Vector.normalise(Vector.perp(bullet[me].velocity)) //fire a packet of bullets then delay for a while this.wavePacketCycle++ - if (this.wavePacketCycle > tech.wavePacketLength) { + if (this.wavePacketCycle > 35) { m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCDscale); // cool down this.wavePacketCycle = 0; } diff --git a/js/engine.js b/js/engine.js index 03c816d..cd01a77 100644 --- a/js/engine.js +++ b/js/engine.js @@ -176,6 +176,7 @@ function collisionChecks(event) { if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) { obj.beforeDmg(mob[k]); //some bullets do actions when they hits things, like despawn //forces don't seem to work here let dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity))) + console.log(dmg) if (tech.isCrit && mob[k].isStunned) dmg *= 4 mob[k].foundPlayer(); mob[k].damage(dmg); diff --git a/js/index.js b/js/index.js index 756573d..197a864 100644 --- a/js/index.js +++ b/js/index.js @@ -257,7 +257,7 @@ const build = { } } - + //show in game console with scroll bar? // text +=`` @@ -434,7 +434,6 @@ const build = { for (let i = 0, len = b.guns.length; i < len; i++) { text += `
  ${b.guns[i].name}
${b.guns[i].description}
` } - for (let i = 0, len = tech.tech.length; i < len; i++) { if (!tech.tech[i].isExperimentHide && (!tech.tech[i].isNonRefundable || tech.tech[i].isExperimentalMode)) { if (tech.tech[i].allowed()) { // || tech.tech[i].name === "+1 cardinality") { //|| tech.tech[i].name === "leveraged investment" @@ -457,7 +456,6 @@ const build = { document.getElementById("difficulty-select").value = document.getElementById("difficulty-select-experiment").value localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage }); - //add tooltips for (let i = 0, len = tech.tech.length; i < len; i++) { if (document.getElementById(`tech-${i}`)) { @@ -470,9 +468,7 @@ const build = { simulation.startGame(true); //starts game, but pauses it build.isExperimentSelection = true; simulation.paused = true; - m.setField(0) - b.inventory = []; //removes guns and ammo for (let i = 0, len = b.guns.length; i < len; ++i) { b.guns[i].count = 0; @@ -481,7 +477,6 @@ const build = { } b.activeGun = null; simulation.makeGunHUD(); - tech.setupAllTech(); build.populateGrid(); document.getElementById("field-0").classList.add("build-field-selected"); @@ -490,14 +485,12 @@ const build = { shareURL(isCustom = false) { let url = "https://landgreen.github.io/sidescroller/index.html?" let count = 0; - for (let i = 0; i < b.inventory.length; i++) { if (b.guns[b.inventory[i]].have) { url += `&gun${count}=${encodeURIComponent(b.guns[b.inventory[i]].name.trim())}` count++ } } - count = 0; for (let i = 0; i < tech.tech.length; i++) { for (let j = 0; j < tech.tech[i].count; j++) { @@ -516,7 +509,6 @@ const build = { } console.log('n-gon build URL copied to clipboard.\nPaste into browser address bar.') console.log(url) - navigator.clipboard.writeText(url).then(function() { /* clipboard successfully set */ if (isCustom) { diff --git a/js/level.js b/js/level.js index ad4a727..dc180e3 100644 --- a/js/level.js +++ b/js/level.js @@ -15,13 +15,15 @@ const level = { // level.difficultyIncrease(30) // simulation.isHorizontalFlipped = true // m.setField("wormhole") - // b.giveGuns("shotgun") - // tech.isShotgunRecoil = true - // tech.isShotgunReversed = true - // tech.giveTech("supertemporal") - // tech.giveTech("free-electron laser") + // b.giveGuns("drones") + // tech.giveTech("torque bursts") + // b.giveGuns("wave beam") + // tech.giveTech("phonon") + // tech.giveTech("bound state") + // tech.giveTech("bound state") + // tech.giveTech("bound state") + // tech.giveTech("isotropic radiator") // for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics") - // tech.giveTech("decoherence") // for (let i = 0; i < 3; i++) tech.giveTech("packet length") level.intro(); //starting level @@ -2252,14 +2254,14 @@ const level = { spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump // spawn.starter(1900, -500, 200) //big boy - // spawn.pulseShooter(1900, -500) - spawn.shieldingBoss(1900, -500) + // spawn.pulsarBoss(1900, -500) + // spawn.shieldingBoss(1900, -500) // spawn.grenadierBoss(1900, -500) // spawn.shieldingBoss(1900, -500) // spawn.historyBoss(1200, -500) // spawn.laserTargetingBoss(1600, -400) - // spawn.hopper(1600, -500) + // spawn.focuser(1600, -500) // spawn.laserTargetingBoss(1700, -120) // spawn.bomberBoss(1400, -500) // spawn.hopBoss(1800, -120) @@ -2267,7 +2269,7 @@ const level = { // spawn.orbitalBoss(1600, -500) // spawn.cellBossCulture(1600, -500) // spawn.shieldingBoss(1600, -500) - // spawn.laser(1200, -500) + spawn.grenadier(1200, -500) // spawn.shield(mob[mob.length - 1], 1800, -120, 1); // spawn.nodeGroup(1200, -500, "grenadier") @@ -2621,7 +2623,7 @@ const level = { // localSettings.levelsClearedLastGame = 20 if (level.levelsCleared === 0) { - powerUps.spawn(2500, -50, "research", false); + // powerUps.spawn(2500, -50, "research", false); powerUps.spawn(1900, -50, "heal", false); powerUps.spawn(2050, -50, "heal", false); if (localSettings.levelsClearedLastGame < 6) { diff --git a/js/player.js b/js/player.js index 42d0274..9bf1480 100644 --- a/js/player.js +++ b/js/player.js @@ -1830,7 +1830,7 @@ const m = { m.energy -= 0.04; b.iceIX(1) } else if (tech.isDroneRadioactive) { - m.energy -= 1.5; //almost 5x drain of normal drones + m.energy -= 0.9; b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 25) } else { m.energy -= 0.45 * tech.droneEnergyReduction; diff --git a/js/powerup.js b/js/powerup.js index 7322863..fe7eac6 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -262,12 +262,14 @@ const powerUps = { } } }, + currentRerollCount: 0, use(type) { //runs when you actually research a list of selections, type can be field, gun, or tech - if (tech.isJunkResearch) { + if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { tech.addJunkTechToPool(tech.junkResearchNumber) } else { powerUps.research.changeRerolls(-1) } + powerUps.research.currentRerollCount++ // simulation.makeTextLog(`m.research-- //
${powerUps.research.count}`) if (tech.isBanish && type === 'tech') { // banish researched tech @@ -447,8 +449,8 @@ const powerUps = { powerUps.field.choiceLog.push(choice2) powerUps.field.choiceLog.push(choice3) - if (tech.isJunkResearch) { - tech.junkResearchNumber = Math.floor(5 * Math.random()) + if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { + tech.junkResearchNumber = Math.floor(4 * Math.random()) text += `
` for (let i = 0; i < tech.junkResearchNumber; i++) text += `
` text += `
  pseudoscience
` @@ -461,8 +463,6 @@ const powerUps = { // text += `
${simulation.SVGrightMouse} activate the shield with the right mouse
fields shield you from damage
and let you pick up and throw blocks
` document.getElementById("choose-grid").innerHTML = text powerUps.showDraft(); - } else { - powerUps.giveRandomAmmo() } } }, @@ -566,7 +566,7 @@ const powerUps = { powerUps.tech.choiceLog.push(choice3) // if (powerUps.research.count) text += `
  research ${powerUps.research.count}
` - if (tech.isJunkResearch) { + if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { tech.junkResearchNumber = Math.floor(5 * Math.random()) text += `
` for (let i = 0; i < tech.junkResearchNumber; i++) text += `
` @@ -579,19 +579,16 @@ const powerUps = { document.getElementById("choose-grid").innerHTML = text powerUps.showDraft(); - } else { - if (tech.isBanish) { - for (let i = 0, len = tech.tech.length; i < len; i++) { - if (tech.tech[i].name === "decoherence") powerUps.ejectTech(i) - } - // simulation.makeTextLog(`No tech left
erased tech have been recovered`) - simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - powerUps.tech.banishLog.length)}`) - // powerUps.spawn(m.pos.x, m.pos.y, "tech"); - powerUps.endDraft("tech"); - } else { - powerUps.giveRandomAmmo() + } else if (tech.isBanish) { + for (let i = 0, len = tech.tech.length; i < len; i++) { + if (tech.tech[i].name === "decoherence") powerUps.ejectTech(i) } + // simulation.makeTextLog(`No tech left
erased tech have been recovered`) + simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - powerUps.tech.banishLog.length)}`) + // powerUps.spawn(m.pos.x, m.pos.y, "tech"); + powerUps.endDraft("tech"); } + } } }, @@ -658,7 +655,7 @@ const powerUps = { powerUps.gun.choiceLog.push(choice3) // if (powerUps.research.count) text += `
  research ${powerUps.research.count}
` - if (tech.isJunkResearch) { + if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { tech.junkResearchNumber = Math.floor(5 * Math.random()) text += `
` for (let i = 0; i < tech.junkResearchNumber; i++) text += `
` @@ -673,12 +670,11 @@ const powerUps = { if (tech.isOneGun && b.inventory.length > 0) text += `
replaces your current gun
` document.getElementById("choose-grid").innerHTML = text powerUps.showDraft(); - } else { - powerUps.giveRandomAmmo() } } }, onPickUp(who) { + powerUps.research.currentRerollCount = 0 if (tech.isTechDamage && who.name === "tech") m.damage(0.11) if (tech.isMassEnergy) m.energy += 2; if (tech.isMineDrop) { @@ -700,15 +696,15 @@ const powerUps = { } } }, - giveRandomAmmo() { - const ammoTarget = Math.floor(Math.random() * (b.guns.length)); - const ammo = Math.ceil(b.guns[ammoTarget].ammoPack * 6); - if (ammo !== Infinity) { - b.guns[ammoTarget].ammo += ammo; - simulation.updateGunHUD(); - simulation.makeTextLog(`${b.guns[ammoTarget].name}.ammo += ${ammo}`); - } - }, + // giveRandomAmmo() { + // const ammoTarget = Math.floor(Math.random() * (b.guns.length)); + // const ammo = Math.ceil(b.guns[ammoTarget].ammoPack * 6); + // if (ammo !== Infinity) { + // b.guns[ammoTarget].ammo += ammo; + // simulation.updateGunHUD(); + // simulation.makeTextLog(`${b.guns[ammoTarget].name}.ammo += ${ammo}`); + // } + // }, spawnRandomPowerUp(x, y) { //mostly used after mob dies, doesn't always return a power up if ((Math.random() * Math.random() - 0.3 > Math.sqrt(m.health) && !tech.isEnergyHealth) || Math.random() < 0.04) { //spawn heal chance is higher at low health powerUps.spawn(x, y, "heal"); diff --git a/js/simulation.js b/js/simulation.js index 7537530..1a1fe50 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -332,14 +332,14 @@ const simulation = { } }, nextGun() { - if (b.inventory.length > 0 && !tech.isGunCycle) { + if (b.inventory.length > 1 && !tech.isGunCycle) { b.inventoryGun++; if (b.inventoryGun > b.inventory.length - 1) b.inventoryGun = 0; simulation.switchGun(); } }, previousGun() { - if (b.inventory.length > 0 && !tech.isGunCycle) { + if (b.inventory.length > 1 && !tech.isGunCycle) { b.inventoryGun--; if (b.inventoryGun < 0) b.inventoryGun = b.inventory.length - 1; simulation.switchGun(); diff --git a/js/spawn.js b/js/spawn.js index 0308088..3fa8e59 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -306,16 +306,16 @@ const spawn = { function loop() { if (!simulation.paused) { count++ - if (count < 600) { + if (count < 660) { if (count === 1) simulation.makeTextLog(`//enter testing mode to set level.levels.length to Infinite`); - if (!(count % 60)) simulation.makeTextLog(`simulation.analysis = ${(count/60- Math.random()).toFixed(3)}`); - } else if (count === 600) { + if (!(count % 60)) simulation.makeTextLog(`simulation.analysis = ${((count/60- Math.random())*0.1 ).toFixed(3)}`); + } else if (count === 660) { simulation.makeTextLog(`simulation.analysis = 1 //analysis complete`); - } else if (count === 720) { + } else if (count === 780) { simulation.makeTextLog(`undefined = ${lore.techCount}/${lore.techGoal}`) - } else if (count === 900) { + } else if (count === 1020) { simulation.makeTextLog(`World.clear(engine.world) //simulation successful`); - } else if (count === 1140) { + } else if (count === 1260) { // tech.isImmortal = false; // m.death() // m.alive = false; @@ -1709,7 +1709,7 @@ const spawn = { if (targetDist < r + 16) { targetDist = r + 10; //charge at player - const forceMag = this.accelMag * 30 * this.mass; + const forceMag = this.accelMag * 40 * this.mass; const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x); this.force.x += forceMag * Math.cos(angle); this.force.y += forceMag * Math.sin(angle); @@ -1906,7 +1906,7 @@ const spawn = { me.fireCycle = 0 me.fireTarget = { x: 0, y: 0 } me.pulseRadius = Math.min(500, 230 + simulation.difficulty * 3) - me.fireDelay = Math.max(60, 140 - simulation.difficulty * 2) + me.fireDelay = Math.max(60, 150 - simulation.difficulty * 2) me.isFiring = false Matter.Body.setDensity(me, 0.01); //extra dense //normal is 0.001 //makes effective life much larger me.isBoss = true; @@ -2999,20 +2999,21 @@ const spawn = { }; }, grenadierBoss(x, y, radius = 95) { - mobs.spawn(x, y, 6, radius, "rgb(255,50,160)"); + mobs.spawn(x, y, 6, radius, "rgb(215,80,190)"); let me = mob[mob.length - 1]; me.isBoss = true; - me.accelMag = 0.00008 * simulation.accelScale; + me.accelMag = 0.0001 * simulation.accelScale; me.fireFreq = Math.floor(360 * simulation.CDScale) me.frictionStatic = 0; me.friction = 0; - me.frictionAir = 0.02; + me.frictionAir = 0.035; me.memory = 420; me.repulsionRange = 1200000; //squared - spawn.shield(me, x, y, 1); - spawn.spawnOrbitals(me, radius + 25, 1); - spawn.spawnOrbitals(me, radius + 75, 1); - Matter.Body.setDensity(me, 0.002 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger + // spawn.shield(me, x, y, 1); + spawn.spawnOrbitals(me, radius + 50, 1); + spawn.spawnOrbitals(me, radius + 125, 1); + spawn.spawnOrbitals(me, radius + 200, 1); + Matter.Body.setDensity(me, 0.004 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger me.onDeath = function() { //helps collisions functions work better after vertex have been changed for (let i = 0; i < 6; i++) { spawn.grenade(this.position.x, this.position.y, 2, 4, 75 * simulation.CDScale); @@ -3050,110 +3051,8 @@ const spawn = { this.attraction(); }; }, - // grenadierBoss(x, y, radius = 110) { - // mobs.spawn(x, y, 3, radius, "rgb(255,50,160)"); //rgb(255,100,200) - // let me = mob[mob.length - 1]; - // me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front - // me.isVerticesChange = true - // me.isBoss = true; - // me.frictionStatic = 0; - // me.friction = 0; - // me.memory = 180 //140; - // me.fireFreq = 0.02; - // me.noseLength = 0; - // me.fireAngle = 0; - // me.accelMag = 0.005 * simulation.accelScale; - // me.frictionAir = 0.05; - // me.lookTorque = 0.000006 * (Math.random() > 0.5 ? -1 : 1); - // me.fireDir = { - // x: 0, - // y: 0 - // }; - // Matter.Body.setDensity(me, 0.008 + 0.0003 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger - // setTimeout(() => { - // spawn.spawnOrbitals(me, radius + 25, 1); - // spawn.spawnOrbitals(me, radius + 75, 1); - // }, 100); //have to wait a sec so the tether constraint doesn't attach to an orbital - // me.onDeath = function() { //helps collisions functions work better after vertex have been changed - // for (let i = 0; i < 6; i++) { - // spawn.grenade(this.position.x, this.position.y, 2, 4, 75 * simulation.CDScale); - // const who = mob[mob.length - 1] - // who.collisionFilter.category = 0 - // who.collisionFilter.mask = 0 - // const speed = 4 * simulation.accelScale; - // const angle = 2 * Math.PI * i / 6 - // Matter.Body.setVelocity(who, { - // x: this.velocity.x + speed * Math.cos(angle), - // y: this.velocity.y + speed * Math.sin(angle) - // }); - // } - // powerUps.spawnBossPowerUp(this.position.x, this.position.y) - // } - // // me.onDamage = function() { - // // spawn.grenade(this.position.x, this.position.y, 2, 4, 120 * simulation.CDScale); - // // const who = mob[mob.length - 1] - // // who.collisionFilter.category = 0 - // // who.collisionFilter.mask = 0 - // // const velocity = Vector.mult(Vector.normalise(Vector.sub(player.position, who.position)), 3) - // // Matter.Body.setVelocity(who, { - // // x: this.velocity.x + velocity.x, - // // y: this.velocity.y + velocity.y - // // }); - // // }; - // me.do = function() { - // this.seePlayerByLookingAt(); - // this.checkStatus(); - - // if (!m.isBodiesAsleep) { - // const setNoseShape = () => { - // const mag = this.radius + this.radius * this.noseLength; - // this.vertices[1].x = this.position.x + Math.cos(this.angle) * mag; - // this.vertices[1].y = this.position.y + Math.sin(this.angle) * mag; - // }; - // //throw a mob/bullet at player - // if (this.seePlayer.recall) { - // //set direction to turn to fire - // if (!(simulation.cycle % this.seePlayerFreq)) { - // this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position)); - // // this.fireDir.y -= Math.abs(this.seePlayer.position.x - this.position.x) / 1600; //gives the bullet an arc - // } - // //rotate towards fireAngle - // const angle = this.angle + Math.PI / 2; - // // c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y; - // //rotate towards fireAngle - // const dot = Vector.dot({ - // x: Math.cos(angle), - // y: Math.sin(angle) - // }, this.fireDir) - // const threshold = 0.03; - // if (dot > threshold) { - // this.torque += 0.000004 * this.inertia; - // } else if (dot < -threshold) { - // this.torque -= 0.000004 * this.inertia; - // } else if (this.noseLength > 1.5 && dot > -0.2 && dot < 0.2) { - // //fire - // spawn.grenade(this.vertices[1].x, this.vertices[1].y); - // const v = 7 * simulation.accelScale; - // Matter.Body.setVelocity(mob[mob.length - 1], { - // x: this.velocity.x + this.fireDir.x * v + Math.random(), - // y: this.velocity.y + this.fireDir.y * v + Math.random() - // }); - // this.noseLength = 0; - // // recoil - // this.force.x -= 0.002 * this.fireDir.x * this.mass; - // this.force.y -= 0.002 * this.fireDir.y * this.mass; - // } - // if (this.noseLength < 1.5) this.noseLength += this.fireFreq; - // setNoseShape(); - // } else if (this.noseLength > 0.1) { - // this.noseLength -= this.fireFreq / 2; - // setNoseShape(); - // } - // } - // }; - // }, grenadier(x, y, radius = 35 + Math.ceil(Math.random() * 20)) { - mobs.spawn(x, y, 3, radius, "rgba(255,50,160,1)"); //rgb(255,100,200) + mobs.spawn(x, y, 3, radius, "rgb(215,80,190)"); //rgb(255,100,200) let me = mob[mob.length - 1]; me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front me.isVerticesChange = true @@ -3231,7 +3130,7 @@ const spawn = { }; }, grenade(x, y, radius = 2, sides = 4, lifeSpan = 90 + Math.ceil(60 / simulation.accelScale)) { - mobs.spawn(x, y, sides, radius, "rgb(255,0,0)"); + mobs.spawn(x, y, sides, radius, "rgb(215,0,190)"); //rgb(215,80,190) let me = mob[mob.length - 1]; me.stroke = "transparent"; me.onHit = function() { @@ -3258,7 +3157,7 @@ const spawn = { x: this.position.x, y: this.position.y, radius: this.pulseRadius, - color: "rgba(255,0,100,0.6)", + color: "rgba(255,0,220,0.3)", time: simulation.drawTime }); }; @@ -3269,7 +3168,7 @@ const spawn = { this.timeLimit(); ctx.beginPath(); //draw explosion outline ctx.arc(this.position.x, this.position.y, this.pulseRadius * (1.01 - this.timeLeft / this.lifeSpan), 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay - ctx.fillStyle = "rgba(255,0,100,0.06)"; + ctx.fillStyle = "rgba(255,0,220,0.05)"; ctx.fill(); }; }, diff --git a/js/tech.js b/js/tech.js index bfed355..3f5d982 100644 --- a/js/tech.js +++ b/js/tech.js @@ -647,7 +647,7 @@ }, { name: "microstates", - description: "increase damage by 6%
for every 10 active bullets", + description: "increase damage by 6%
for every 10 active projectiles", maxCount: 1, count: 0, frequency: 2, @@ -665,7 +665,7 @@ }, { name: "anti-shear topology", - description: "some bullets last 30% longer
drones, spores, missiles, foam, wave, neutron", + description: "some projectiles last 30% longer
drones, spores, missiles, foam, wave, neutron", // isGunTech: true, maxCount: 3, count: 0, @@ -2802,7 +2802,7 @@ }, { name: "pseudoscience", - description: "rerolling choices no longer costs research
instead it adds 0-4 JUNK to the tech pool", + description: "when selecting a power up, research 3 times
for free, but add 0-3 JUNK to the tech pool", maxCount: 1, count: 0, frequency: 1, @@ -3883,28 +3883,9 @@ tech.bulletSize = 1; } }, - { - name: "bound state", - description: "instead of dissipating normally
wave packets reflect backwards 2 times", - isGunTech: true, - maxCount: 3, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.haveGunCheck("wave beam") && !tech.isLongitudinal - }, - requires: "wave beam", - effect() { - tech.waveReflections += 2 - }, - remove() { - tech.waveReflections = 1 - } - }, { name: "phase velocity", - description: "wave beam propagates faster through solids
up by 3000% in the map and 760% in blocks", + description: "wave beam propagates faster through solids
up by 3000% in the map and 760% in blocks", isGunTech: true, maxCount: 1, count: 0, @@ -3913,7 +3894,7 @@ allowed() { return tech.haveGunCheck("wave beam") && !tech.isLongitudinal }, - requires: "wave beam", + requires: "wave beam, not phonon", effect() { tech.isPhaseVelocity = true; }, @@ -3922,27 +3903,22 @@ } }, { - name: "packet length", - description: "wave packet length and duration
is increased by 50%", // description: "holding fire allows the wave beam to emits a second packet
at zero ammo cost", + name: "bound state", + description: "wave packets reflect backwards 2 times
range is reduced by 25%", isGunTech: true, - maxCount: 3, + maxCount: 9, count: 0, frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("wave beam") && !tech.isLongitudinal + return tech.haveGunCheck("wave beam") }, requires: "wave beam", effect() { - const scale = 1.5 - 0.025 * this.count - tech.wavePacketLength *= scale - tech.wavePacketFrequency /= scale - tech.waveLengthRange *= Math.sqrt(scale) + tech.waveReflections += 2 }, remove() { - tech.wavePacketFrequency = 0.088 //0.0968 //0.1012 //0.11 //0.088 //shorten wave packet - tech.wavePacketLength = 35 //32.7 //31.3 //28.8 //36 //how many wave packets are released // double this to emit 2 packets - tech.waveLengthRange = 130; + tech.waveReflections = 1 } }, { @@ -3968,7 +3944,7 @@ }, { name: "propagation", - description: "wave packet propagation speed is 25% slower
wave damage is increased by 50%", + description: "wave packet propagation speed is 20% slower
wave damage is increased by 50%", isGunTech: true, maxCount: 9, count: 0, @@ -3979,26 +3955,26 @@ }, requires: "wave beam", effect() { - tech.waveBeamSpeed *= 0.75; - tech.waveBeamDamage += 1.3 * 0.5 + tech.waveBeamSpeed *= 0.8; + tech.waveBeamDamage += 1.5 * 0.5 //this sets base wave beam damage, not used by arcs or circles }, remove() { tech.waveBeamSpeed = 10; - tech.waveBeamDamage = 1.5 //this sets base wave beam damage + tech.waveBeamDamage = 1.5 //this sets base wave beam damage, not used by arcs or circles } }, { - name: "pressure wave", //longitudinal //gravitational wave? - description: "wave beam emits low frequency, high damage
expanding arcs that propagate through solids", + name: "phonon", //longitudinal //gravitational wave? + description: "wave beam emits low frequency, high damage
expanding arcs that propagate through solids", isGunTech: true, maxCount: 1, count: 0, frequency: 4, frequencyDefault: 4, allowed() { - return tech.haveGunCheck("wave beam") && !tech.isPhaseVelocity && tech.waveLengthRange === 130 && tech.waveReflections === 1 + return tech.haveGunCheck("wave beam") && !tech.isPhaseVelocity }, - requires: "wave beam, not phase velocity, packet length, bound state", + requires: "wave beam, not phase velocity ", effect() { tech.isLongitudinal = true; for (i = 0, len = b.guns.length; i < len; i++) { //find which gun @@ -4026,6 +4002,37 @@ tech.isLongitudinal = false; } }, + { + name: "isotropic radiator", + description: "wave beam expands in all directions
range reduced 40% and damage increased 50%", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 4, + frequencyDefault: 4, + allowed() { + return tech.isLongitudinal + }, + requires: "phonon", + effect() { + tech.is360Longitudinal = true; + for (i = 0, len = b.guns.length; i < len; i++) { //find which gun + if (b.guns[i].name === "wave beam") { + b.guns[i].chooseFireMethod() + break + } + } + }, + remove() { + tech.is360Longitudinal = false; + for (i = 0, len = b.guns.length; i < len; i++) { //find which gun + if (b.guns[i].name === "wave beam") { + b.guns[i].chooseFireMethod() + break + } + } + } + }, { name: "cruise missile", description: "missiles travel 63% slower,
but have a 50% larger explosive payload", @@ -4432,24 +4439,42 @@ } }, { - name: "irradiated drones", - description: "irradiate the space around your drones
reduce ammo/efficiency by 80%", - //
does damage, harm, and drains energy + name: "torque bursts", + description: "drones rapidly rush towards their target
increase drone collision damage by 33%", isGunTech: true, maxCount: 1, count: 0, frequency: 2, frequencyDefault: 2, allowed() { - return tech.droneCycleReduction === 1 && !tech.isIncendiary && (tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField))) + return tech.haveGunCheck("drones") && !tech.isDroneRadioactive + }, + requires: "drone gun", + effect() { + tech.isDroneTeleport = true + }, + remove() { + tech.isDroneTeleport = false + } + }, + { + name: "irradiated drones", + description: "irradiate the space around your drones
reduce ammo/efficiency by 75%", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.droneCycleReduction === 1 && !tech.isIncendiary && !tech.isDroneTeleport && (tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField))) }, requires: "drone gun, not reduced tolerances or incendiary", effect() { tech.isDroneRadioactive = true for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "drones") { - b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * 0.2 - b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 0.2) + b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * 0.25 + b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 0.25) } } }, @@ -4459,7 +4484,7 @@ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "drones") { b.guns[i].ammoPack = b.guns[i].defaultAmmoPack - b.guns[i].ammo = b.guns[i].ammo * 5 + b.guns[i].ammo = b.guns[i].ammo * 4 } } } @@ -4583,7 +4608,7 @@ }, { name: "electrostatic induction", - description: "foam bullets are electrically charged
causing attraction to nearby mobs", + description: "foam bubbles are electrically charged
causing attraction to nearby mobs", isGunTech: true, maxCount: 1, count: 0, @@ -5173,7 +5198,7 @@ m.energy = 0.01; b.randomBot() b.randomBot() - // b.randomBot() + b.randomBot() }, remove() {} }, @@ -5726,7 +5751,7 @@ }, { name: "traversable geodesics", - description: "your bullets can traverse wormholes
spawn 2 guns and ammo", + description: "your projectiles can traverse wormholes
spawn 2 guns and ammo", isFieldTech: true, maxCount: 1, count: 0, @@ -6299,13 +6324,16 @@ if ( tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && - !tech.tech[i].isJunk + !tech.tech[i].isJunk && + !tech.tech.isLore ) { - for (let j = 0; j < tech.tech[i].frequency; j++) options.push(i); + options.push(i); } } - const index = options[Math.floor(Math.random() * options.length)] - tech.tech[index].frequency = 100 + if (options.length) { + const index = options[Math.floor(Math.random() * options.length)] + tech.tech[index].frequency = 100 + } }, remove() {} }, @@ -7445,10 +7473,8 @@ isMobBlockFling: null, blockingIce: null, isPhaseVelocity: null, - wavePacketLength: null, waveBeamSpeed: null, wavePacketAmplitude: null, - waveLengthRange: null, isCollisionRealitySwitch: null, iceIXOnDeath: null, wimpCount: null, @@ -7473,10 +7499,12 @@ laserColor: null, laserColorAlpha: null, isLongitudinal: null, + is360Longitudinal: null, isShotgunReversed: null, wormDuplicate: null, isCloakingDamage: null, harmonicEnergy: null, isFieldHarmReduction: null, - isFastTime: null + isFastTime: null, + isDroneTeleport: null } \ No newline at end of file diff --git a/todo.txt b/todo.txt index 68eafff..9e34faf 100644 --- a/todo.txt +++ b/todo.txt @@ -1,29 +1,30 @@ ******************************************************** NEXT PATCH ******************************************************** -shieldingBoss stops re-shielding after taking damage - 25% more health - re-shielding Cooldown is 25% shorter +"pressure wave" renamed "phonon" + tech packet length removed + most wave beam tech is now compatible with phonon -you can pick up ammo with laser again - it was too annoying to switch guns +wave beam tech: isotropic radiator - phonon has shorter range but expands in every direction -you have 1/2 second harm immunity after leaving a portal +drone tech: torque bursts - teleport towards targets and do 30% more collision damage -lore conversations are better at recovering from speech API freezes - (if the speech API doesn't work after 10 seconds it switches to pure text) +irradiated drones do 33% more damage, 33% less collisions damage + 5% more ammo, 30% less range, don't lose duration on collisions + +pseudoscience only gets 3 free rerolls per tech ******************************************************** TODO ******************************************************** -so JUNK tech in experiment mode? +give drones or spores some mobs abilities + striker: teleport towards target -new wave tech - reduce range, but make bullets circles, not arcs +drone tech: snakes + I haven't thought about this much, but I don't know make them look like snakes... scrolling console history in pause menu? also make tech, guns scrolling? - -consider executables: - press F to do things - ideas: +in testing mode console log the body you click on +pause should at least show the last in game console message make the player get a buff after using wormhole while energy lasts: drain energy and give damage buff @@ -33,8 +34,6 @@ tech: quantized shields - harmonic standing wave field can only lose 33 energy p the blocked value only scales up to 2x or 4x (33 energy) blocked doesn't stack with spherical tech -in testing mode console log the body you click on - make a tech that improves all charge guns for: pulse, foam, rail gun effect: @@ -58,8 +57,10 @@ tech: use the ability for power ups to have custom code attracted to other power ups explode if they touch? -pause should show the last in game console message - +consider executables: + press F to do things + ideas: + nail-gun, or .... 1s after being fired your bullets turn: towards the nearest mob @@ -352,6 +353,8 @@ possible names for tech Laplace's demon was a notable published articulation of causal determinism on a scientific basis by Pierre-Simon Laplace in 1814.[1] According to determinism, if someone (the demon) knows the precise location and momentum of every atom in the universe, their past and future values for any given time are entailed; they can be calculated from the laws of classical mechanics. evolutionary cosmology eternal inflation + hypergraph + gnarl a tutorial / lore intro needs to be optional so it doesn't slow experienced players