diff --git a/js/bullets.js b/js/bullets.js index a44e720..5af08a4 100644 --- a/js/bullets.js +++ b/js/bullets.js @@ -1056,6 +1056,22 @@ const b = { } } }, + { + name: "fragmentation grenade", + description: "grenades are loaded with +5 nails
on detonation nails are ejected towards mobs", + maxCount: 9, + count: 0, + allowed() { + return b.haveGunCheck("grenades") + }, + requires: "grenades", + effect() { + b.modGrenadeFragments += 5 + }, + remove() { + b.modGrenadeFragments = 0 + } + }, { name: "electromagnetic pulse", description: "vacuum bomb's explosion destroys shields
and does 20% more damage", @@ -1154,7 +1170,7 @@ const b = { }, { name: "fragmenting projectiles", - description: "rail gun fragments into nails after hitting mobs at high speeds", + description: "rail gun fragments into nails
after hitting mobs at high speeds", maxCount: 1, count: 0, allowed() { @@ -1170,7 +1186,7 @@ const b = { }, { name: "specular reflection", - description: "the laser gains +1 reflection
+50% laser damage and energy drain", + description: "laser beams gain +1 reflection
+50% laser damage and energy drain", maxCount: 9, count: 0, allowed() { @@ -1889,7 +1905,7 @@ const b = { friction: 0, frictionAir: 0.025, thrust: b.isModFastSpores ? 0.0008 : 0.0004, - dmg: 2.2, //damage done in addition to the damage from momentum + dmg: 2.4, //damage done in addition to the damage from momentum classType: "bullet", collisionFilter: { category: cat.bullet, @@ -1952,7 +1968,7 @@ const b = { friction: 0, frictionAir: 0.10, restitution: 0.3, - dmg: 0.3, //damage done in addition to the damage from momentum + dmg: 0.2, //damage done in addition to the damage from momentum lookFrequency: 10 + Math.floor(7 * Math.random()), endCycle: game.cycle + 120 * b.isModBulletsLastLonger, //Math.floor((1200 + 420 * Math.random()) * b.isModBulletsLastLonger), classType: "bullet", @@ -2022,7 +2038,7 @@ const b = { friction: 0.05, frictionAir: 0.0005, restitution: 1, - dmg: 0.15, //damage done in addition to the damage from momentum + dmg: 0.17, //damage done in addition to the damage from momentum lookFrequency: 83 + Math.floor(41 * Math.random()), endCycle: game.cycle + Math.floor((1200 + 420 * Math.random()) * b.isModBulletsLastLonger), classType: "bullet", @@ -2418,7 +2434,7 @@ const b = { name: "super balls", //2 description: "fire four balls in a wide arc
balls bounce with no momentum loss", ammo: 0, - ammoPack: 13, + ammoPack: 14, have: false, num: 5, isStarterGun: true, @@ -2724,6 +2740,37 @@ const b = { bullet[me].explodeRad = 275; bullet[me].onEnd = function () { b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end + if (b.modGrenadeFragments) { + const targets = [] //target nearby mobs + for (let i = 0, len = mob.length; i < len; i++) { + if (mob[i].dropPowerUp) { + const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)); + if (dist < 1440000 && //1200*1200 + Matter.Query.ray(map, this.position, mob[i].position).length === 0 && + Matter.Query.ray(body, this.position, mob[i].position).length === 0) { + targets.push(Vector.add(mob[i].position, Vector.mult(mob[i].velocity, Math.sqrt(dist) / 60))) //predict where the mob will be in a few cycles + } + } + } + for (let i = 0; i < b.modGrenadeFragments; i++) { + const speed = 53 + 10 * Math.random() + if (targets.length > 0) { // aim near a random target in array + const index = Math.floor(Math.random() * targets.length) + const SPREAD = 150 / targets.length + const WHERE = { + x: targets[index].x + SPREAD * (Math.random() - 0.5), + y: targets[index].y + SPREAD * (Math.random() - 0.5) + } + b.nail(this.position, Vector.mult(Vector.normalise(Vector.sub(WHERE, this.position)), speed), 1.1) + } else { // aim in random direction + const ANGLE = 2 * Math.PI * Math.random() + b.nail(this.position, { + x: speed * Math.cos(ANGLE), + y: speed * Math.sin(ANGLE) + }) + } + } + } } bullet[me].minDmgSpeed = 1; bullet[me].onDmg = function () { diff --git a/js/index.js b/js/index.js index b3cce54..d2b694e 100644 --- a/js/index.js +++ b/js/index.js @@ -126,6 +126,7 @@ const build = { document.body.style.overflow = "hidden" document.getElementById("pause-grid-left").style.display = "none" document.getElementById("pause-grid-right").style.display = "none" + window.scrollTo(0, 0); }, isCustomSelection: true, choosePowerUp(who, index, type) { @@ -337,10 +338,10 @@ const build = { game.makeGunHUD(); } - //remove any bullets that might have spawned from mods for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]); - bullet = []; - const levelsCleared = Number(document.getElementById("starting-level").value) - 1 + bullet = []; //remove any bullets that might have spawned from mods + + const levelsCleared = Number(document.getElementById("starting-level").value) level.difficultyIncrease(Math.min(99, levelsCleared * game.difficultyMode)) //increase difficulty based on modes level.levelsCleared += levelsCleared; diff --git a/js/player.js b/js/player.js index 730bf9f..1312b90 100644 --- a/js/player.js +++ b/js/player.js @@ -723,8 +723,8 @@ const mech = { fieldEnergyMax: 1, //can be increased by a mod holdingTarget: null, fieldShieldingScale: 1, - fieldRange: 155, // these values are set on reset by setHoldDefaults() + fieldRange: 155, energy: 0, fieldRegen: 0, fieldMode: 0, @@ -742,6 +742,7 @@ const mech = { mech.fieldMeterColor = "#0cf" mech.fieldShieldingScale = 1; mech.fieldDamageResistance = 1; + mech.fieldRange = 155; mech.fieldFire = false; mech.fieldCDcycle = 0; mech.isStealth = false; @@ -1519,7 +1520,7 @@ const mech = { }, { name: "negative mass field", - description: "use energy to nullify   gravity
reduce harm by 66% while field is active", //
launch larger blocks at much higher speeds + description: "use energy to nullify   gravity
reduce harm by 75% while field is active", //
launch larger blocks at much higher speeds fieldDrawRadius: 0, isEasyToAim: true, effect: () => { @@ -1538,7 +1539,7 @@ const mech = { mech.lookForPickUp(); const DRAIN = 0.00035 if (mech.energy > DRAIN) { - mech.fieldDamageResistance = 0.33; // 1 - 0.66 + mech.fieldDamageResistance = 0.25; // 1 - 0.75 // mech.pushMobs360(); //repulse mobs @@ -1746,14 +1747,40 @@ const mech = { }, { name: "phase decoherence field", - description: "use energy to become intangible
moving and touching shields amplifies cost", + description: "use energy to become intangible
firing and touching shields increases drain", isEasyToAim: true, effect: () => { + mech.fieldFire = true; mech.fieldMeterColor = "#fff" + mech.fieldPhase = 0 + mech.hold = function () { + function drawField(radius) { + radius *= 0.7 + 0.7 * mech.energy + const rotate = mech.cycle * 0.005 + const amplitude = 0.06 + mech.fieldPhase += 0.5 - 0.5 * Math.sqrt(Math.min(mech.energy, 1)) + const off1 = 1 + amplitude * Math.sin(mech.fieldPhase) //+ 0.07 * Math.sin(mech.cycle * 0.05) + const off2 = 1 - amplitude * Math.sin(mech.fieldPhase) //+ 0.07 * Math.sin(mech.cycle * 0.05) + ctx.beginPath(); + ctx.ellipse(mech.pos.x, mech.pos.y, radius * off1, radius * off2, rotate, 0, 2 * Math.PI); + ctx.fillStyle = "#fff" //`rgba(0,0,0,${0.5+0.5*mech.energy})`; + ctx.globalCompositeOperation = "destination-in"; //in or atop + ctx.fill(); + ctx.globalCompositeOperation = "source-over"; + ctx.clip(); + + if (mech.fireCDcycle > mech.cycle) { + ctx.lineWidth = 5; + ctx.strokeStyle = `rgba(0, 204, 255,1)` + ctx.stroke() + } + } + mech.isStealth = false //isStealth disables most uses of foundPlayer() player.collisionFilter.mask = cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield //normal collisions if (mech.isHolding) { + this.fieldRange = 2000; mech.drawHold(mech.holdingTarget); mech.holding(); mech.throwBlock(); @@ -1761,66 +1788,51 @@ const mech = { mech.grabPowerUp(); mech.lookForPickUp(); - const DRAIN = 0.00004 + 0.00009 * player.speed + const DRAIN = (0.0005 + 0.0001 * player.speed) * (mech.fireCDcycle > mech.cycle ? 4 : 1) //game.mouseDown if (mech.energy > DRAIN) { mech.energy -= DRAIN; if (mech.energy < 0.001) { mech.fieldCDcycle = mech.cycle + 120; mech.energy = 0; } - + this.fieldRange = this.fieldRange * 0.9 + 0.1 * 160 + drawField(this.fieldRange) mech.isStealth = true //isStealth disables most uses of foundPlayer() player.collisionFilter.mask = cat.map - if (!game.isTimeSkipping) { - // game.timeSkip(1) - const drawRadius = 125 - ctx.beginPath(); - ctx.arc(mech.pos.x, mech.pos.y, drawRadius, 0, 2 * Math.PI); - ctx.fillStyle = `rgba(255,255,255,${mech.energy*0.5})`; - ctx.globalCompositeOperation = "destination-in"; //in or atop - ctx.fill(); - ctx.globalCompositeOperation = "source-over"; - ctx.strokeStyle = "#000" - ctx.lineWidth = 2; - ctx.stroke(); - ctx.beginPath(); - ctx.arc(mech.pos.x, mech.pos.y, drawRadius, 0, 2 * Math.PI); - ctx.clip(); - 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(0, 204, 255,0.6)` - ctx.fill() - } else if (b.isModPhaseFieldDamage && mech.energy > 0.006 && inPlayer[i].dropPowerUp && !inPlayer[i].isShielded) { - inPlayer[i].damage(0.4 * b.dmgScale); //damage mobs inside the player - mech.energy -= 0.002; + 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(0, 204, 255,0.6)` + ctx.fill() + } else if (b.isModPhaseFieldDamage && mech.energy > 0.006 && inPlayer[i].dropPowerUp && !inPlayer[i].isShielded) { + inPlayer[i].damage(0.4 * b.dmgScale); //damage mobs inside the player + mech.energy -= 0.002; - //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.strokeStyle = "#000" - // ctx.lineWidth = 1 - // ctx.stroke() - ctx.fillStyle = "rgba(0,0,0,0.3)" - ctx.fill() + //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); } - break; + ctx.lineTo(xOff + vertices[0].x, yOff + vertices[0].y); + ctx.fillStyle = "rgba(0,0,0,0.3)" + ctx.fill() + // ctx.strokeStyle = "#000" + // ctx.lineWidth = 1 + // ctx.stroke() } + break; } } } @@ -1828,6 +1840,11 @@ const mech = { } else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released mech.pickUp(); } else { + // this.fieldRange = 3000 + if (this.fieldRange < 2000 && mech.holdingTarget === null) { + this.fieldRange += 200 + drawField(this.fieldRange) + } 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) } // mech.drawFieldMeter() diff --git a/todo.txt b/todo.txt index cc89132..8a8333c 100644 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,13 @@ +phase decoherence field - updated graphics, can fire gun while active +mod - fragmentation grenade fires nails + ************** TODO - n-gon ************** +pulse and time dilation only ones left with no dedicated mod + +mod - renormalization: you can shoot bullets while in phase field + lore - a robot (the player) gains self awareness each mod/gun/field is a new tech all the technology leads to the singularity @@ -13,8 +20,6 @@ lore - a robot (the player) gains self awareness make a global variable that goes up by one every time you play show text at start, loading simulation #... -mod - spores with no target hang out about player - mod - status effects last 1 second longer cryonics : a mod that increases the freezing time of mobs. wait until you have more status effects written @@ -26,10 +31,6 @@ add a way to run player submitted maps. MOB stabber - extends one vector like the shooter, but quickly in order to stab -mod - frag grenades fire nails on explosion - -mod - drop a mine after taking damage - work on burn status effect graphics don't look right how is it different from the chemical dot