diff --git a/js/bullet.js b/js/bullet.js index b672669..57d523e 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -1484,54 +1484,17 @@ const b = { index: 3, isInternal: false }, { - x: 34, - y: 5, + x: 37, + y: 3, index: 4, isInternal: false }], - - // [{ - // x: -10, - // y: 2, - // index: 0, - // isInternal: false - // }, { - // x: -10, - // y: -2, - // index: 1, - // isInternal: false - // }, { - // x: 35, - // y: -3, - // index: 2, - // isInternal: false - // }, { - // x: 37, - // y: -2, - // index: 3, - // isInternal: false - // }, { - // x: 40, - // y: 0, - // index: 4, - // isInternal: false - // }, { - // x: 37, - // y: 2, - // index: 5, - // isInternal: false - // }, { - // x: 35, - // y: 3, - // index: 6, - // isInternal: false - // }], { angle: angle, friction: 1, frictionAir: 0.4, thrustMag: 0.13, - dmg: 6, //damage done in addition to the damage from momentum + dmg: 8, //damage done in addition to the damage from momentum classType: "bullet", endCycle: simulation.cycle + 70, isSlowPull: false, @@ -1543,6 +1506,70 @@ const b = { // lookFrequency: Math.floor(7 + Math.random() * 3), density: 0.004, //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed drain: 0.001, + draw() { + const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) } + const sub = Vector.sub(where, this.vertices[0]) + const controlPoint = Vector.add(where, Vector.mult(sub, -0.5)) + //draw rope + ctx.beginPath(); + ctx.moveTo(where.x, where.y); + ctx.quadraticCurveTo(controlPoint.x, controlPoint.y, this.vertices[0].x, this.vertices[0].y) + // ctx.lineTo(this.vertices[0].x, this.vertices[0].y); + // if (tech.isHookWire) { + // //draw wire + // const hitMob = Matter.Query.ray(mob, this.position, m.pos, 10) + // if (hitMob.length && m.immuneCycle < m.cycle) { + // for (let i = 0; i < hitMob.length; i++) { + // console.log(hitMob[i].bodyA) + // // simulation.drawList.push({ //add dmg to draw queue + // // x: path[path.length - 1].x, + // // y: path[path.length - 1].y, + // // radius: Math.sqrt(2000 * damage * best.who.damageReduction) + 2, + // // color: tech.laserColorAlpha, + // // time: simulation.drawTime + // // }); + // hitMob[i].bodyA.damage(0.001) + // } + // } + // //draw glow around wire + // ctx.strokeStyle = "rgba(0,255,255,0.2)" // "#0ce" + // ctx.lineWidth = 20 + // ctx.stroke(); + // } + ctx.strokeStyle = "rgba(0,255,255,0.2)" // "#0ce" + ctx.lineWidth = 10 + ctx.stroke(); + ctx.strokeStyle = "#000" // "#0ce" + ctx.lineWidth = 0.5 + ctx.stroke(); + + + + //draw harpoon spikes + // ctx.beginPath(); + // ctx.lineTo(this.vertices[3].x, this.vertices[3].y); + // // const spike1 = Vector.add(this.vertices[1], Vector.mult(Vector.sub(this.vertices[1], this.vertices[2]), 3)) + // // ctx.lineTo(spike1.x, spike1.y); + // const controlPoint2 = Vector.add(this.vertices[3], Vector.mult(Vector.sub(this.vertices[3], this.vertices[2]), 20)) + // ctx.quadraticCurveTo(controlPoint2.x, controlPoint2.y, this.vertices[2].x, this.vertices[2].y) + // ctx.fillStyle = '#000' + // ctx.fill(); + + + ctx.beginPath(); + ctx.lineTo(this.vertices[0].x, this.vertices[0].y); + const spikeLength = 2 + // const spike1 = Vector.add(this.vertices[1], Vector.mult(Vector.sub(this.vertices[1], this.vertices[2]), spikeLength)) + // ctx.moveTo(this.vertices[2].x, this.vertices[2].y); + // ctx.lineTo(spike1.x, spike1.y); + // ctx.lineTo(this.vertices[3].x, this.vertices[3].y); + const spike2 = Vector.add(this.vertices[3], Vector.mult(Vector.sub(this.vertices[3], this.vertices[2]), spikeLength)) + ctx.moveTo(this.vertices[2].x, this.vertices[2].y); + ctx.lineTo(spike2.x, spike2.y); + ctx.lineTo(this.vertices[1].x, this.vertices[1].y); + ctx.fillStyle = '#000' + ctx.fill(); + }, beforeDmg(who) { if (tech.isShieldPierce && who.isShielded) { //disable shields who.isShielded = false @@ -1565,7 +1592,9 @@ const b = { // // this.endCycle = 0; // } if (m.fieldCDcycle < m.cycle + 40) m.fieldCDcycle = m.cycle + 40 //extra long cooldown on hitting mobs + if (tech.isHookExplosion) b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end this.retract() + }, caughtPowerUp: null, dropCaughtPowerUp() { @@ -1594,35 +1623,6 @@ const b = { this.dropCaughtPowerUp() } }, - draw() { - const where = { - x: m.pos.x + 30 * Math.cos(m.angle), - y: m.pos.y + 30 * Math.sin(m.angle) - } - const sub = Vector.sub(where, this.vertices[0]) - const controlPoint = Vector.add(where, Vector.mult(sub, -0.5)) - ctx.strokeStyle = "#000" // "#0ce" - ctx.lineWidth = 0.5 - ctx.beginPath(); - ctx.moveTo(where.x, where.y); - ctx.quadraticCurveTo(controlPoint.x, controlPoint.y, this.vertices[0].x, this.vertices[0].y) - // ctx.lineTo(this.vertices[0].x, this.vertices[0].y); - ctx.stroke(); - //draw harpoon spikes - const spikeLength = 2 - ctx.beginPath(); - const spike1 = Vector.add(this.vertices[1], Vector.mult(Vector.sub(this.vertices[1], this.vertices[2]), spikeLength)) - ctx.moveTo(this.vertices[2].x, this.vertices[2].y); - ctx.lineTo(spike1.x, spike1.y); - ctx.lineTo(this.vertices[3].x, this.vertices[3].y); - - const spike2 = Vector.add(this.vertices[3], Vector.mult(Vector.sub(this.vertices[3], this.vertices[2]), spikeLength)) - ctx.moveTo(this.vertices[2].x, this.vertices[2].y); - ctx.lineTo(spike2.x, spike2.y); - ctx.lineTo(this.vertices[1].x, this.vertices[1].y); - ctx.fillStyle = '#000' - ctx.fill(); - }, retract() { this.do = this.returnToPlayer this.endCycle = simulation.cycle + 60 @@ -1630,7 +1630,8 @@ const b = { if (this.angularSpeed < 0.5) this.torque += this.inertia * 0.001 * (Math.random() - 0.5) //(Math.round(Math.random()) ? 1 : -1) this.collisionFilter.mask = 0//cat.map | cat.mob | cat.mobBullet | cat.mobShield // | cat.body //recoil on pulling grapple back - const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (m.crouch ? 0.0001 : 0.0002)) + const mag = this.pickUpTarget ? Math.max(this.pickUpTarget.mass, 0.5) : 0.5 + const momentum = Vector.mult(Vector.sub(this.position, m.pos), mag * (m.crouch ? 0.0001 : 0.0002)) player.force.x += momentum.x player.force.y += momentum.y }, @@ -1642,7 +1643,20 @@ const b = { const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (m.crouch ? 0.0001 : 0.0002)) player.force.x += momentum.x player.force.y += momentum.y + if (this.pickUpTarget) { + m.holdingTarget = this.pickUpTarget + // give block to player after it returns + m.isHolding = true; + //conserve momentum when player mass changes + totalMomentum = Vector.add(Vector.mult(player.velocity, player.mass), Vector.mult(Vector.normalise(this.velocity), 15 * Math.min(20, this.pickUpTarget.mass))) + Matter.Body.setVelocity(player, Vector.mult(totalMomentum, 1 / (m.defaultMass + this.pickUpTarget.mass))); + m.definePlayerMass(m.defaultMass + this.pickUpTarget.mass * m.holdingMassScale) + //make block collide with nothing + m.holdingTarget.collisionFilter.category = 0; + m.holdingTarget.collisionFilter.mask = 0; + this.pickUpTarget = null + } } else { if (m.energy > this.drain) m.energy -= this.drain const sub = Vector.sub(this.position, m.pos) @@ -1651,10 +1665,11 @@ const b = { this.force.x -= returnForce.x this.force.y -= returnForce.y this.grabPowerUp() + this.grabBlocks() } this.draw(); }, - destroyBlocks() { + destroyBlocks() {//not used? const blocks = Matter.Query.collides(this, body) if (blocks.length && !blocks[0].bodyA.isNotHoldable) { if (blocks[0].bodyA.mass > 2.5) this.retract() @@ -1679,6 +1694,32 @@ const b = { }) } }, + pickUpTarget: null, + grabBlocks() { + if (this.pickUpTarget) { + //position block on hook + Matter.Body.setPosition(this.pickUpTarget, Vector.add(this.vertices[2], this.velocity)) + Matter.Body.setVelocity(this.pickUpTarget, { x: 0, y: 0 }) + } else if (!input.down) { + const blocks = Matter.Query.collides(this, body) + if (blocks.length) { + // console.log(blocks) + for (let i = 0; i < blocks.length; i++) { + if (blocks[i].bodyA.classType === "body" && !blocks[i].bodyA.isNotHoldable && !blocks[0].bodyA.mass < 60) { + this.retract() + this.pickUpTarget = blocks[i].bodyA + if (tech.isHookExplosion) b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end + } else if (blocks[i].bodyB.classType === "body" && !blocks[i].bodyB.isNotHoldable && !blocks[0].bodyB.mass < 60) { + this.retract() + this.pickUpTarget = blocks[i].bodyB + if (tech.isHookExplosion) b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end + } + } + // if (blocks[0].bodyA.mass > 2.5 && blocks[0].bodyA.mass > 15) { + + } + } + }, grabPowerUp() { //grab power ups near the tip of the harpoon if (this.caughtPowerUp) { Matter.Body.setPosition(this.caughtPowerUp, Vector.add(this.vertices[2], this.velocity)) @@ -1695,7 +1736,7 @@ const b = { powerUp[i].collisionFilter.mask = 0 this.thrustMag *= 0.6 this.endCycle += 0.5 //it pulls back slower, so this prevents it from ending early - this.retract() + // this.retract() break //just pull 1 power up if possible } } @@ -1706,7 +1747,8 @@ const b = { do() { if (m.fieldCDcycle < m.cycle + 5) m.fieldCDcycle = m.cycle + 5 if (input.field) { //&& !Matter.Query.collides(this, body).length - this.destroyBlocks() + // this.destroyBlocks() + this.grabBlocks() this.grabPowerUp() // if (this.endCycle < simulation.cycle + 1) { //if at end of lifespan, but player is holding down field, force retraction // this.endCycle = simulation.cycle + 30 @@ -1736,6 +1778,7 @@ const b = { if (input.field && Matter.Query.collides(this, map).length) { Matter.Body.setPosition(this, Vector.add(this.position, { x: -20 * Math.cos(this.angle), y: -20 * Math.sin(this.angle) })) if (Matter.Query.collides(this, map).length) { + if (tech.isHookExplosion) b.explosion(this.position, 150 + 50 * Math.random()); //makes bullet do explosive damage at end Matter.Body.setVelocity(this, { x: 0, y: 0 }); Matter.Sleeping.set(this, true) this.endCycle = simulation.cycle + 5 diff --git a/js/engine.js b/js/engine.js index 7a0b708..0374fcd 100644 --- a/js/engine.js +++ b/js/engine.js @@ -204,6 +204,24 @@ function collisionChecks(event) { // time: 25 // }); } + // if (true) { //fire harpoons at mobs after getting hit + // const countMax = 12 + // let count = countMax + // const range = 300 + // for (let i = 0; i < mob.length; i++) { + // if (count > 0 && Vector.magnitude(Vector.sub(m.pos, mob[i].position)) < range) { + // count-- + // if (m.fieldCDcycle < m.cycle + 30) m.fieldCDcycle = m.cycle + 30 + // const angle = Math.atan2(mob[i].position.y - player.position.y, mob[i].position.x - player.position.x); + // b.harpoon(m.pos, mob[i], angle, 0.75, true, 20) // harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) { + // for (; count > 0; count--) { + // b.harpoon(m.pos, mob[i], count * Math.PI / countMax, 0.75, true, 9) // harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) { + // bullet[bullet.length - 1].drain = 0 + // } + // break + // } + // } + // } if (tech.isStimulatedEmission) powerUps.ejectTech() if (mob[k].onHit) mob[k].onHit(); if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles diff --git a/js/index.js b/js/index.js index b852be9..54eff25 100644 --- a/js/index.js +++ b/js/index.js @@ -524,12 +524,10 @@ ${simulation.isCheating ? "

