From 2a5a4781a99a776c2e9a8df9d0597ca83f84d39c Mon Sep 17 00:00:00 2001 From: landgreen Date: Sat, 9 Apr 2022 14:17:55 -0700 Subject: [PATCH] 2 more classic n-gon dates added 2 more classic n-gon dates plasma ball does 10% more damage moves 20% faster targets mob bullets better standing wave has a 45/60->30/60 second cooldown after blocking a shielded mob but, standing wave now also triggers it's CD on shields that protect groups of mobs JUNK tech: Mech v4.48 removed JUNK tech: cosmogonic myth - opens a random classic version of n-gon in a new tab, after 5 minutes close the tab and spawn 1 of every tech bug fixes --- index.html | 2 + js/bullet.js | 35 +++++------------- js/index.js | 2 + js/level.js | 14 +++---- js/player.js | 96 +++++++++++++++++++++++++++++++++--------------- js/powerup.js | 5 +-- js/simulation.js | 6 ++- js/spawn.js | 20 +++++----- js/tech.js | 76 ++++++++++++++++++++++++++++++++++---- todo.txt | 75 +++++++++++++++++++++++++++---------- 10 files changed, 227 insertions(+), 104 deletions(-) diff --git a/index.html b/index.html index 1d32e17..e1eec7b 100644 --- a/index.html +++ b/index.html @@ -120,6 +120,8 @@ + +
diff --git a/js/bullet.js b/js/bullet.js index 9030363..49671c4 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -1531,25 +1531,6 @@ const b = { }) let dist = Vector.magnitude(sub) if (input.fire) { - //control position while hooked - // if (input.down) { //down - // player.force.y += 5 * player.mass * simulation.g; - // dist *= 0.25 - // this.ropeExtension += 10 - // } else if (input.up) { //up - // this.ropeExtension -= 10 - // if (this.ropeExtension < 0) this.ropeExtension = 0 - // player.force.y -= 5 * player.mass * simulation.g; - // dist *= 0.4 - // } else {} - - // if (input.right) { //down - // dist *= 0.4 - // player.force.x += 5 * player.mass * simulation.g; - // } else if (input.left) { //up - // dist *= 0.4 - // player.force.x -= 5 * player.mass * simulation.g; - // } m.fireCDcycle = m.cycle + 30; // cool down if out of energy this.endCycle = simulation.cycle + 10 if (input.down) { //down @@ -1608,7 +1589,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) { + harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true) { 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 }], { @@ -1723,11 +1704,13 @@ const b = { player.force.x += momentum.x player.force.y += momentum.y // refund ammo - for (i = 0, len = b.guns.length; i < len; i++) { //find which gun - if (b.guns[i].name === "harpoon") { - b.guns[i].ammo++; - simulation.updateGunHUD(); - break; + if (isReturnAmmo) { + for (i = 0, len = b.guns.length; i < len; i++) { //find which gun + if (b.guns[i].name === "harpoon") { + b.guns[i].ammo++; + simulation.updateGunHUD(); + break; + } } } } else { @@ -6404,7 +6387,7 @@ const b = { } } if (input.down) { - b.harpoon(where, null, m.angle, harpoonSize, true, 1.5 * totalCycles) + b.harpoon(where, null, m.angle, harpoonSize, true, 1.5 * totalCycles, (input.down && tech.crouchAmmoCount && (tech.crouchAmmoCount - 1) % 2) ? false : true) } else { b.harpoon(where, closest.target, m.angle, harpoonSize, true, totalCycles) } diff --git a/js/index.js b/js/index.js index 66ce301..7ef6e2e 100644 --- a/js/index.js +++ b/js/index.js @@ -1252,7 +1252,9 @@ if (localSettings.isAllowed && !localSettings.isEmpty) { document.getElementById("fps-select").value = localSettings.fpsCapDefault } else { console.log('setting default localSettings') + const isAllowed = localSettings.isAllowed //don't overwrite isAllowed value localSettings = { + isAllowed: isAllowed, personalSeeds: [], isJunkExperiment: false, isCommunityMaps: false, diff --git a/js/level.js b/js/level.js index 6ad2cfe..a6bef15 100644 --- a/js/level.js +++ b/js/level.js @@ -17,10 +17,13 @@ const level = { if (level.levelsCleared === 0) { //this code only runs on the first level // simulation.isHorizontalFlipped = true // m.setField("metamaterial cloaking") - // b.giveGuns("harpoon") + // b.giveGuns("drones") + // tech.giveTech("desublimated ammunition") + // tech.giveTech("smelting") + // tech.giveTech("smelting") + // tech.giveTech("616") // tech.giveTech("grappling hook") - // tech.giveTech("discount") - // tech.giveTech("shape-memory alloy") + // tech.giveTech("coyote") // for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech"); // for (let i = 0; i < 2; i++) tech.giveTech("corona discharge") // for (let i = 10; i < tech.tech.length; i++) { tech.tech[i].isBanished = true } @@ -112,10 +115,7 @@ const level = { if ((tech.isRelay || tech.isFlipFlop) && !tech.isFlipFlopOn) { tech.isFlipFlopOn = true if (tech.isFlipFlopHealth) m.setMaxHealth() - if (tech.isRelayEnergy) { - m.setMaxEnergy() - m.energy += 2 - } + if (tech.isRelayEnergy) m.setMaxEnergy() m.eyeFillColor = m.fieldMeterColor simulation.makeTextLog(`tech.isFlipFlopOn = true`); } diff --git a/js/player.js b/js/player.js index 29b8ead..3ebe9bd 100644 --- a/js/player.js +++ b/js/player.js @@ -233,6 +233,7 @@ const m = { }, buttonCD_jump: 0, //cool down for player buttons jump() { + // if (!m.onGround) m.lastOnGroundCycle = 0 //m.cycle - tech.coyoteTime m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass //apply a fraction of the jump force to the body the player is jumping off of Matter.Body.applyForce(m.standingOn, m.pos, { @@ -287,6 +288,7 @@ const m = { }, airControl() { //check for coyote time jump + // if (input.up && m.buttonCD_jump + 20 + tech.coyoteTime < m.cycle && m.yOffWhen.stand > 23 && m.lastOnGroundCycle + tech.coyoteTime > m.cycle) m.jump() if (input.up && m.buttonCD_jump + 20 < m.cycle && m.yOffWhen.stand > 23 && m.lastOnGroundCycle + 5 > m.cycle) m.jump() //check for short jumps //moving up //recently pressed jump //but not pressing jump key now @@ -969,7 +971,7 @@ const m = { } }, setMaxEnergy() { - m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2 * tech.isGroundState + 2 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy simulation.makeTextLog(`m.maxEnergy = ${(m.maxEnergy.toFixed(2))}`) }, fieldMeterColor: "#0cf", @@ -1558,7 +1560,7 @@ const m = { m.pushMass(mob[i]); this.drainCD = m.cycle + 10 } - if (mob[i].isShielded) m.fieldCDcycle = m.cycle + 45 + if (mob[i].isShielded || mob[i].shield) m.fieldCDcycle = m.cycle + 30 } } } @@ -1587,7 +1589,7 @@ const m = { m.pushMass(mob[i]); this.drainCD = m.cycle + 10 } - if (mob[i].isShielded) m.fieldCDcycle = m.cycle + 45 + if (mob[i].isShielded || mob[i].shield) m.fieldCDcycle = m.cycle + 30 } } } @@ -2111,14 +2113,14 @@ const m = { isOn: false, drain: 0.0015, radiusLimit: 10, - damage: 0.6, + damage: 0.7, setPositionToNose() { const nose = { x: m.pos.x + 10 * Math.cos(m.angle), y: m.pos.y + 10 * Math.sin(m.angle) } Matter.Body.setPosition(this, Vector.add(nose, Vector.mult(Vector.normalise(Vector.sub(nose, m.pos)), this.circleRadius))); }, fire() { this.isAttached = false; - const speed = 6 //scale with mass? + const speed = 7 //scale with mass? Matter.Body.setVelocity(this, { x: player.velocity.x * 0.4 + speed * Math.cos(m.angle), y: speed * Math.sin(m.angle) @@ -2194,7 +2196,7 @@ const m = { const arcList = [] const dischargeRange = 150 + 1600 * tech.plasmaDischarge + 1.3 * this.circleRadius for (let i = 0, len = mob.length; i < len; i++) { - if (!mob[i].isBadTarget && mob[i].alive) { + if (mob[i].alive && (!mob[i].isBadTarget || mob[i].isMobBullet)) { const sub = Vector.magnitude(Vector.sub(this.position, mob[i].position)) if (sub < this.circleRadius + mob[i].radius) { if (!this.isAttached && !mob[i].isMobBullet) this.isPopping = true @@ -2251,8 +2253,8 @@ const m = { //slowly slow down if too fast - if (this.speed > 8) { - const scale = 0.997 + if (this.speed > 10) { + const scale = 0.998 Matter.Body.setVelocity(this, { x: scale * this.velocity.x, y: scale * this.velocity.y @@ -2744,8 +2746,44 @@ const m = { // m.fieldDamage = 2.46 // 1 + 146/100 m.fieldDrawRadius = 0 m.isSneakAttack = true; - const drawRadius = 900 - + const drawRadius = 800 + m.drawCloak = function() { + m.fieldPhase += 0.007 + const wiggle = 0.15 * Math.sin(m.fieldPhase * 0.5) + ctx.beginPath(); + ctx.ellipse(m.pos.x, m.pos.y, m.fieldDrawRadius * (1 - wiggle), m.fieldDrawRadius * (1 + wiggle), m.fieldPhase, 0, 2 * Math.PI); + // if (m.fireCDcycle > m.cycle && (input.field)) {} + ctx.fillStyle = "#fff" + ctx.lineWidth = 2; + ctx.strokeStyle = "#000" + ctx.stroke() + // ctx.fillStyle = "#fff" //`rgba(0,0,0,${0.5+0.5*m.energy})`; + ctx.globalCompositeOperation = "destination-in"; + ctx.fill(); + ctx.globalCompositeOperation = "source-over"; + ctx.clip(); + } + // m.drawCloak = function() { //controlled by player look direction + // m.fieldPhase = m.angle + // const wiggle = 0.15 * Math.sin(m.angle) + // const off = { + // x: Math.cos(m.angle), + // y: Math.sin(m.angle) + // } + // const look = Vector.add(m.pos, Vector.mult(off, 500)) + // ctx.beginPath(); + // ctx.ellipse(look.x, look.y, m.fieldDrawRadius * (1 - wiggle), m.fieldDrawRadius * (1 + wiggle), m.fieldPhase, 0, 2 * Math.PI); + // // if (m.fireCDcycle > m.cycle && (input.field)) {} + // ctx.fillStyle = "#fff" + // ctx.lineWidth = 2; + // ctx.strokeStyle = "#000" + // ctx.stroke() + // // ctx.fillStyle = "#fff" //`rgba(0,0,0,${0.5+0.5*m.energy})`; + // ctx.globalCompositeOperation = "destination-in"; + // ctx.fill(); + // ctx.globalCompositeOperation = "source-over"; + // ctx.clip(); + // } m.hold = function() { // console.log(m.holdingTarget) if (m.isHolding) { @@ -2805,32 +2843,32 @@ const m = { } } - function drawField() { - m.fieldPhase += 0.007 - const wiggle = 0.15 * Math.sin(m.fieldPhase * 0.5) - ctx.beginPath(); - ctx.ellipse(m.pos.x, m.pos.y, m.fieldDrawRadius * (1 - wiggle), m.fieldDrawRadius * (1 + wiggle), m.fieldPhase, 0, 2 * Math.PI); - // if (m.fireCDcycle > m.cycle && (input.field)) {} - ctx.fillStyle = "#fff" - ctx.lineWidth = 2; - ctx.strokeStyle = "#000" - ctx.stroke() - // ctx.fillStyle = "#fff" //`rgba(0,0,0,${0.5+0.5*m.energy})`; - ctx.globalCompositeOperation = "destination-in"; - ctx.fill(); - ctx.globalCompositeOperation = "source-over"; - ctx.clip(); - } + // function drawField() { + // m.fieldPhase += 0.007 + // const wiggle = 0.15 * Math.sin(m.fieldPhase * 0.5) + // ctx.beginPath(); + // ctx.ellipse(m.pos.x, m.pos.y, m.fieldDrawRadius * (1 - wiggle), m.fieldDrawRadius * (1 + wiggle), m.fieldPhase, 0, 2 * Math.PI); + // // if (m.fireCDcycle > m.cycle && (input.field)) {} + // ctx.fillStyle = "#fff" + // ctx.lineWidth = 2; + // ctx.strokeStyle = "#000" + // ctx.stroke() + // // ctx.fillStyle = "#fff" //`rgba(0,0,0,${0.5+0.5*m.energy})`; + // ctx.globalCompositeOperation = "destination-in"; + // ctx.fill(); + // ctx.globalCompositeOperation = "source-over"; + // ctx.clip(); + // } // const energy = Math.max(0.01, Math.min(m.energy, 1)) if (m.isCloak) { this.fieldRange = this.fieldRange * 0.9 + 0.1 * drawRadius m.fieldDrawRadius = this.fieldRange * 0.88 //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy)); - drawField() - } else if (this.fieldRange < 3000) { + m.drawCloak() + } else if (this.fieldRange < 4000) { this.fieldRange += 50 m.fieldDrawRadius = this.fieldRange //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy)); - drawField() + m.drawCloak() } if (tech.isIntangible) { if (m.isCloak) { diff --git a/js/powerup.js b/js/powerup.js index bd4e84e..6b53eb3 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -889,10 +889,7 @@ const powerUps = { if (document.getElementById("tech-switch")) document.getElementById("tech-switch").innerHTML = ` = ON` m.eyeFillColor = m.fieldMeterColor //'#0cf' } - if (tech.isRelayEnergy) { - m.setMaxEnergy(); - m.energy += 2 - } + if (tech.isRelayEnergy) m.setMaxEnergy(); } }, // giveRandomAmmo() { diff --git a/js/simulation.js b/js/simulation.js index d8e1880..50581cb 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -822,7 +822,8 @@ const simulation = { level.zones = []; simulation.drawList = []; - if (tech.isDronesTravel && player.alive) { + if (tech.isDronesTravel && m.alive) { + console.log('hi') //count drones let count = 0 let deliveryCount = 0 @@ -946,7 +947,7 @@ const simulation = { } } - if (m.pos.y > simulation.fallHeight || isNaN(player.position.x)) { // if 4000px deep + if (m.pos.y > simulation.fallHeight) { // if 4000px deep Matter.Body.setVelocity(player, { x: 0, y: 0 @@ -971,6 +972,7 @@ const simulation = { m.damage(0.1 * simulation.difficultyMode); m.energy -= 0.1 * simulation.difficultyMode } + if (isNaN(player.position.x)) m.death(); // if (tech.isEnergyDamage) { // document.getElementById("tech-capacitor").innerHTML = `(+${(m.energy/0.05).toFixed(0)}%)` diff --git a/js/spawn.js b/js/spawn.js index 5e4e4b6..93b4150 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -335,7 +335,7 @@ const spawn = { let count = 0 function loop() { - if (!simulation.paused) { + if (!simulation.paused && !simulation.onTitlePage) { count++ if (count < 660) { if (count === 1) simulation.makeTextLog(`//enter testing mode to set level.levels.length to Infinite`); @@ -359,13 +359,15 @@ const spawn = { document.getElementById("fade-out").style.opacity = 1; //slowly fades out // build.shareURL(false) setTimeout(function() { - simulation.paused = true; - // simulation.clearMap(); - // Matter.Composite.clear(composite, keepStatic, [deep = false]) - // Composite.clear(engine.composite); - engine.world.bodies.forEach((body) => { Matter.Composite.remove(engine.world, body) }) - Engine.clear(engine); - simulation.splashReturn(); + if (!simulation.onTitlePage) { + simulation.paused = true; + // simulation.clearMap(); + // Matter.Composite.clear(composite, keepStatic, [deep = false]) + // Composite.clear(engine.composite); + engine.world.bodies.forEach((body) => { Matter.Composite.remove(engine.world, body) }) + Engine.clear(engine); + simulation.splashReturn(); + } }, 6000); return } @@ -376,7 +378,7 @@ const spawn = { simulation.makeTextLog(`level.levels.length = Infinite`); }, 1500); } else { - requestAnimationFrame(loop); + if (!simulation.onTitlePage) requestAnimationFrame(loop); } } requestAnimationFrame(loop); diff --git a/js/tech.js b/js/tech.js index ef0cb01..e7eae40 100644 --- a/js/tech.js +++ b/js/tech.js @@ -705,6 +705,34 @@ const tech = { m.setMovement() } }, + // { + // name: "coyote", + // description: "", + // maxCount: 1, + // count: 0, + // frequency: 1, + // frequencyDefault: 1, + // allowed() { return true }, + // requires: "", + // effect() { // good with melee builds, content skipping builds + // tech.coyoteTime = 120 + // // simulation.gravity = function() { + // // function addGravity(bodies, magnitude) { + // // for (var i = 0; i < bodies.length; i++) { + // // bodies[i].force.y += bodies[i].mass * magnitude; + // // } + // // } + // // if (!m.isBodiesAsleep) { + // // addGravity(powerUp, simulation.g); + // // addGravity(body, simulation.g); + // // } + // // player.force.y += player.mass * simulation.g + // // } + // }, + // remove() { + // tech.coyoteTime = 5 + // } + // }, { name: "Newton's 1st law", description: "moving at high speeds
reduces harm by up to 66%", @@ -1816,7 +1844,7 @@ const tech = { }, { name: "lithium-ion", - description: "if relay switch is in the ON state
increase your maximum energy by 200", + description: "if relay switch is in the ON state
increase your maximum energy by 300", maxCount: 1, count: 0, frequency: 4, @@ -7510,6 +7538,25 @@ const tech = { }, remove() {} }, + { + name: "hi", + description: `spawn to seed`, + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isJunk: true, + allowed() { + return true + }, + requires: "", + effect() { + document.getElementById("seed").placeholder = Math.initialSeed = String(616) + Math.seed = Math.abs(Math.hash(Math.initialSeed)) //update randomizer seed in case the player changed it + + }, + remove() {} + }, { name: "meteor shower", description: "take a shower, but meteors instead of water", @@ -7553,7 +7600,7 @@ const tech = { }, { name: "Higgs phase transition", - description: "instantly spawn 3 tech, but add a chance to
remove everything with a 5 minute half-life", + description: "instantly spawn 5 tech, but add a chance to
remove everything with a 5 minute half-life", maxCount: 1, count: 0, frequency: 0, @@ -7566,8 +7613,10 @@ const tech = { requires: "", effect() { powerUps.spawn(m.pos.x, m.pos.y, "tech"); - powerUps.spawn(m.pos.x + 20, m.pos.y, "tech"); - powerUps.spawn(m.pos.x + 40, m.pos.y, "tech"); + powerUps.spawn(m.pos.x + 30, m.pos.y, "tech"); + powerUps.spawn(m.pos.x + 60, m.pos.y, "tech"); + powerUps.spawn(m.pos.x, m.pos.y - 30, "tech"); + powerUps.spawn(m.pos.x + 30, m.pos.y - 60, "tech"); function loop() { // (1-X)^cycles = chance to be removed //Math.random() < 0.000019 10 min @@ -9226,8 +9275,8 @@ const tech = { remove() {} }, { - name: "Mech v4.48", - description: `open a portal to a primordial version of reality`, + name: "cosmogonic myth", + description: `open a portal to a primordial version of reality
after 5 minutes close the portal, and spawn 1 of every power up`, maxCount: 1, count: 0, frequency: 0, @@ -9236,7 +9285,19 @@ const tech = { allowed() { return true }, requires: "", effect() { - window.open('https://scratch.mit.edu/projects/14005697/fullscreen/', '_blank') + const urls = ["https://scratch.mit.edu/projects/14005697/fullscreen/", "https://scratch.mit.edu/projects/22573757/fullscreen/", "https://codepen.io/lilgreenland/full/ozXNWZ", "https://codepen.io/lilgreenland/full/wzARJY", "classic/7-1-2017/", "classic/4-15-2018/", "classic/7-11-2019/", "classic/9-8-2019/", "classic/7-15-2020/", "classic/6-1-2021/"] + const choose = urls[Math.floor(Math.random() * urls.length)] + console.log(`opening new tab" ${choose}`) + let tab = window.open(choose, "_blank"); + setTimeout(() => { + tab.close(); + powerUps.spawn(m.pos.x, m.pos.y, "gun"); + setTimeout(() => { powerUps.spawn(m.pos.x, m.pos.y - 50, "ammo") }, 250); + setTimeout(() => { powerUps.spawn(m.pos.x + 50, m.pos.y, "field"); }, 500); + setTimeout(() => { powerUps.spawn(m.pos.x + 50, m.pos.y - 50, "heal"); }, 750); + setTimeout(() => { powerUps.spawn(m.pos.x - 50, m.pos.y, "tech"); }, 1000); + setTimeout(() => { powerUps.spawn(m.pos.x - 50, m.pos.y - 50, "research"); }, 1250); + }, 1000 * 5); }, remove() {} }, @@ -9687,4 +9748,5 @@ const tech = { plasmaDischarge: null, isFlipFlopHealth: null, isRelayEnergy: null, + coyoteTime: null } \ No newline at end of file diff --git a/todo.txt b/todo.txt index bc4630b..c23c0a6 100644 --- a/todo.txt +++ b/todo.txt @@ -1,18 +1,64 @@ ******************************************************** NEXT PATCH ************************************************** -added 5 cycles of "coyote time" - this means you can still jump for 5/60 = 0.1 seconds after leaving the ground - let me know if you like the feel - this might cause some unexpected bugs, or reduce the difficulty of some platforming levels +added 2 more classic n-gon dates -JUNK tech: NFT - buy your current game seed - no one is allow to use your seeds - if they use them they are gonna get in trouble +plasma ball + does 10% more damage + moves 20% faster + targets mob bullets better + +standing wave has a 45/60->30/60 second cooldown after blocking a shielded mob + but, standing wave now also triggers it's CD on shields that protect groups of mobs + +JUNK tech: Mech v4.48 removed +JUNK tech: cosmogonic myth - opens a random classic version of n-gon in a new tab, after 5 minutes close the tab and spawn 1 of every tech + +bug fixes -removed the pavilion/ruins map to see if it's causing bugs ******************************************************** TODO ******************************************************** +bugs: requirement text man discord messages + +bring back: + missiles that fall back and down for a sec after they fire + the old phase decoherence field + make cloak only active on input.field down + could be a tech + would need some other buff + how to make it good enough + combine with not killing tech? + stun mobs that touch you while phased + firing doesn't exit you from cloak + but it does drain some energy + tech pilot wave: Bose Einstein condensate - freeze mobs in superposition with pilot wave + +plasma ball + graphics should look more like a real plasma ball + gently scale damage with circleRadius + balance corona discharge + delay on returning to player is annoying + scale float effect with ball size + tech upgrades + greatly improve floating effects while holding + black hole: gives the plasma ball gravity + stun on expansion + plasma orb increases in size and power as it eats enemies + while attached? + +make level.do() graphic that only shows direction player is facing + pattern it after cloaking field + will it work with cloaking field at the same time + +double jump? + +tech coyote time + you can still jump for 2 seconds after falling off a ledge + make it a JUNK tech? so you can keep the name + some other benefit + reduce your gravity also? + increase jump? + tech smoke grenades - mobs inside a cloud can't see player draw on the region so it's hard for player to see as well you'd have to make something similar to MACHO that exists after an explosion goes off @@ -26,18 +72,6 @@ tech mines: mines fire _____ instead of nails super balls? foam? -plasma ball - gently scale damage with circleRadius - balance corona discharge - delay on returning to player is annoying - scale float effect with ball size - tech upgrades - greatly improve floating effects while holding - black hole: gives the plasma ball gravity - stun on expansion - plasma orb increases in size and power as it eats enemies - while attached? - tech: frozen mobs die at 10% life tech: harpoons stick into enemies @@ -703,6 +737,7 @@ possible names for tech particle accelerator superluminal signalling NP-complete + lenticular lens: is an array of lenses, designed so that when viewed from slightly different angles, different parts of the image underneath are shown. a tutorial / lore intro needs to be optional so it doesn't slow experienced players