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 += `