lore disabled" : ""} if (!aHasKeyword && bHasKeyword) return 1; return 0; } - if (find === 'guntech') { tech.tech.sort((a, b) => { if (a.isGunTech && b.isGunTech) { - if (a.allowed() > b.allowed()) return -1; //sort to the top - if (!a.allowed() < b.allowed()) return 1; //sort to the bottom + return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1; } if (a.isGunTech && !b.isGunTech) return -1; //sort to the top if (!a.isGunTech && b.isGunTech) return 1; //sort to the bottom @@ -538,30 +536,30 @@ ${simulation.isCheating ? "

lore disabled" : ""} } else if (find === 'fieldtech') { tech.tech.sort((a, b) => { if (a.isFieldTech && b.isFieldTech) { - if (a.allowed() > b.allowed()) return -1; //sort to the top - if (!a.allowed() < b.allowed()) return 1; //sort to the bottom + return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1; } if (a.isFieldTech && !b.isFieldTech) return -1; //sort to the top if (!a.isFieldTech && b.isFieldTech) return 1; //sort to the bottom return 0; }); } else if (find === 'allowed') { + // tech.tech.sort((a, b) => { + // if (a.allowed() > !b.allowed()) return -1; //sort to the top + // if (!a.allowed() < b.allowed()) return 1; //sort to the bottom + // return 0; + // }); tech.tech.sort((a, b) => { - if (a.allowed() > b.allowed()) return -1; //sort to the top - if (!a.allowed() < b.allowed()) return 1; //sort to the bottom - return 0; + return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1; }); } else if (find === 'have') { tech.tech.sort((a, b) => { - if (a.count > b.count) return -1; //sort to the top - if (!a.count < b.count) return 1; //sort to the bottom + return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1; return 0; }); } else if (find === 'heal') { tech.tech.sort((a, b) => { if (a.isHealTech && b.isHealTech) { - if (a.allowed() > b.allowed()) return -1; //sort to the top - if (!a.allowed() < b.allowed()) return 1; //sort to the bottom + return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1; } if (a.isHealTech && !b.isHealTech) return -1; //sort to the top if (!a.isHealTech && b.isHealTech) return 1; //sort to the bottom @@ -570,8 +568,7 @@ ${simulation.isCheating ? "

