diff --git a/js/bullet.js b/js/bullet.js index fe97a53..d940d8e 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -798,7 +798,6 @@ const b = { const SCALE = 1.06 Matter.Body.scale(this, SCALE, SCALE); this.radius *= SCALE; - console.log(this.radius) } else { //shrink const SCALE = 1 - 0.005 / mod.isBulletsLastLonger @@ -1164,28 +1163,20 @@ const b = { isEasyToAim: false, fire() { const me = bullet.length; - const dir = mech.angle + (Math.random() - 0.5) * ((mech.crouch) ? 0.03 : 0.1); - bullet[me] = Bodies.rectangle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 20 * mod.bulletSize, 6 * mod.bulletSize, b.fireAttributes(dir)); - b.fireProps(mech.crouch ? 8 : 4, mech.crouch ? 52 : 38, dir, me); //cd , speed + const dir = mech.angle + (Math.random() - 0.5) * ((mech.crouch) ? 0.01 : 0.1); + bullet[me] = Bodies.rectangle(mech.pos.x + 23 * Math.cos(mech.angle), mech.pos.y + 23 * Math.sin(mech.angle), 20 * mod.bulletSize, 6 * mod.bulletSize, b.fireAttributes(dir)); + b.fireProps(mech.crouch ? 7 : 4, mech.crouch ? 40 : 34, dir, me); //cd , speed bullet[me].endCycle = game.cycle + 70; - bullet[me].dmg = 0.07; - bullet[me].frictionAir = mech.crouch ? 0.007 : 0.01; + bullet[me].dmg = 0.25; + bullet[me].frictionAir = mech.crouch ? 0.001 : 0.003; if (mod.isIceCrystals && mech.energy > 0.01) { - mech.energy -= mech.fieldRegen + 0.007 + mech.energy -= mech.fieldRegen + 0.005 bullet[me].onDmg = function (who) { mobs.statusSlow(who, 30) }; - //ice muzzleFlash - ctx.fillStyle = "rgb(0,100,255)"; - - ctx.beginPath(); - ctx.arc(mech.pos.x + 35 * Math.cos(mech.angle), mech.pos.y + 35 * Math.sin(mech.angle), 15, 0, 2 * Math.PI); - ctx.fill(); - } else { - b.muzzleFlash(15); } bullet[me].do = function () { - this.force.y += this.mass * 0.0005; + this.force.y += this.mass * 0.0003; }; } }, @@ -1425,7 +1416,7 @@ const b = { for (let i = 0; i < q.length; i++) { slowCheck = 0.3; Matter.Body.setPosition(this, Vector.add(this.position, q[i].velocity)) //move with the medium - let dmg = b.dmgScale * 0.43 / Math.sqrt(q[i].mass) * (mod.waveHelix === 1 ? 1 : 0.6) //1 - 0.4 = 0.6 for helix mod 40% damage reduction + let dmg = b.dmgScale * 0.37 / Math.sqrt(q[i].mass) * (mod.waveHelix === 1 ? 1 : 0.6) //1 - 0.4 = 0.6 for helix mod 40% damage reduction q[i].damage(dmg); q[i].foundPlayer(); game.drawList.push({ //add dmg to draw queue @@ -1443,7 +1434,6 @@ const b = { Matter.Body.setVelocity(this, Vector.mult(Vector.normalise(this.velocity), SPEED * slowCheck)); } } - this.cycle++ const wiggle = Vector.mult(transverse, wiggleMag * Math.cos(this.cycle * 0.35) * ((i % 2) ? -1 : 1)) Matter.Body.setPosition(this, Vector.add(this.position, wiggle)) diff --git a/js/level.js b/js/level.js index 8776a70..9f79a41 100644 --- a/js/level.js +++ b/js/level.js @@ -184,7 +184,7 @@ const level = { // spawn.bomberBoss(2900, -500) spawn.launcherBoss(1200, -500) - // spawn.launcher(1600, -400) + spawn.launcher(1600, -400) // spawn.spawner(1600, -500) // spawn.cellBossCulture(1600, -500) // spawn.shooter(1600, -500) diff --git a/js/mob.js b/js/mob.js index f66b6b3..f85b586 100644 --- a/js/mob.js +++ b/js/mob.js @@ -187,7 +187,7 @@ const mobs = { index: i, health: 1, showHealthBar: true, - accelMag: 0.001, + accelMag: 0.001 * game.accelScale, cd: 0, //game cycle when cooldown will be over delay: 60, //static: time between cooldowns fill: color, diff --git a/js/mods.js b/js/mods.js index d8d36d8..c6af864 100644 --- a/js/mods.js +++ b/js/mods.js @@ -44,6 +44,25 @@ const mod = { game.updateModHUD(); } }, + giveBasicMod(index = 'random') { + // if (isNaN(index)) { //find index by name + // let found = false; + // for (let i = 0; i < mod.mods.length; i++) { + // if (index === mod.mods[i].name) { + // index = i; + // found = true; + // break; + // } + // } + // if (!found) return //if name not found don't give any mod + // } + + mod.basicMods[index].effect(); //give specific mod + mod.mods[index].count++ + mod.totalCount++ //used in power up randomization + game.updateModHUD(); + + }, haveGunCheck(name) { for (i = 0, len = b.inventory.length; i < len; i++) { if (b.guns[b.inventory[i]].name === name) return true @@ -90,6 +109,7 @@ const mod = { if (document.getElementById("mod-low-health-damage")) document.getElementById("mod-low-health-damage").innerHTML = ""; }, 10); }, + mods: [{ name: "capacitor", // nameInfo: "", @@ -156,26 +176,6 @@ const mod = { mod.isCrit = false; } }, - { - name: "fluoroantimonic acid", - nameInfo: "", - description: "each bullet does instant acid damage
active when you are above 80% base health", - maxCount: 1, - count: 0, - allowed() { - return mech.health > 0.8 || build.isCustomSelection - }, - requires: "health above 80%", - effect() { - mod.isAcidDmg = true; - mod.onHealthChange(); - }, - remove() { - mod.acidDmg = 0; - mod.isAcidDmg = false; - game.playerDmgColor = "rgba(0,0,0,0.7)" - } - }, { name: "negative feedback", // nameInfo: "", @@ -929,6 +929,27 @@ const mod = { mod.isDamageFromBulletCount = false } }, + { + name: "fluoroantimonic acid", + nameInfo: "", + description: "each bullet does instant acid damage
active when you are above 80% base health", + maxCount: 1, + count: 0, + allowed() { + return (mech.health > 0.8 || build.isCustomSelection) && + (mod.haveGunCheck("mine") || mod.haveGunCheck("minigun") || mod.haveGunCheck("shotgun") || mod.haveGunCheck("super balls") || mod.haveGunCheck("spores") || mod.haveGunCheck("drones") || mod.haveGunCheck("ice IX")) + }, + requires: "health above 80%", + effect() { + mod.isAcidDmg = true; + mod.onHealthChange(); + }, + remove() { + mod.acidDmg = 0; + mod.isAcidDmg = false; + game.playerDmgColor = "rgba(0,0,0,0.7)" + } + }, { name: "depleted uranium rounds", description: `your bullets are +16% larger
increased mass and physical damage`, diff --git a/js/player.js b/js/player.js index 6344fd3..b558784 100644 --- a/js/player.js +++ b/js/player.js @@ -358,15 +358,13 @@ const mech = { alive: false, death() { if (mod.isImmortal) { //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 - powerUps.reroll.rerolls = Math.floor(Math.random() * Math.random() * 12) //count mods let totalMods = 0; for (let i = 0; i < mod.mods.length; i++) { totalMods += mod.mods[i].count } + const totalGuns = b.inventory.length //count guns function randomizeMods() { for (let i = 0; i < totalMods; i++) { @@ -394,18 +392,16 @@ const mech = { } function randomizeField() { - mech.setField(Math.floor(Math.random() * (mech.fieldUpgrades.length))) + mech.setField(Math.ceil(Math.random() * (mech.fieldUpgrades.length - 1))) } function randomizeHealth() { - mech.health = 0.6 + Math.random() + mech.health = 0.7 + Math.random() if (mech.health > 1) mech.health = 1; mech.displayHealth(); } function randomizeGuns() { - // const length = Math.round(b.inventory.length * (1 + 0.4 * (Math.random() - 0.5))) - const length = b.inventory.length //removes guns and ammo b.inventory = []; b.activeGun = null; @@ -415,11 +411,11 @@ const mech = { if (b.guns[i].ammo !== Infinity) b.guns[i].ammo = 0; } //give random guns - for (let i = 0; i < length; i++) b.giveGuns() + for (let i = 0; i < totalGuns; i++) b.giveGuns() //randomize ammo for (let i = 0, len = b.inventory.length; i < len; i++) { if (b.guns[b.inventory[i]].ammo !== Infinity) { - b.guns[b.inventory[i]].ammo = Math.max(0, Math.floor(5 * b.guns[b.inventory[i]].ammo * (Math.random() - 0.1))) + b.guns[b.inventory[i]].ammo = Math.max(0, Math.floor(6 * b.guns[b.inventory[i]].ammo * Math.sqrt(Math.random()))) } } game.makeGunHUD(); //update gun HUD @@ -431,6 +427,9 @@ const mech = { } function randomizeEverything() { + spawn.setSpawnList(); //new mob types + game.clearNow = true; //triggers a map reset + mod.setupAllMods(); //remove all mods for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]); bullet = []; //remove all bullets @@ -442,7 +441,7 @@ const mech = { randomizeEverything() const swapPeriod = 1000 - for (let i = 0, len = 7; i < len; i++) { + for (let i = 0, len = 5; i < len; i++) { setTimeout(function () { randomizeEverything() game.replaceTextLog = true; @@ -460,7 +459,7 @@ const mech = { } game.replaceTextLog = true; game.makeTextLog("your quantum probability has stabilized", 1000); - }, 8 * swapPeriod); + }, 6 * swapPeriod); } else if (mech.alive) { //normal death code here mech.alive = false; @@ -1873,62 +1872,66 @@ const mech = { mech.drawHold(mech.holdingTarget); mech.holding(); mech.throwBlock(); - } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { + } else if (keys[32] || game.mouseDownRight) { mech.grabPowerUp(); mech.lookForPickUp(); - const DRAIN = 0.0003 + 0.00015 * player.speed + ((!mod.renormalization && mech.fireCDcycle > mech.cycle) ? 0.005 : 0.001) - if (mech.energy > DRAIN) { - mech.energy -= DRAIN; - // if (mech.energy < 0.001) { - // mech.fieldCDcycle = mech.cycle + 120; - // mech.energy = 0; - // mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) - // } - this.fieldRange = this.fieldRange * 0.8 + 0.2 * 160 - drawField(this.fieldRange) - - mech.isStealth = true //isStealth disables most uses of foundPlayer() - player.collisionFilter.mask = cat.map + if (mech.fieldCDcycle < mech.cycle) { - let inPlayer = Matter.Query.region(mob, player.bounds) - if (inPlayer.length > 0) { - for (let i = 0; i < inPlayer.length; i++) { - if (inPlayer[i].shield) { - mech.energy -= 0.005; //shields drain player energy - //draw outline of shield - ctx.fillStyle = `rgba(140,217,255,0.5)` - ctx.fill() - } else if (mod.superposition && inPlayer[i].dropPowerUp) { - // inPlayer[i].damage(0.4 * b.dmgScale); //damage mobs inside the player - // mech.energy += 0.005; + const DRAIN = 0.0003 + 0.00015 * player.speed + ((!mod.renormalization && mech.fireCDcycle > mech.cycle) ? 0.005 : 0.001) + if (mech.energy > DRAIN) { + mech.energy -= DRAIN; + // if (mech.energy < 0.001) { + // mech.fieldCDcycle = mech.cycle + 120; + // mech.energy = 0; + // mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) + // } + this.fieldRange = this.fieldRange * 0.8 + 0.2 * 160 + drawField(this.fieldRange) - mobs.statusStun(inPlayer[i], 240) - //draw outline of mob in a few random locations to show blurriness - const vertices = inPlayer[i].vertices; - const off = 30 - for (let k = 0; k < 3; k++) { - const xOff = off * (Math.random() - 0.5) - const yOff = off * (Math.random() - 0.5) - ctx.beginPath(); - ctx.moveTo(xOff + vertices[0].x, yOff + vertices[0].y); - for (let j = 1, len = vertices.length; j < len; ++j) { - ctx.lineTo(xOff + vertices[j].x, yOff + vertices[j].y); - } - ctx.lineTo(xOff + vertices[0].x, yOff + vertices[0].y); - ctx.fillStyle = "rgba(0,0,0,0.1)" + mech.isStealth = true //isStealth disables most uses of foundPlayer() + player.collisionFilter.mask = cat.map + + + let inPlayer = Matter.Query.region(mob, player.bounds) + if (inPlayer.length > 0) { + for (let i = 0; i < inPlayer.length; i++) { + if (inPlayer[i].shield) { + mech.energy -= 0.005; //shields drain player energy + //draw outline of shield + ctx.fillStyle = `rgba(140,217,255,0.5)` ctx.fill() + } else if (mod.superposition && inPlayer[i].dropPowerUp) { + // inPlayer[i].damage(0.4 * b.dmgScale); //damage mobs inside the player + // mech.energy += 0.005; + + mobs.statusStun(inPlayer[i], 240) + //draw outline of mob in a few random locations to show blurriness + const vertices = inPlayer[i].vertices; + const off = 30 + for (let k = 0; k < 3; k++) { + const xOff = off * (Math.random() - 0.5) + const yOff = off * (Math.random() - 0.5) + ctx.beginPath(); + ctx.moveTo(xOff + vertices[0].x, yOff + vertices[0].y); + for (let j = 1, len = vertices.length; j < len; ++j) { + ctx.lineTo(xOff + vertices[j].x, yOff + vertices[j].y); + } + ctx.lineTo(xOff + vertices[0].x, yOff + vertices[0].y); + ctx.fillStyle = "rgba(0,0,0,0.1)" + ctx.fill() + } + break; } - break; } } + } else { + mech.fieldCDcycle = mech.cycle + 120; + mech.energy = 0; + mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) + drawField(this.fieldRange) } - } else { - mech.fieldCDcycle = mech.cycle + 120; - mech.energy = 0; - mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) - drawField(this.fieldRange) } } else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released mech.pickUp(); @@ -1983,128 +1986,134 @@ const mech = { mech.fieldRadius = 0; mech.drop(); mech.hold = function () { - if ((keys[32] || game.mouseDownRight && mech.fieldCDcycle < mech.cycle)) { - const scale = 25 - const bounds = { - min: { - x: mech.fieldPosition.x - scale, - y: mech.fieldPosition.y - scale - }, - max: { - x: mech.fieldPosition.x + scale, - y: mech.fieldPosition.y + scale - } - } - const isInMap = Matter.Query.region(map, bounds).length - // const isInMap = Matter.Query.point(map, mech.fieldPosition).length - - if (!mech.fieldOn) { // if field was off, and it starting up, teleport to new mouse location - mech.fieldOn = true; - mech.fieldPosition = { //smooth the mouse position - x: game.mouseInGame.x, - y: game.mouseInGame.y - } - mech.lastFieldPosition = { //used to find velocity of field changes - x: mech.fieldPosition.x, - y: mech.fieldPosition.y - } - } else { //when field is on it smoothly moves towards the mouse - mech.lastFieldPosition = { //used to find velocity of field changes - x: mech.fieldPosition.x, - y: mech.fieldPosition.y - } - const smooth = isInMap ? 0.985 : 0.96; - mech.fieldPosition = { //smooth the mouse position - x: mech.fieldPosition.x * smooth + game.mouseInGame.x * (1 - smooth), - y: mech.fieldPosition.y * smooth + game.mouseInGame.y * (1 - smooth), - } - } - - //grab power ups into the field - for (let i = 0, len = powerUp.length; i < len; ++i) { - const dxP = mech.fieldPosition.x - powerUp[i].position.x; - const dyP = mech.fieldPosition.y - powerUp[i].position.y; - const dist2 = dxP * dxP + dyP * dyP; - // float towards field if looking at and in range or if very close to player - if (dist2 < mech.fieldRadius * mech.fieldRadius && (mech.lookingAt(powerUp[i]) || dist2 < 16000) && !(mech.health === mech.maxHealth && powerUp[i].name === "heal")) { - powerUp[i].force.x += 7 * (dxP / dist2) * powerUp[i].mass; - powerUp[i].force.y += 7 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * game.g; //negate gravity - //extra friction - Matter.Body.setVelocity(powerUp[i], { - x: powerUp[i].velocity.x * 0.11, - y: powerUp[i].velocity.y * 0.11 - }); - if (dist2 < 5000 && !game.isChoosing) { //use power up if it is close enough - if (mod.isMassEnergy) mech.energy = mech.maxEnergy * 2; - powerUp[i].effect(); - Matter.World.remove(engine.world, powerUp[i]); - powerUp.splice(i, 1); - // mech.fieldRadius += 50 - break; //because the array order is messed up after splice + if (keys[32] || game.mouseDownRight) { + if (mech.fieldCDcycle < mech.cycle) { + const scale = 25 + const bounds = { + min: { + x: mech.fieldPosition.x - scale, + y: mech.fieldPosition.y - scale + }, + max: { + x: mech.fieldPosition.x + scale, + y: mech.fieldPosition.y + scale } } - } + const isInMap = Matter.Query.region(map, bounds).length + // const isInMap = Matter.Query.point(map, mech.fieldPosition).length - if (mech.energy > 0.01) { - //find mouse velocity - const diff = Vector.sub(mech.fieldPosition, mech.lastFieldPosition) - const speed = Vector.magnitude(diff) - const velocity = Vector.mult(Vector.normalise(diff), Math.min(speed, 45)) //limit velocity - let radius, radiusSmooth - if (Matter.Query.ray(map, mech.fieldPosition, player.position).length) { //is there something block the player's view of the field - radius = 0 - radiusSmooth = Math.max(0, isInMap ? 0.96 - 0.02 * speed : 0.995); //0.99 + if (!mech.fieldOn) { // if field was off, and it starting up, teleport to new mouse location + mech.fieldOn = true; + mech.fieldPosition = { //smooth the mouse position + x: game.mouseInGame.x, + y: game.mouseInGame.y + } + mech.lastFieldPosition = { //used to find velocity of field changes + x: mech.fieldPosition.x, + y: mech.fieldPosition.y + } + } else { //when field is on it smoothly moves towards the mouse + mech.lastFieldPosition = { //used to find velocity of field changes + x: mech.fieldPosition.x, + y: mech.fieldPosition.y + } + const smooth = isInMap ? 0.985 : 0.96; + mech.fieldPosition = { //smooth the mouse position + x: mech.fieldPosition.x * smooth + game.mouseInGame.x * (1 - smooth), + y: mech.fieldPosition.y * smooth + game.mouseInGame.y * (1 - smooth), + } + } + + //grab power ups into the field + for (let i = 0, len = powerUp.length; i < len; ++i) { + const dxP = mech.fieldPosition.x - powerUp[i].position.x; + const dyP = mech.fieldPosition.y - powerUp[i].position.y; + const dist2 = dxP * dxP + dyP * dyP; + // float towards field if looking at and in range or if very close to player + if (dist2 < mech.fieldRadius * mech.fieldRadius && (mech.lookingAt(powerUp[i]) || dist2 < 16000) && !(mech.health === mech.maxHealth && powerUp[i].name === "heal")) { + powerUp[i].force.x += 7 * (dxP / dist2) * powerUp[i].mass; + powerUp[i].force.y += 7 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * game.g; //negate gravity + //extra friction + Matter.Body.setVelocity(powerUp[i], { + x: powerUp[i].velocity.x * 0.11, + y: powerUp[i].velocity.y * 0.11 + }); + if (dist2 < 5000 && !game.isChoosing) { //use power up if it is close enough + if (mod.isMassEnergy) mech.energy = mech.maxEnergy * 2; + powerUp[i].effect(); + Matter.World.remove(engine.world, powerUp[i]); + powerUp.splice(i, 1); + // mech.fieldRadius += 50 + break; //because the array order is messed up after splice + } + } + } + //grab power ups normally too + mech.grabPowerUp(); + + if (mech.energy > 0.01) { + //find mouse velocity + const diff = Vector.sub(mech.fieldPosition, mech.lastFieldPosition) + const speed = Vector.magnitude(diff) + const velocity = Vector.mult(Vector.normalise(diff), Math.min(speed, 45)) //limit velocity + let radius, radiusSmooth + if (Matter.Query.ray(map, mech.fieldPosition, player.position).length) { //is there something block the player's view of the field + radius = 0 + radiusSmooth = Math.max(0, isInMap ? 0.96 - 0.02 * speed : 0.995); //0.99 + } else { + radius = Math.max(50, 250 - 2 * speed) + radiusSmooth = 0.97 + } + mech.fieldRadius = mech.fieldRadius * radiusSmooth + radius * (1 - radiusSmooth) + + for (let i = 0, len = body.length; i < len; ++i) { + if (Vector.magnitude(Vector.sub(body[i].position, mech.fieldPosition)) < mech.fieldRadius) { + const DRAIN = speed * body[i].mass * 0.000022 + if (mech.energy > DRAIN) { + mech.energy -= DRAIN; + Matter.Body.setVelocity(body[i], velocity); //give block mouse velocity + Matter.Body.setAngularVelocity(body[i], body[i].angularVelocity * 0.8) + body[i].force.y -= body[i].mass * game.g; //remove gravity effects + } else { + mech.fieldCDcycle = mech.cycle + 120; + mech.fieldOn = false + mech.fieldRadius = 0 + break + } + } + } + + if (mod.isPilotFreeze) { + for (let i = 0, len = mob.length; i < len; ++i) { + if (Vector.magnitude(Vector.sub(mob[i].position, mech.fieldPosition)) < mech.fieldRadius) { + mobs.statusSlow(mob[i], 120) + } + } + } + + ctx.beginPath(); + const rotate = mech.cycle * 0.008; + mech.fieldPhase += 0.2 // - 0.5 * Math.sqrt(Math.min(mech.energy, 1)); + const off1 = 1 + 0.06 * Math.sin(mech.fieldPhase); + const off2 = 1 - 0.06 * Math.sin(mech.fieldPhase); + ctx.beginPath(); + ctx.ellipse(mech.fieldPosition.x, mech.fieldPosition.y, 1.2 * mech.fieldRadius * off1, 1.2 * mech.fieldRadius * off2, rotate, 0, 2 * Math.PI); + ctx.globalCompositeOperation = "exclusion"; //"exclusion" "difference"; + ctx.fillStyle = "#fff"; //"#eef"; + ctx.fill(); + ctx.globalCompositeOperation = "source-over"; + ctx.beginPath(); + ctx.ellipse(mech.fieldPosition.x, mech.fieldPosition.y, 1.2 * mech.fieldRadius * off1, 1.2 * mech.fieldRadius * off2, rotate, 0, mech.energy * 2 * Math.PI); + ctx.strokeStyle = "#000"; + ctx.lineWidth = 4; + ctx.stroke(); } else { - radius = Math.max(50, 250 - 2 * speed) - radiusSmooth = 0.97 + mech.fieldCDcycle = mech.cycle + 120; + mech.fieldOn = false + mech.fieldRadius = 0 } - mech.fieldRadius = mech.fieldRadius * radiusSmooth + radius * (1 - radiusSmooth) - - for (let i = 0, len = body.length; i < len; ++i) { - if (Vector.magnitude(Vector.sub(body[i].position, mech.fieldPosition)) < mech.fieldRadius) { - const DRAIN = speed * body[i].mass * 0.000022 - if (mech.energy > DRAIN) { - mech.energy -= DRAIN; - Matter.Body.setVelocity(body[i], velocity); //give block mouse velocity - Matter.Body.setAngularVelocity(body[i], body[i].angularVelocity * 0.8) - body[i].force.y -= body[i].mass * game.g; //remove gravity effects - } else { - mech.fieldCDcycle = mech.cycle + 120; - mech.fieldOn = false - mech.fieldRadius = 0 - break - } - } - } - - if (mod.isPilotFreeze) { - for (let i = 0, len = mob.length; i < len; ++i) { - if (Vector.magnitude(Vector.sub(mob[i].position, mech.fieldPosition)) < mech.fieldRadius) { - mobs.statusSlow(mob[i], 120) - } - } - } - - ctx.beginPath(); - const rotate = mech.cycle * 0.008; - mech.fieldPhase += 0.2 // - 0.5 * Math.sqrt(Math.min(mech.energy, 1)); - const off1 = 1 + 0.06 * Math.sin(mech.fieldPhase); - const off2 = 1 - 0.06 * Math.sin(mech.fieldPhase); - ctx.beginPath(); - ctx.ellipse(mech.fieldPosition.x, mech.fieldPosition.y, 1.2 * mech.fieldRadius * off1, 1.2 * mech.fieldRadius * off2, rotate, 0, 2 * Math.PI); - ctx.globalCompositeOperation = "exclusion"; //"exclusion" "difference"; - ctx.fillStyle = "#fff"; //"#eef"; - ctx.fill(); - ctx.globalCompositeOperation = "source-over"; - ctx.beginPath(); - ctx.ellipse(mech.fieldPosition.x, mech.fieldPosition.y, 1.2 * mech.fieldRadius * off1, 1.2 * mech.fieldRadius * off2, rotate, 0, mech.energy * 2 * Math.PI); - ctx.strokeStyle = "#000"; - ctx.lineWidth = 4; - ctx.stroke(); } else { - mech.fieldCDcycle = mech.cycle + 120; - mech.fieldOn = false - mech.fieldRadius = 0 + mech.grabPowerUp(); } } else { mech.fieldOn = false diff --git a/js/powerup.js b/js/powerup.js index a91851c..0ba6da9 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -211,6 +211,8 @@ const powerUps = { }, choiceLog: [], //records all previous choice options effect() { + + function pick(skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { let options = []; for (let i = 0; i < mod.mods.length; i++) { @@ -232,28 +234,30 @@ const powerUps = { } } } - if (options.length > 0) { - return options[Math.floor(Math.random() * options.length)] - } - } + if (options.length > 0) { + const choose = options[Math.floor(Math.random() * options.length)] + text += `
  ${mod.mods[choose].name}
${mod.mods[choose].description}
` + return choose + } + + } + let text = `

choose a mod

` let choice1 = pick() let choice2 = -1 let choice3 = -1 if (choice1 > -1) { - let text = `

choose a mod

` - text += `
  ${mod.mods[choice1].name}
${mod.mods[choice1].description}
` if (!mod.isDeterminism) { choice2 = pick(choice1) - if (choice2 > -1) text += `
  ${mod.mods[choice2].name}
${mod.mods[choice2].description}
` + // if (choice2 > -1) text += `
  ${mod.mods[choice2].name}
${mod.mods[choice2].description}
` choice3 = pick(choice1, choice2) - if (choice3 > -1) text += `
  ${mod.mods[choice3].name}
${mod.mods[choice3].description}
` + // if (choice3 > -1) text += `
  ${mod.mods[choice3].name}
${mod.mods[choice3].description}
` } if (mod.isExtraChoice) { let choice4 = pick(choice1, choice2, choice3) - if (choice4 > -1) text += `
  ${mod.mods[choice4].name}
${mod.mods[choice4].description}
` + // if (choice4 > -1) text += `
  ${mod.mods[choice4].name}
${mod.mods[choice4].description}
` let choice5 = pick(choice1, choice2, choice3, choice4) - if (choice5 > -1) text += `
  ${mod.mods[choice5].name}
${mod.mods[choice5].description}
` + // if (choice5 > -1) text += `
  ${mod.mods[choice5].name}
${mod.mods[choice5].description}
` powerUps.mod.choiceLog.push(choice4) powerUps.mod.choiceLog.push(choice5) } diff --git a/js/spawn.js b/js/spawn.js index f709ab9..8b8bfc4 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -1440,38 +1440,22 @@ const spawn = { launcher(x, y, radius = 30 + Math.ceil(Math.random() * 40)) { mobs.spawn(x, y, 3, radius, "rgb(150,150,255)"); let me = mob[mob.length - 1]; - me.accelMag = 0.00002 * game.accelScale; + me.accelMag = 0.00004 * game.accelScale; + me.fireFreq = Math.floor(420 + 90 * Math.random() * game.CDScale) me.frictionStatic = 0; me.friction = 0; - // me.memory = 200; - me.delay = 770 * game.CDScale; - me.cd = Infinity; + me.frictionAir = 0.02; spawn.shield(me, x, y); me.onDamage = function () {}; me.do = function () { - if (!(game.cycle % this.seePlayerFreq)) { // this.seePlayerCheck(); from mobs - if ( - this.distanceToPlayer2() < this.seeAtDistance2 && - Matter.Query.ray(map, this.position, this.mechPosRange()).length === 0 && - Matter.Query.ray(body, this.position, this.mechPosRange()).length === 0 && - !mech.isStealth - ) { - this.foundPlayer(); - if (this.cd === Infinity) this.cd = game.cycle + this.delay * 0.3; - } else if (this.seePlayer.recall) { - this.lostPlayer(); - this.cd = Infinity - } - } + this.seePlayerCheck(); this.checkStatus(); this.attraction(); - if (this.seePlayer.recall && this.cd < game.cycle) { - this.cd = game.cycle + this.delay; - // this.torque += 0.0002 * this.inertia; + if (this.seePlayer.recall && !(game.cycle % this.fireFreq)) { Matter.Body.setAngularVelocity(this, 0.14) //fire a bullet from each vertex for (let i = 0, len = this.vertices.length; i < len; i++) { - spawn.seeker(this.vertices[i].x, this.vertices[i].y, 5) + spawn.seeker(this.vertices[i].x, this.vertices[i].y, 6) //give the bullet a rotational velocity as if they were attached to a vertex const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[i]))), -8) Matter.Body.setVelocity(mob[mob.length - 1], { @@ -1482,40 +1466,29 @@ const spawn = { } }; }, - launcherBoss(x, y, radius = 75 + Math.ceil(Math.random() * 20)) { - mobs.spawn(x, y, 7, radius, "rgb(150,150,255)"); + launcherBoss(x, y, radius = 90) { + mobs.spawn(x, y, 6, radius, "rgb(150,150,255)"); let me = mob[mob.length - 1]; - me.accelMag = 0.000065 * game.accelScale; - me.memory = 720; - me.delay = 420 * game.CDScale; - me.cd = Infinity; + me.accelMag = 0.00008 * game.accelScale; + me.fireFreq = Math.floor(330 * game.CDScale) + me.frictionStatic = 0; + me.friction = 0; + me.frictionAir = 0.02; + me.memory = 420 * game.CDScale; + me.repulsionRange = 1200000; //squared spawn.shield(me, x, y, 1); - me.onDamage = function () {}; - Matter.Body.setDensity(me, 0.002 + 0.0002 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger + Matter.Body.setDensity(me, 0.004 + 0.0005 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger me.onDeath = function () { powerUps.spawnBossPowerUp(this.position.x, this.position.y) // this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //helps collisions functions work better after vertex have been changed }; + me.onDamage = function () {}; me.do = function () { - if (!(game.cycle % this.seePlayerFreq)) { // this.seePlayerCheck(); from mobs - if ( - this.distanceToPlayer2() < this.seeAtDistance2 && - Matter.Query.ray(map, this.position, this.mechPosRange()).length === 0 && - Matter.Query.ray(body, this.position, this.mechPosRange()).length === 0 && - !mech.isStealth - ) { - this.foundPlayer(); - if (this.cd === Infinity) this.cd = game.cycle + this.delay * 0.2; - } else if (this.seePlayer.recall) { - this.lostPlayer(); - this.cd = Infinity - } - } + this.seePlayerCheck(); this.checkStatus(); this.attraction(); - if (this.seePlayer.recall && this.cd < game.cycle) { - this.cd = game.cycle + this.delay; - // this.torque += 0.0002 * this.inertia; + this.repulsion(); + if (this.seePlayer.recall && !(game.cycle % this.fireFreq)) { Matter.Body.setAngularVelocity(this, 0.11) //fire a bullet from each vertex for (let i = 0, len = this.vertices.length; i < len; i++) { @@ -1530,17 +1503,17 @@ const spawn = { } }; }, - seeker(x, y, radius = 6, sides = 0) { + seeker(x, y, radius = 5, sides = 0) { //bullets - mobs.spawn(x, y, sides, radius, "rgb(0,0,255)"); + mobs.spawn(x, y, sides, radius, "rgb(100,100,255)"); let me = mob[mob.length - 1]; me.stroke = "transparent"; me.onHit = function () { this.explode(this.mass * 10); }; Matter.Body.setDensity(me, 0.00005); //normal is 0.001 - me.timeLeft = 380 * (0.8 + 0.4 * Math.random()); - me.accelMag = 0.00012 * (0.8 + 0.4 * Math.random()) * game.accelScale; + me.timeLeft = 420 * (0.8 + 0.4 * Math.random()); + me.accelMag = 0.00015 * (0.8 + 0.4 * Math.random()) * game.accelScale; me.frictionAir = 0.01 * (0.8 + 0.4 * Math.random()); me.restitution = 0.5; me.leaveBody = false; diff --git a/todo.txt b/todo.txt index ea34efc..69455a1 100644 --- a/todo.txt +++ b/todo.txt @@ -1,34 +1,6 @@ -mob: launchers now have a new fire mechanic -mob: launcher boss -huge rework of code organization, this might produce some new bugs around mods - ************** TODO - n-gon ************** -launchers shouldn't have to face the player - fire after a spin - give bullets velocity from spin -mob boss - launcher - -lower tier of basic mods - 33% chance for basic mod on each selection - make an odds variable that starts at 0% and gains 33% for each normal mod, resets to 0% after get a basic mod - don't track these mods for avoiding no repeats - make ball different color to indicate quality - basic: grey? smaller size? - also make gun/field specific mods have a different icon for top tier - don't include basic mods in custom mod? - basic mods can show on guns or fields? - ideas - +5% damage - +8% haste - +5% damage reduction - +25% max health - +25% max energy - spawn 2 ammo //or 3? - spawn 2 heal - spawn 2 reroll //or 1? - movement fluidity let legs jump on mobs, but player will still take damage like: ori and the blind forest, celeste @@ -41,7 +13,6 @@ movement fluidity wall grab? maybe remove falling damage and block damage? - rays can have width, how to use this? Matter.Query.ray(bodies, startPoint, endPoint, [rayWidth]) wide lasers?