From 47eeafab08b118b6d4a6cc490542e6194edea543 Mon Sep 17 00:00:00 2001 From: landgreen Date: Wed, 1 Jan 2020 18:09:03 -0800 Subject: [PATCH] recursive mods, gaurdian mod --- js/bullets.js | 524 +++++++++++++++++++++++++++++++------------------ js/engine.js | 4 +- js/game.js | 5 +- js/index.js | 24 ++- js/level.js | 5 +- js/player.js | 12 +- js/powerups.js | 8 +- 7 files changed, 375 insertions(+), 207 deletions(-) diff --git a/js/bullets.js b/js/bullets.js index aed1b46..f452d18 100644 --- a/js/bullets.js +++ b/js/bullets.js @@ -12,7 +12,7 @@ const b = { modHealthDrain: null, modNoAmmo: null, isModBulletsLastLonger: null, - modIsImmortal: null, + isModImmortal: null, modSpores: null, isModImmuneExplosion: null, isModDroneOnDamage: null, @@ -20,13 +20,14 @@ const b = { annihilation: null, isModRecursiveHealing: null, modSquirrelFx: null, - modIsCrit: null, + isModCrit: null, isModBayesian: null, isModLowHealthDmg: null, isModFarAwayDmg: null, isModEntanglement: null, isModMassEnergy: null, - modIsFourOptions: null, + isModFourOptions: null, + modGuardianCount: null, setModDefaults() { b.modCount = 0; b.modFireRate = 1; @@ -38,180 +39,220 @@ const b = { b.modHealthDrain = 0; b.modNoAmmo = 0; b.isModBulletsLastLonger = 1; - b.modIsImmortal = false; + b.isModImmortal = false; b.modSpores = 0; b.modExtraDmg = 0; - b.modAnnihilation = false; + b.isModAnnihilation = false; b.isModRecursiveHealing = false; b.modSquirrelFx = 1; - b.modIsCrit = false; + b.isModCrit = false; b.isModBayesian = 0; - b.modIsFourOptions = false; + b.isModFourOptions = false; b.isModLowHealthDmg = false; b.isModFarAwayDmg = false; b.isModEntanglement = false; b.isModMassEnergy = false; + b.modGuardianCount = 0; mech.Fx = 0.015; mech.jumpForce = 0.38; mech.throwChargeRate = 2; mech.throwChargeMax = 50; mech.maxHealth = 1; for (let i = 0; i < b.mods.length; i++) { - b.mods[i].have = false; + b.mods[i].count = 0 } }, mods: [{ name: "depleted uranium rounds", - description: "your bullets are 10% larger
increased mass and physical damage", - have: false, //0 - effect: () => { - //good for guns that do mostly projectile damage: - //testing at 1.08: spray(point blank)(+0.25), one shot(+0.16), wave beam(point blank)(+0.14) - b.modBulletSize = 1.1; + description: `your bullets are 11% larger
increased mass and physical damage`, + //0 + count: 0, + maxCount: 4, + value: 1.11, + effect() { + b.modBulletSize *= this.value; + this.value -= 0.01 + this.description = `your bullets are ${Math.floor((this.value-1)*100)}% larger
increased mass and physical damage` } }, { name: "fluoroantimonic acid", description: "each bullet does extra chemical damage
instant damage, unaffected by momentum", - have: false, //1 - effect: () => { //good with guns that fire many bullets at low speeds, minigun, drones, junk-bots, shotgun, superballs, wavebeam - b.modExtraDmg = 0.25 + //1 + maxCount: 4, + count: 0, + effect() { //good with guns that fire many bullets at low speeds, minigun, drones, junk-bots, shotgun, superballs, wavebeam + b.modExtraDmg += 0.25 game.playerDmgColor = "rgba(0,80,80,0.9)" } }, { name: "fracture analysis", description: "5x physical damage to unaware enemies
unaware enemies don't have a health bar", - have: false, //2 - effect: () => { // good with high damage guns that strike from a distance: rail gun, drones, flechettes, spores, grenade, vacuum bomb - b.modIsCrit = true; + //2 + maxCount: 1, + count: 0, + effect() { // good with high damage guns that strike from a distance: rail gun, drones, flechettes, spores, grenade, vacuum bomb + b.isModCrit = true; } }, { name: "kinetic bombardment", description: "do extra damage from a distance
up to 50% increase at about 30 steps away", - have: false, //3 - effect: () => { // good with annihilation, melee builds + //3 + maxCount: 1, + count: 0, + effect() { // good with annihilation, melee builds b.isModFarAwayDmg = true; //used in mob.damage() } }, { name: "quasistatic equilibrium", description: "do extra damage at low health
up to 50% increase when near death", - have: false, //4 - effect: () => { // good with annihilation, melee builds + //4 + maxCount: 1, + count: 0, + effect() { // good with annihilation, melee builds b.isModLowHealthDmg = true; //used in mob.damage() } }, { name: "auto-loading heuristics", - description: "your delay after firing is 15% shorter", - have: false, //5 - effect: () => { //good for guns with extra ammo: needles, M80, rapid fire, flak, super balls - b.modFireRate = 0.85 + description: "your delay after firing is 12% shorter", + //5 + maxCount: 4, + count: 0, + effect() { //good for guns with extra ammo: needles, M80, rapid fire, flak, super balls + b.modFireRate *= 0.88 } }, { name: "desublimated ammunition", description: "use 50% less ammo when crouching", - have: false, //6 - effect: () => { //good with guns that have less ammo: one shot, grenades, missiles, super balls, spray + //6 + maxCount: 1, + count: 0, + effect() { //good with guns that have less ammo: one shot, grenades, missiles, super balls, spray b.modNoAmmo = 1 } }, { name: "Lorentzian topology", description: "your bullets last 33% longer", - have: false, //7 - effect: () => { //good with: drones, super balls, spore, missiles, wave beam(range), rapid fire(range), flak(range) - b.isModBulletsLastLonger = 1.33 + //7 + maxCount: 4, + count: 0, + effect() { //good with: drones, super balls, spore, missiles, wave beam(range), rapid fire(range), flak(range) + b.isModBulletsLastLonger += 0.33 } }, { name: "zoospore vector", description: "enemies can discharge spores on death
spores seek out enemies", - have: false, //8 - effect: () => { //good late game maybe? - b.modSpores = 0.15; + //8 + maxCount: 4, + count: 0, + effect() { //good late game maybe? + b.modSpores += 0.15; } }, { name: "ablative synthesis", description: "rebuild your broken parts as drones
chance to occur after being harmed", - have: false, //9 - effect: () => { //makes dangerous situations more survivable + //9 + maxCount: 1, + count: 0, + effect() { //makes dangerous situations more survivable b.isModDroneOnDamage = true; } }, { name: "annihilation", description: "after touching enemies, they are annihilated", - have: false, //10 - effect: () => { //good with mods that heal: superconductive healing, entropy transfer - b.modAnnihilation = true + //10 + maxCount: 1, + count: 0, + effect() { //good with mods that heal: superconductive healing, entropy transfer + b.isModAnnihilation = true } }, { name: "high explosives", - description: "explosions are 33% larger
immune to harm from explosions", - have: false, //11 + description: "the radius of explosions are 20% larger
immune to harm from explosions", + //11 + maxCount: 4, + count: 0, effect: () => { - b.modExplosionRadius = 1.2; + b.modExplosionRadius += 0.2; b.isModImmuneExplosion = true; } }, { name: "entanglement", description: "using your first gun reduces harm
scales by 7% for each gun in your inventory", - have: false, //12 - effect: () => { // good with laser-bots + //12 + maxCount: 1, + count: 0, + effect() { // good with laser-bots b.isModEntanglement = true } }, { name: "energy transfer", description: "gain energy proportional to damage done", - have: false, //13 - effect: () => { //good with laser, and all fields - b.modEnergySiphon = 0.18; + //13 + maxCount: 4, + count: 0, + effect() { //good with laser, and all fields + b.modEnergySiphon += 0.18; } }, { name: "entropy transfer", description: "heal proportional to damage done", - have: false, //14 - effect: () => { //good with guns that overkill: one shot, grenade - b.modHealthDrain = 0.015; + //14 + maxCount: 4, + count: 0, + effect() { //good with guns that overkill: one shot, grenade + b.modHealthDrain += 0.015; } }, { name: "overcharge", description: "charge energy 33% beyond your maximum", - have: false, //15 - effect: () => { - mech.fieldEnergyMax = 1.33 + //15 + maxCount: 4, + count: 0, + effect() { + mech.fieldEnergyMax += 0.33 } }, { name: "supersaturation", description: "heal 33% beyond your max health", - have: false, //16 - effect: () => { - mech.maxHealth = 1.33 + //16 + maxCount: 4, + count: 0, + effect() { + mech.maxHealth += 0.33 } }, { name: "recursive healing", description: "healing power ups are twice as effective", - have: false, //17 - effect: () => { // good with ablative synthesis, melee builds + //17 + maxCount: 1, + count: 0, + effect() { // good with ablative synthesis, melee builds b.isModRecursiveHealing = true } }, { name: "mass-energy equivalence", description: "convert the mass of power ups into energy
power ups fill your energy and heal for +5%", - have: false, //18 + //18 + maxCount: 1, + count: 0, effect: () => { b.isModMassEnergy = true // used in mech.usePowerUp } @@ -219,34 +260,53 @@ const b = { { name: "+1 cardinality", description: "one extra choice when selecting power ups", - have: false, //19 + //19 + maxCount: 1, + count: 0, effect: () => { - b.modIsFourOptions = true; + b.isModFourOptions = true; } }, { name: "Bayesian inference", - description: "25% chance for double power ups to drop
one fewer choice when selecting power ups", - have: false, //20 + description: "20% chance for double power ups to drop
one fewer choice when selecting power ups", + //20 + maxCount: 1, + count: 0, effect: () => { - b.isModBayesian = 0.25; + b.isModBayesian = 0.20; } }, { name: "Gauss rifle", description: "launch blocks at much higher speeds
hold onto larger blocks even after getting hit", - have: false, //21 - effect: () => { // good with guns that run out of ammo + //21 + maxCount: 1, + count: 0, + effect() { // good with guns that run out of ammo mech.throwChargeRate = 4; mech.throwChargeMax = 150; mech.holdingMassScale = 0.05; //can hold heavier blocks with lower cost to jumping } }, + { + name: "guardian", + description: "a bot protects the space around you
uses a short range laser that drains energy", + //22 + maxCount: 4, + count: 0, + effect() { // good with melee builds, content skipping builds + b.modGuardianCount++; + b.guardian(); + } + }, { name: "squirrel-cage rotor", description: "jump higher and move faster
reduced harm from falling ", - have: false, //22 - effect: () => { // good with melee builds, content skipping builds + //23 + maxCount: 1, + count: 0, + effect() { // good with melee builds, content skipping builds b.modSquirrelFx = 1.2; mech.Fx = 0.015 * b.modSquirrelFx; mech.jumpForce = 0.38 * 1.1; @@ -255,9 +315,11 @@ const b = { { name: "quantum immortality", description: "after dying, continue in an alternate reality
guns, ammo, and field are randomized", - have: false, //23 - effect: () => { - b.modIsImmortal = true; + //24 + maxCount: 1, + count: 0, + effect() { + b.isModImmortal = true; } }, ], @@ -265,7 +327,7 @@ const b = { if (index === 'random') { let options = []; for (let i = 0; i < b.mods.length; i++) { - if (!b.mods[i].have) options.push(i); + if (b.mods[i].count < b.mods[i].maxCount) options.push(i); } // give a random mod from the mods I don't have @@ -275,8 +337,8 @@ const b = { } } else { b.mods[index].effect(); //give specific mod - b.modCount++ - b.mods[index].have = true + b.mods[index].count++ + b.modCount++ //used in power up randomization game.updateModHUD(); } }, @@ -756,8 +818,101 @@ const b = { y: speed * Math.sin(dir) }); }, - giveGuns(gun = "random", ammoPacks = 2) { + guardian(speed = 1) { + const me = bullet.length; + const dir = mech.angle; + const RADIUS = (13 + 10 * Math.random()) * b.modBulletSize //(22 + 10 * Math.random()) * b.modBulletSize + bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 3, RADIUS, { + angle: dir, + friction: 0, + frictionStatic: 0, + restitution: 0.5 + 0.5 * Math.random(), + dmg: 0, // 0.14 //damage done in addition to the damage from momentum + minDmgSpeed: 2, + lookFrequency: 37 + Math.floor(27 * Math.random()), + acceleration: 0.0015 + 0.0013 * Math.random(), + range: 500 + Math.floor(200 * Math.random()), + endCycle: Infinity, + classType: "bullet", + collisionFilter: { + category: cat.bullet, + mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield + }, + lockedOn: null, + onDmg() { + this.lockedOn = null + }, + onEnd() {}, + do() { + if (!(game.cycle % this.lookFrequency)) { + this.lockedOn = null; + let closeDist = this.range; + for (let i = 0, len = mob.length; i < len; ++i) { + const DIST = Vector.magnitude(Vector.sub(this.vertices[0], mob[i].position)); + if (DIST - mob[i].radius < closeDist && + Matter.Query.ray(map, this.vertices[0], mob[i].position).length === 0 && + Matter.Query.ray(body, this.vertices[0], mob[i].position).length === 0) { + closeDist = DIST; + this.lockedOn = mob[i] + } + } + } + if (this.lockedOn && this.lockedOn.alive && mech.fieldMeter > 0.15) { //hit target with laser + mech.fieldMeter -= 0.001 + + //make sure you can still see target + const DIST = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.position)); + if (DIST - this.lockedOn.radius < this.range + 150 && + Matter.Query.ray(map, this.vertices[0], this.lockedOn.position).length === 0 && + Matter.Query.ray(body, this.vertices[0], this.lockedOn.position).length === 0) { + //find the closest vertex + let bestVertexDistance = Infinity + let bestVertex = null + for (let i = 0; i < this.lockedOn.vertices.length; i++) { + const dist = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.vertices[i])); + if (dist < bestVertexDistance) { + bestVertex = i + bestVertexDistance = dist + } + } + const dmg = b.dmgScale * 0.03; + this.lockedOn.damage(dmg); + this.lockedOn.locatePlayer(); + + ctx.beginPath(); //draw laser + ctx.moveTo(this.vertices[0].x, this.vertices[0].y); + ctx.lineTo(this.lockedOn.vertices[bestVertex].x, this.lockedOn.vertices[bestVertex].y); + ctx.strokeStyle = "#f00"; + ctx.lineWidth = "2" + ctx.lineDashOffset = 300 * Math.random() + ctx.setLineDash([50 + 100 * Math.random(), 100 * Math.random()]); + ctx.stroke(); + ctx.setLineDash([0, 0]); + ctx.beginPath(); + ctx.arc(this.lockedOn.vertices[bestVertex].x, this.lockedOn.vertices[bestVertex].y, Math.sqrt(dmg) * 100, 0, 2 * Math.PI); + ctx.fillStyle = "#f00"; + ctx.fill(); + } + } + const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos)) + if (distanceToPlayer > this.range * 0.2) { //if far away move towards player + this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.acceleration) + this.frictionAir = 0.02 + } else { //close to player + this.frictionAir = 0 + //add player's velocity + Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 1), Vector.mult(player.velocity, 0.02))); + } + } + }) + World.add(engine.world, bullet[me]); //add bullet to world + Matter.Body.setVelocity(bullet[me], { + x: speed * Math.cos(dir), + y: speed * Math.sin(dir) + }); + }, + giveGuns(gun = "random", ammoPacks = 2) { if (gun === "random") { //find what guns player doesn't have options = [] @@ -768,12 +923,10 @@ const b = { //randomly pick from list of possible guns gun = options[Math.floor(Math.random() * options.length)] } - if (gun === "all") { b.activeGun = 0; b.inventoryGun = 0; for (let i = 0; i < b.guns.length; i++) { - b.guns[i].have = true; b.guns[i].ammo = b.guns[i].ammoPack * ammoPacks; b.inventory[i] = i; } @@ -799,7 +952,7 @@ const b = { const dir = mech.angle + (Math.random() - 0.5) * ((mech.crouch) ? 0.04 : 0.12); bullet[me] = Bodies.rectangle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 17 * b.modBulletSize, 5 * b.modBulletSize, b.fireAttributes(dir)); b.fireProps(mech.crouch ? 10 : 5, mech.crouch ? 50 : 36, dir, me); //cd , speed - bullet[me].endCycle = game.cycle + Math.floor(65 * b.isModBulletsLastLonger); + bullet[me].endCycle = game.cycle + 65; bullet[me].frictionAir = mech.crouch ? 0.007 : 0.01; bullet[me].do = function () { this.force.y += this.mass * 0.0005; @@ -829,7 +982,7 @@ const b = { x: SPEED * Math.cos(dir), y: SPEED * Math.sin(dir) }); - bullet[me].endCycle = game.cycle + Math.floor(55 * b.isModBulletsLastLonger); + bullet[me].endCycle = game.cycle + 55 bullet[me].frictionAir = 0.03; bullet[me].do = function () { this.force.y += this.mass * 0.001; @@ -901,7 +1054,7 @@ const b = { const me = bullet.length; bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(mech.angle), mech.pos.y + 40 * Math.sin(mech.angle), 45 * b.modBulletSize, 1.4 * b.modBulletSize, b.fireAttributes(mech.angle)); - bullet[me].endCycle = game.cycle + Math.floor(180 * b.isModBulletsLastLonger); + bullet[me].endCycle = game.cycle + 180; bullet[me].dmg = 1; bullet[me].do = function () { if (this.speed < 10) this.force.y += this.mass * 0.0003; //no gravity until it slows don to improve aiming @@ -1004,7 +1157,7 @@ const b = { this.isCharging = false mech.fireCDcycle = mech.cycle + 2; // set fire cool down Matter.Body.scale(this, 8000, 8000) // show the bullet by scaling it up (don't judge me... I know this is a bad way to do it) - this.endCycle = game.cycle + Math.floor(140 * b.isModBulletsLastLonger) + this.endCycle = game.cycle + 140 this.collisionFilter.category = cat.bullet Matter.Body.setPosition(this, { x: mech.pos.x, @@ -1233,7 +1386,6 @@ const b = { this.lockedOn = null; let closeDist = Infinity; - //look for closest target to where the missile will be in 30 cycles const futurePos = Vector.add(this.position, Vector.mult(this.velocity, 30)) // ctx.beginPath(); //draw future pos @@ -1307,7 +1459,7 @@ const b = { mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 25 : 10) * b.modFireRate); // cool down b.muzzleFlash(30); const SPEED = mech.crouch ? 29 : 25 - const END = Math.floor((mech.crouch ? 30 : 18) * b.isModBulletsLastLonger); + const END = Math.floor(mech.crouch ? 30 : 18); const side1 = 17 * b.modBulletSize const side2 = 4 * b.modBulletSize const totalBullets = 5 @@ -1351,7 +1503,7 @@ const b = { b.fireProps(mech.crouch ? 30 : 20, mech.crouch ? 43 : 32, dir, me); //cd , speed Matter.Body.setDensity(bullet[me], 0.0005); bullet[me].totalCycles = 100; - bullet[me].endCycle = game.cycle + Math.floor((mech.crouch ? 120 : 80) * b.isModBulletsLastLonger); + bullet[me].endCycle = game.cycle + Math.floor(mech.crouch ? 120 : 80); bullet[me].restitution = 0.5; bullet[me].explodeRad = 290; bullet[me].onEnd = b.explode; //makes bullet do explosive damage before despawn @@ -1486,7 +1638,7 @@ const b = { const dir = mech.angle; bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 15 * b.modBulletSize, b.fireAttributes(dir, false)); b.fireProps(mech.crouch ? 60 : 40, mech.crouch ? 34 : 22, dir, me); //cd , speed - bullet[me].endCycle = game.cycle + Math.floor(60 * b.isModBulletsLastLonger); + bullet[me].endCycle = game.cycle + 60 bullet[me].restitution = 0.3; // bullet[me].frictionAir = 0.01; // bullet[me].friction = 0.15; @@ -1601,106 +1753,106 @@ const b = { mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 25 : 10) * b.modFireRate); // cool down } }, - { - name: "guardian", //13 - description: "deploy a bot that protects you for one level
uses a short range laser that drains energy", - ammo: 0, - ammoPack: 1, - have: false, - isStarterGun: false, - fire() { - const dir = mech.angle; - const me = bullet.length; - const RADIUS = (13 + 10 * Math.random()) * b.modBulletSize //(22 + 10 * Math.random()) * b.modBulletSize - bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 3, RADIUS, { - angle: dir, - friction: 0, - frictionStatic: 0, - restitution: 0.5 + 0.5 * Math.random(), - dmg: 0, // 0.14 //damage done in addition to the damage from momentum - minDmgSpeed: 2, - lookFrequency: 37 + Math.floor(27 * Math.random()), - acceleration: 0.0015 + 0.0013 * Math.random(), - range: 500 + Math.floor(200 * Math.random()), - endCycle: Infinity, - classType: "bullet", - collisionFilter: { - category: cat.bullet, - mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield - }, - lockedOn: null, - onDmg() { - this.lockedOn = null - }, - onEnd() {}, - do() { - if (!(game.cycle % this.lookFrequency)) { - this.lockedOn = null; - let closeDist = this.range; - for (let i = 0, len = mob.length; i < len; ++i) { - const DIST = Vector.magnitude(Vector.sub(this.vertices[0], mob[i].position)); - if (DIST - mob[i].radius < closeDist && - Matter.Query.ray(map, this.vertices[0], mob[i].position).length === 0 && - Matter.Query.ray(body, this.vertices[0], mob[i].position).length === 0) { - closeDist = DIST; - this.lockedOn = mob[i] - } - } - } + // { + // name: "guardian", //13 + // description: "deploy a bot that protects you for one level
uses a short range laser that drains energy", + // ammo: 0, + // ammoPack: 1, + // have: false, + // isStarterGun: false, + // fire() { + // const dir = mech.angle; + // const me = bullet.length; + // const RADIUS = (13 + 10 * Math.random()) * b.modBulletSize //(22 + 10 * Math.random()) * b.modBulletSize + // bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 3, RADIUS, { + // angle: dir, + // friction: 0, + // frictionStatic: 0, + // restitution: 0.5 + 0.5 * Math.random(), + // dmg: 0, // 0.14 //damage done in addition to the damage from momentum + // minDmgSpeed: 2, + // lookFrequency: 37 + Math.floor(27 * Math.random()), + // acceleration: 0.0015 + 0.0013 * Math.random(), + // range: 500 + Math.floor(200 * Math.random()), + // endCycle: Infinity, + // classType: "bullet", + // collisionFilter: { + // category: cat.bullet, + // mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield + // }, + // lockedOn: null, + // onDmg() { + // this.lockedOn = null + // }, + // onEnd() {}, + // do() { + // if (!(game.cycle % this.lookFrequency)) { + // this.lockedOn = null; + // let closeDist = this.range; + // for (let i = 0, len = mob.length; i < len; ++i) { + // const DIST = Vector.magnitude(Vector.sub(this.vertices[0], mob[i].position)); + // if (DIST - mob[i].radius < closeDist && + // Matter.Query.ray(map, this.vertices[0], mob[i].position).length === 0 && + // Matter.Query.ray(body, this.vertices[0], mob[i].position).length === 0) { + // closeDist = DIST; + // this.lockedOn = mob[i] + // } + // } + // } - if (this.lockedOn && this.lockedOn.alive && mech.fieldMeter > 0.15) { //hit target with laser - mech.fieldMeter -= 0.001 + // if (this.lockedOn && this.lockedOn.alive && mech.fieldMeter > 0.15) { //hit target with laser + // mech.fieldMeter -= 0.001 - //make sure you can still see target - const DIST = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.position)); - if (DIST - this.lockedOn.radius < this.range + 150 && - Matter.Query.ray(map, this.vertices[0], this.lockedOn.position).length === 0 && - Matter.Query.ray(body, this.vertices[0], this.lockedOn.position).length === 0) { - //find the closest vertex - let bestVertexDistance = Infinity - let bestVertex = null - for (let i = 0; i < this.lockedOn.vertices.length; i++) { - const dist = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.vertices[i])); - if (dist < bestVertexDistance) { - bestVertex = i - bestVertexDistance = dist - } - } - const dmg = b.dmgScale * 0.03; - this.lockedOn.damage(dmg); - this.lockedOn.locatePlayer(); + // //make sure you can still see target + // const DIST = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.position)); + // if (DIST - this.lockedOn.radius < this.range + 150 && + // Matter.Query.ray(map, this.vertices[0], this.lockedOn.position).length === 0 && + // Matter.Query.ray(body, this.vertices[0], this.lockedOn.position).length === 0) { + // //find the closest vertex + // let bestVertexDistance = Infinity + // let bestVertex = null + // for (let i = 0; i < this.lockedOn.vertices.length; i++) { + // const dist = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.vertices[i])); + // if (dist < bestVertexDistance) { + // bestVertex = i + // bestVertexDistance = dist + // } + // } + // const dmg = b.dmgScale * 0.03; + // this.lockedOn.damage(dmg); + // this.lockedOn.locatePlayer(); - //draw laser - ctx.beginPath(); - ctx.moveTo(this.vertices[0].x, this.vertices[0].y); - ctx.lineTo(this.lockedOn.vertices[bestVertex].x, this.lockedOn.vertices[bestVertex].y); - ctx.strokeStyle = "#f00"; - ctx.lineWidth = "2" - ctx.lineDashOffset = 300 * Math.random() - ctx.setLineDash([50 + 100 * Math.random(), 100 * Math.random()]); - ctx.stroke(); - ctx.setLineDash([0, 0]); - ctx.beginPath(); - ctx.arc(this.lockedOn.vertices[bestVertex].x, this.lockedOn.vertices[bestVertex].y, Math.sqrt(dmg) * 100, 0, 2 * Math.PI); - ctx.fillStyle = "#f00"; - ctx.fill(); - } - } + // //draw laser + // ctx.beginPath(); + // ctx.moveTo(this.vertices[0].x, this.vertices[0].y); + // ctx.lineTo(this.lockedOn.vertices[bestVertex].x, this.lockedOn.vertices[bestVertex].y); + // ctx.strokeStyle = "#f00"; + // ctx.lineWidth = "2" + // ctx.lineDashOffset = 300 * Math.random() + // ctx.setLineDash([50 + 100 * Math.random(), 100 * Math.random()]); + // ctx.stroke(); + // ctx.setLineDash([0, 0]); + // ctx.beginPath(); + // ctx.arc(this.lockedOn.vertices[bestVertex].x, this.lockedOn.vertices[bestVertex].y, Math.sqrt(dmg) * 100, 0, 2 * Math.PI); + // ctx.fillStyle = "#f00"; + // ctx.fill(); + // } + // } - const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos)) - if (distanceToPlayer > this.range * 0.2) { //if far away move towards player - this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.acceleration) - this.frictionAir = 0.02 - } else { //close to player - this.frictionAir = 0 - //add player's velocity - Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 1), Vector.mult(player.velocity, 0.02))); - } - } - }) - b.fireProps(mech.crouch ? 40 : 30, mech.crouch ? 50 : 15, dir, me); //cd , speed - } - }, + // const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos)) + // if (distanceToPlayer > this.range * 0.2) { //if far away move towards player + // this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.acceleration) + // this.frictionAir = 0.02 + // } else { //close to player + // this.frictionAir = 0 + // //add player's velocity + // Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 1), Vector.mult(player.velocity, 0.02))); + // } + // } + // }) + // b.fireProps(mech.crouch ? 40 : 30, mech.crouch ? 50 : 15, dir, me); //cd , speed + // } + // }, { name: "laser", //14 description: "drain energy to emit a beam of coherent light
when crouched, initiate a fusion explosion", @@ -1783,9 +1935,9 @@ const b = { } //use energy to explode - const energy = mech.fieldMeter * 0.25 + const energy = 0.25 * Math.min(mech.fieldMeter, 1.5) mech.fieldMeter -= energy - if (best.who) b.explosion(path[1], 1000 * energy) + if (best.who) b.explosion(path[1], 900 * energy) mech.fireCDcycle = mech.cycle + Math.floor(65 * b.modFireRate); // cool down //draw laser beam @@ -2292,7 +2444,7 @@ const b = { mask: cat.map | cat.body | cat.mob | cat.mobShield }, minDmgSpeed: 0, - endCycle: Infinity, //game.cycle + Math.floor(265 * b.isModBulletsLastLonger), + endCycle: Infinity, count: 0, radius: RADIUS, target: null, diff --git a/js/engine.js b/js/engine.js index ff4ee75..a19c4b3 100644 --- a/js/engine.js +++ b/js/engine.js @@ -142,7 +142,7 @@ function mobCollisionChecks(event) { let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * game.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0 mech.damage(dmg); if (mob[k].onHit) mob[k].onHit(k); - if (b.modAnnihilation && mob[k].dropPowerUp) { + if (b.isModAnnihilation && mob[k].dropPowerUp) { mob[k].death(); game.drawList.push({ //add dmg to draw queue @@ -180,7 +180,7 @@ function mobCollisionChecks(event) { if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) { // const dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity))); let dmg = b.dmgScale * (obj.dmg + b.modExtraDmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity))) - if (b.modIsCrit && !mob[k].seePlayer.recall) dmg *= 5 + if (b.isModCrit && !mob[k].seePlayer.recall) dmg *= 5 mob[k].foundPlayer(); mob[k].damage(dmg); obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn diff --git a/js/game.js b/js/game.js index 97cbcac..7820286 100644 --- a/js/game.js +++ b/js/game.js @@ -168,9 +168,10 @@ const game = { updateModHUD() { let text = "" for (let i = 0, len = b.mods.length; i < len; i++) { //add mods - if (b.mods[i].have) { + if (b.mods[i].count > 0) { if (text) text += "
" //add a new line, but not on the first line text += b.mods[i].name + if (b.mods[i].count > 1) text += ` (${b.mods[i].count}x)` } } document.getElementById("mods").innerHTML = text @@ -447,7 +448,7 @@ const game = { reset() { //run on first run, and each later run after you die b.inventory = []; //removes guns and ammo for (let i = 0, len = b.guns.length; i < len; ++i) { - b.guns[i].have = false; + b.guns[i].count = 0; if (b.guns[i].ammo != Infinity) b.guns[i].ammo = 0; } b.activeGun = null; diff --git a/js/index.js b/js/index.js index 109726c..6c9acdc 100644 --- a/js/index.js +++ b/js/index.js @@ -2,16 +2,26 @@ /* TODO: ******************************************* ***************************************************** -use cookies to remember settings +selection options for field to stay with current -field: catch mobs in your field and make them into guardian bullets +custom mode grey out mods that are bad, like selection based mods + not important -negative mod effect ideas - -max health - -fire rate - -slow life decay +field graphics too dark at high energy + not important -mod: gain an extra choice of power ups +rewrite pause as a change to the main loop + not important + like testing loop + +game setting for slower computers + fewer blocks + fewer debris + fewer mobs + +mod: guardian + recursive + spawns at start of level mod: if you fire when out of ammo you gain 1 ammo pack at the cost of 10% max health diff --git a/js/level.js b/js/level.js index 7a032d5..cea3deb 100644 --- a/js/level.js +++ b/js/level.js @@ -16,7 +16,7 @@ const level = { // game.difficulty = 6; //for testing to simulate possible mobs spawns // b.giveGuns(0) // mech.setField(2) - b.giveMod(20) + // b.giveMod(20) level.intro(); //starting level // level.testingMap(); @@ -36,6 +36,9 @@ const level = { game.setZoom(); level.addToWorld(); //add bodies to game engine game.draw.setPaths(); + for (let i = 0; i < b.modGuardianCount; i++) { + b.guardian() + } }, isBuildRun: false, difficultyIncrease(num = 1) { diff --git a/js/player.js b/js/player.js index 300e949..2a8aa13 100644 --- a/js/player.js +++ b/js/player.js @@ -296,14 +296,14 @@ const mech = { }, alive: true, death() { - if (b.modIsImmortal) { //if player has the immortality buff, spawn on the same level with randomized stats + if (b.isModImmortal) { //if player has the immortality buff, spawn on the same level with randomized stats spawn.setSpawnList(); //new mob types game.clearNow = true; //triggers a map reset //count mods let totalMods = -2; //lose 2 mods for balance reasons for (let i = 0; i < b.mods.length; i++) { - if (b.mods[i].have) totalMods++ + totalMods += b.mods[i].count } function randomizeMods() { @@ -313,7 +313,7 @@ const mech = { let options = []; for (let i = 0, len = b.mods.length; i < len; i++) { //can't get quantum immortality again - if (b.mods[i].name !== "quantum immortality" && !b.mods[i].have) options.push(i); + if (b.mods[i].name !== "quantum immortality" && b.mods[i].count < b.mods[i].maxCount) options.push(i); } //add a new mod if (options.length > 0) { @@ -666,9 +666,11 @@ const mech = { if (mech.fieldMeter < mech.fieldEnergyMax) { mech.fieldMeter += mech.fieldRegen; ctx.fillStyle = "rgba(0, 0, 0, 0.4)"; - ctx.fillRect(mech.pos.x - mech.radius, mech.pos.y - 50, range, 10); + const xOff = mech.pos.x - mech.radius * mech.fieldEnergyMax + const yOff = mech.pos.y - 50 + ctx.fillRect(xOff, yOff, range * mech.fieldEnergyMax, 10); ctx.fillStyle = "#0cf"; - ctx.fillRect(mech.pos.x - mech.radius, mech.pos.y - 50, range * mech.fieldMeter, 10); + ctx.fillRect(xOff, yOff, range * mech.fieldMeter, 10); } else { mech.fieldMeter = mech.fieldEnergyMax } diff --git a/js/powerups.js b/js/powerups.js index 089fb26..7c7bc24 100644 --- a/js/powerups.js +++ b/js/powerups.js @@ -107,7 +107,7 @@ const powerUps = { choice3 = doNotHave(mech.fieldUpgrades, choice1, choice2) if (choice3 > -1) text += `
  ${mech.fieldUpgrades[choice3].name}
${mech.fieldUpgrades[choice3].description}
` } - if (b.modIsFourOptions) { + if (b.isModFourOptions) { let choice4 = doNotHave(mech.fieldUpgrades, choice1, choice2, choice3) if (choice4 > -1) text += `
  ${mech.fieldUpgrades[choice4].name}
${mech.fieldUpgrades[choice4].description}
` } @@ -129,7 +129,7 @@ const powerUps = { function doNotHave(who, skip1 = -1, skip2 = -1, skip3 = -1) { let options = []; for (let i = 0; i < who.length; i++) { - if (!who[i].have && i !== skip1 && i !== skip2 && i !== skip3) options.push(i); + if (who[i].count < who[i].maxCount && i !== skip1 && i !== skip2 && i !== skip3) options.push(i); } if (options.length > 0) return options[Math.floor(Math.random() * options.length)] } @@ -145,7 +145,7 @@ const powerUps = { choice3 = doNotHave(b.mods, choice1, choice2) if (choice3 > -1) text += `
  ${b.mods[choice3].name}
${b.mods[choice3].description}
` } - if (b.modIsFourOptions) { + if (b.isModFourOptions) { let choice4 = doNotHave(b.mods, choice1, choice2, choice3) if (choice4 > -1) text += `
  ${b.mods[choice4].name}
${b.mods[choice4].description}
` } @@ -182,7 +182,7 @@ const powerUps = { choice3 = doNotHave(b.guns, choice1, choice2) if (choice3 > -1) text += `
  ${b.guns[choice3].name}
${b.guns[choice3].description}
` } - if (b.modIsFourOptions) { + if (b.isModFourOptions) { let choice4 = doNotHave(b.guns, choice1, choice2, choice3) if (choice4 > -1) text += `
  ${b.guns[choice4].name}
${b.guns[choice4].description}
` }