lore disabled" : ""} } else if (find === 'bot') { tech.tech.sort((a, b) => { if (a.isBotTech && b.isBotTech) { - if (a.allowed() > b.allowed()) return -1; //sort to the top - if (!a.allowed() < b.allowed()) return 1; //sort to the bottom + return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1; } if (a.isBotTech && !b.isBotTech) return -1; //sort to the top if (!a.isBotTech && b.isBotTech) return 1; //sort to the bottom @@ -580,8 +577,7 @@ ${simulation.isCheating ? "

lore disabled" : ""} } else if (document.getElementById("sort-input").value === 'skin') { tech.tech.sort((a, b) => { if (a.isSkin && b.isSkin) { - if (a.allowed() > b.allowed()) return -1; //sort to the top - if (!a.allowed() < b.allowed()) return 1; //sort to the bottom + return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1; } if (a.isSkin && !b.isSkin) return -1; //sort to the top if (!a.isSkin && b.isSkin) return 1; //sort to the bottom diff --git a/js/level.js b/js/level.js index 3e00aba..3f1401f 100644 --- a/js/level.js +++ b/js/level.js @@ -19,16 +19,18 @@ const level = { // simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode // simulation.isHorizontalFlipped = true // tech.giveTech("performance") - // level.difficultyIncrease(3 * 4) //30 is near max on hard //60 is near max on why + // level.difficultyIncrease(1 * 4) //30 is near max on hard //60 is near max on why // spawn.setSpawnList(); // spawn.setSpawnList(); // m.maxHealth = m.health = 100 + // m.maxEnergy = m.energy = 10000000 // tech.isRerollDamage = true // powerUps.research.changeRerolls(99999) // m.immuneCycle = Infinity //you can't take damage // tech.tech[297].frequency = 100 // m.couplingChange(10) // m.setField("grappling hook") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook + // tech.isHookWire = true // m.energy = 0 // simulation.molecularMode = 2 // m.damage(0.1); @@ -36,10 +38,8 @@ const level = { // 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.guns[8].ammo = 100000000 // requestAnimationFrame(() => { tech.giveTech("MACHO") }); - // for (let i = 0; i < 1; ++i) tech.giveTech("electrostatic induction") - // for (let i = 0; i < 1; ++i) tech.giveTech("grappling hook") - // for (let i = 0; i < 1; ++i) tech.giveTech("superdeterminism") - // for (let i = 0; i < 1; ++i) tech.giveTech("fine-structure constant") + // for (let i = 0; i < 1; ++i) tech.giveTech("autonomous defense") + // for (let i = 0; i < 1; ++i) tech.giveTech("rupture") // for (let i = 0; i < 1; ++i) tech.giveTech("nail-bot upgrade") // requestAnimationFrame(() => { for (let i = 0; i < 30; i++) tech.giveTech("laser-bot") }); // for (let i = 0; i < 1; i++) tech.giveTech("laser-bot upgrade") @@ -47,11 +47,11 @@ const level = { // for (let i = 0; i < 1; ++i) tech.giveTech("mechanical resonance") // for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research"); - // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); + // for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling"); // level.testing(); // for (let i = 0; i < 4; ++i) spawn.hopMother(1900, -500) - // for (let i = 0; i < 0; ++i) spawn.hopper(1900, -500) + // for (let i = 0; i < 5; ++i) spawn.starter(1900, -500) // for (let i = 0; i < 1; ++i) spawn.shooterBoss(1900, -2500) // spawn.beetleBoss(1900, -500, 25) // spawn.slasher2(2000, -1150) @@ -63,7 +63,8 @@ const level = { // for (let i = 0; i < 40; ++i) tech.giveTech() level[simulation.isTraining ? "walk" : "intro"]() //normal starting level ************************************************** - + // spawn.bodyRect(2425, -120, 200, 200); + // console.log(body[body.length - 1].mass) // simulation.isAutoZoom = false; //look in close // simulation.zoomScale *= 0.5; // simulation.setZoom(); diff --git a/js/player.js b/js/player.js index f269256..459438c 100644 --- a/js/player.js +++ b/js/player.js @@ -2496,7 +2496,6 @@ const m = { // set pick up target for when mouse is released if (body[grabbing.targetIndex]) { m.holdingTarget = body[grabbing.targetIndex]; - // ctx.beginPath(); //draw on each valid body let vertices = m.holdingTarget.vertices; ctx.moveTo(vertices[0].x, vertices[0].y); @@ -2588,6 +2587,8 @@ const m = { return `+${(4 * couple).toFixed(0)}% block collision damage` case 9: //wormhole return `after eating blocks +${(2 * couple).toFixed(0)} energy` + case 10: //grappling hook + return `${powerUps.orb.ammo(1)} give ${(4 * couple).toFixed(0)}% more ammo` } }, couplingChange(change = 0) { @@ -2659,12 +2660,6 @@ const m = { } } }, - //
- //
1
- //
2
- //
3
- //
4
- //
{ name: "standing wave", //deflecting protects you in every direction @@ -3083,7 +3078,20 @@ const m = { for (let i = 0, len = who.length; i < len; ++i) { sub = Vector.sub(who[i].position, m.pos); dist = Vector.magnitude(sub); - if (dist < range) who[i].force.y -= who[i].mass * (simulation.g * mag); + if (dist < range) { + who[i].force.y -= who[i].mass * (simulation.g * mag); //add a bit more then standard gravity + if (input.left) { //blocks move horizontally with the same force as the player + who[i].force.x -= m.FxAir * who[i].mass / 10; // move player left / a + } else if (input.right) { + who[i].force.x += m.FxAir * who[i].mass / 10; //move player right / d + } + } + + + + // sub = Vector.sub(who[i].position, m.pos); + // dist = Vector.magnitude(sub); + // if (dist < range) who[i].force.y -= who[i].mass * (simulation.g * mag); } } //control horizontal acceleration @@ -3825,7 +3833,8 @@ const m = { } if (tech.isRewindField) { this.rewindCount = 0 - m.grabPowerUpRange2 = 300000 + m.grabPowerUpRange2 = 300000// m.grabPowerUpRange2 = 200000; + m.hold = function () { // console.log(m.fieldCDcycle) m.grabPowerUp(); @@ -4944,25 +4953,64 @@ const m = { { name: "grappling hook", // description: `use energy to pull yourself towards the map
generate 6 energy per second`, - description: `use energy to fire a hook that attaches to map,
pulls player, damages mobs, and destroys blocks
generate 6 energy per second`, + description: `use energy to fire a hook that pulls player
damages mobs and destroys blocks
generate 6 energy per second`, effect: () => { m.fieldFire = true; // m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping m.fieldMeterColor = "#333" m.eyeFillColor = m.fieldMeterColor - m.fieldHarmReduction = 0.45; //55% reduction + m.grabPowerUpRange2 = 300000 //m.grabPowerUpRange2 = 200000; + // m.fieldHarmReduction = 0.45; //55% reduction m.hold = function () { - if (input.field) { + if (m.isHolding) { + m.drawHold(m.holdingTarget); + m.holding(); + m.throwBlock(); + } else if (input.field) { + m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) if (m.fieldCDcycle < m.cycle) { if (m.energy > 0.02) m.energy -= 0.02 - const where = { x: m.pos.x + 40 * Math.cos(m.angle), y: m.pos.y + 40 * Math.sin(m.angle) } - b.grapple(where, m.angle) + b.grapple({ x: m.pos.x + 40 * Math.cos(m.angle), y: m.pos.y + 40 * Math.sin(m.angle) }, m.angle) if (m.fieldCDcycle < m.cycle + 20) m.fieldCDcycle = m.cycle + 20 } m.grabPowerUp(); + } else { + m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) + if (tech.isHookDefense && m.energy > 0.33 && m.fieldCDcycle < m.cycle) { + const maxCount = 6 //scale the number of hooks fired + let count = maxCount + const range = 300 + for (let i = 0; i < mob.length; i++) { + if (!mob[i].isBadTarget && + !mob[i].isInvulnerable && + Vector.magnitude(Vector.sub(m.pos, mob[i].position)) < range && + Matter.Query.ray(map, m.pos, mob[i].position).length === 0 + ) { + count-- + m.energy -= 0.2 + if (m.fieldCDcycle < m.cycle + 30) m.fieldCDcycle = m.cycle + 30 + const angle = Math.atan2(mob[i].position.y - player.position.y, mob[i].position.x - player.position.x); + b.harpoon(m.pos, mob[i], angle, 0.75, true, 20) // harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) { + bullet[bullet.length - 1].drain = 0 + for (; count > 0; count--) { + b.harpoon(m.pos, mob[i], angle + count * 2 * Math.PI / maxCount, 0.75, true, 10) + bullet[bullet.length - 1].drain = 0 + } + break + } + } + ctx.beginPath(); + ctx.arc(m.pos.x, m.pos.y, range, 0, 2 * Math.PI); + ctx.strokeStyle = "#000"; + ctx.lineWidth = 0.25; + ctx.setLineDash([10, 30]); + ctx.stroke(); + ctx.setLineDash([]); + } } m.drawRegenEnergy() + //look for nearby mobs and fire harpoons at them } } }, diff --git a/js/powerup.js b/js/powerup.js index 1b27ff1..6ffd71b 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -621,17 +621,18 @@ const powerUps = { return 17; }, effect() { + const couplingExtraAmmo = m.fieldMode === 10 ? 1 + 0.04 * m.coupling : 1 if (b.inventory.length > 0) { powerUps.animatePowerUpGrab('rgba(68, 102, 119,0.25)') if (tech.isAmmoForGun && b.activeGun !== null) { //give extra ammo to one gun only with tech logistics const target = b.guns[b.activeGun] if (target.ammo !== Infinity) { if (tech.ammoCap) { - const ammoAdded = Math.ceil(target.ammoPack * 0.7 * tech.ammoCap * 0.8) //0.7 is average + const ammoAdded = Math.ceil(target.ammoPack * 0.7 * tech.ammoCap * 0.8 * couplingExtraAmmo) //0.7 is average target.ammo = ammoAdded // simulation.makeTextLog(`${target.name}.ammo = ${ammoAdded}`) } else { - const ammoAdded = Math.ceil((0.7 * Math.random() + 0.7 * Math.random()) * target.ammoPack * 0.8) + const ammoAdded = Math.ceil((0.7 * Math.random() + 0.7 * Math.random()) * target.ammoPack * 0.8 * couplingExtraAmmo) target.ammo += ammoAdded // simulation.makeTextLog(`${target.name}.ammo += ${ammoAdded}`) } @@ -642,11 +643,12 @@ const powerUps = { const target = b.guns[b.inventory[i]] if (target.ammo !== Infinity) { if (tech.ammoCap) { - const ammoAdded = Math.ceil(target.ammoPack * 0.45 * tech.ammoCap) //0.45 is average + const ammoAdded = Math.ceil(target.ammoPack * 0.45 * tech.ammoCap * couplingExtraAmmo) //0.45 is average target.ammo = ammoAdded // textLog += `${target.name}.ammo = ${ammoAdded}
` - } else { - const ammoAdded = Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack) //Math.ceil(Math.random() * target.ammoPack) + } else { //default ammo behavior + const ammoAdded = Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack * couplingExtraAmmo) //Math.ceil(Math.random() * target.ammoPack) + // console.log(ammoAdded, Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack)) target.ammo += ammoAdded // textLog += `${target.name}.ammo += ${ammoAdded}
` } @@ -1270,24 +1272,25 @@ const powerUps = { } for (let i = 0; i < localSettings.entanglement.techIndexes.length; i++) { //add tech let choose = localSettings.entanglement.techIndexes[i] - const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count + 1}x)` : ""; - - if (choose === null || tech.tech[choose].count + 1 > tech.tech[choose].maxCount || !tech.tech[choose].allowed()) { - // text += `
${tech.tech[choose].name} - incoherent
` - text += powerUps.incoherentTechText(choose) - } else { - if (tech.tech[choose].isFieldTech) { - text += powerUps.fieldTechText(choose, `powerUps.choose('tech',${choose})`) - } else if (tech.tech[choose].isGunTech) { - text += powerUps.gunTechText(choose, `powerUps.choose('tech',${choose})`) - } else if (tech.tech[choose].isLore) { - text += `
  ${tech.tech[choose].name} ${isCount}
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}
` - } else if (tech.tech[choose].isJunk) { - text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`) - } else if (tech.tech[choose].isSkin) { - text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`) - } else { //normal tech - text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`) + if (tech.tech[choose]) { + const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count + 1}x)` : ""; + if (choose === null || tech.tech[choose].count + 1 > tech.tech[choose].maxCount || !tech.tech[choose].allowed()) { + // text += `
${tech.tech[choose].name} - incoherent
` + text += powerUps.incoherentTechText(choose) + } else { + if (tech.tech[choose].isFieldTech) { + text += powerUps.fieldTechText(choose, `powerUps.choose('tech',${choose})`) + } else if (tech.tech[choose].isGunTech) { + text += powerUps.gunTechText(choose, `powerUps.choose('tech',${choose})`) + } else if (tech.tech[choose].isLore) { + text += `
  ${tech.tech[choose].name} ${isCount}
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}
` + } else if (tech.tech[choose].isJunk) { + text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`) + } else if (tech.tech[choose].isSkin) { + text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`) + } else { //normal tech + text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`) + } } } } diff --git a/js/tech.js b/js/tech.js index 9c4a5cb..2c835f9 100644 --- a/js/tech.js +++ b/js/tech.js @@ -4545,7 +4545,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return (!tech.isLargeHarpoon && tech.haveGunCheck("harpoon")) || tech.isNeedles + return (!tech.isLargeHarpoon && tech.haveGunCheck("harpoon")) || tech.isNeedles || tech.isHookDefense }, requires: "needle gun, harpoon, not Bessemer process", effect() { @@ -5149,7 +5149,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return ((tech.haveGunCheck("super balls") || tech.isSuperMine) && !tech.isSuperBounce) || (tech.haveGunCheck("harpoon") && !tech.fragments) + return ((tech.haveGunCheck("super balls") || tech.isSuperMine) && !tech.isSuperBounce) || (tech.haveGunCheck("harpoon") && !tech.fragments) || tech.isHookDefense }, requires: "super balls, harpoon, not fragmentation", effect() { @@ -5574,7 +5574,7 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return !tech.isExplodeRadio && ((tech.haveGunCheck("harpoon") && !tech.isFoamBall) || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount || tech.isRivets || tech.blockDamage > 0.075) + return !tech.isExplodeRadio && ((tech.haveGunCheck("harpoon") && !tech.isFoamBall) || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount || tech.isRivets || tech.blockDamage > 0.075 || tech.isHookDefense) }, requires: "grenades, missiles, rivets, harpoon, or mass driver, not iridium-192, not polyurethane foam", effect() { @@ -7784,7 +7784,7 @@ const tech = { }, { name: "inertial mass", - description: "negative mass is larger and faster
blocks also move horizontally with the field", + description: "negative mass is larger and faster", //
blocks also move horizontally with the field isFieldTech: true, maxCount: 1, count: 0, @@ -8052,7 +8052,7 @@ const tech = { }, { name: "electric generator", - description: "after deflecting mobs
molecular assembler generates +50 energy", + description: "after deflecting mobs
molecular assembler generates +50 energy", isFieldTech: true, maxCount: 9, count: 0, @@ -8754,6 +8754,82 @@ const tech = { tech.isWormholeMapIgnore = false } }, + { + name: "autonomous defense", + description: "grappling hook uses 20 energy
to fire harpoons at nearby mobs", + isFieldTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return m.fieldMode === 10 + }, + requires: "grappling hook", + effect() { + tech.isHookDefense = true + }, + remove() { + tech.isHookDefense = false + } + }, + { + name: "rupture", + description: "after grappling hook impacts solid objects
generate an explosion", + isFieldTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return m.fieldMode === 10 + }, + requires: "grappling hook", + effect() { + tech.isHookExplosion = true + }, + remove() { + tech.isHookExplosion = false + } + }, + // { + // name: "autonomous defense", + // description: "if you collide with a mob
fire harpoons at nearby mobs", + // isFieldTech: true, + // maxCount: 1, + // count: 0, + // frequency: 2, + // frequencyDefault: 2, + // allowed() { + // return m.fieldMode === 10 && !tech.isHookDefense + // }, + // requires: "grappling hook, not automatic offense", + // effect() { + // tech.isHookDefense = true + // }, + // remove() { + // tech.isHookDefense = false + // } + // }, + // { + // name: "wire", + // description: "", + // isFieldTech: true, + // maxCount: 1, + // count: 0, + // frequency: 2, + // frequencyDefault: 2, + // allowed() { + // return m.fieldMode === 10 + // }, + // requires: "grappling hook", + // effect() { + // tech.isHookWire = true + // }, + // remove() { + // tech.isHookWire = false + // } + // }, //************************************************** //************************************************** experimental //************************************************** modes @@ -11800,4 +11876,7 @@ const tech = { isHealBrake: null, isMassProduction: null, isPrinter: null, + // isHookWire: null, + isHookDefense: null, + isHookExplosion: null, } \ No newline at end of file diff --git a/todo.txt b/todo.txt index 76a7a9c..bd298b9 100644 --- a/todo.txt +++ b/todo.txt @@ -1,39 +1,29 @@ ******************************************************** NEXT PATCH ************************************************** -grappling hook is now a field (work in progress) - reworked physics to allow faster speeds, but more control - improved rate of power up grabbing - more player control to hook retraction rate - changed hook shape and field image graphics - grappling hook field coupling, more tech, bug fixes, and general polish to be added soon +grappling hook + added coupling effect - 4% extra ammo per coupling + doesn't destroy blocks, instead the player grabs blocks + doesn't automatically retract after hitting power ups + improved momentum conservation on yank and catching blocks, power ups + removed accidental 55% defense for grapple field + tech (no images yet) + autonomous defense - fire harpoons at nearby mobs + rupture - explosion on impact with map, block, mob -aerostat - 88->100% damage in air 22-> 25% damage on ground -foam damage reduced 10%, ammo increased about 10% -after hitting an invulnerable mob (drones,spores,worms,iceIX,fleas) don't die or lose cycles -added JUNK tech: mobs! - summon 20 random mobs -added announcement of mob names in console at start of new level - -bug fixes +negative mass field has horizontal block motion by default +fixed tech sorting by "allowed tech" in experiment mode *********************************************************** TODO ***************************************************** grappling hook is a field check for places that the player could get into but not out of - maybe grapple could grab more then 1 power up? - grapple slices blocks - cut large blocks into 2,3 - use dead mob code for mobs > 5 sides - write code to cut large blocks in half and remove one half - need several field tech - new field tech ideas - increase hook damage - hook damage aura - hook's line does damage - make several auto targeting harpoons after taking damage - how to make them not drain energy - generate ___ after destroying blocks - energy, drones, iceIX, explosion, nails, junk bots? - coupling effect: defense?, bonus from ammo power ups, fire rate + field tech ideas + hook and line stuns? + increase hook damage + hook damage aura + hook's line does damage + generate ___ after destroying blocks + energy, drones, iceIX, explosion, nails, junk bots? tech - killing a mob heals for the last damage you took disable cloaking heal? maybe you don't need to disable, just don't heal twice