recursive mods, gaurdian mod

This commit is contained in:
landgreen
2020-01-01 18:09:03 -08:00
parent cbdd7f006f
commit 47eeafab08
7 changed files with 375 additions and 207 deletions

View File

@@ -12,7 +12,7 @@ const b = {
modHealthDrain: null, modHealthDrain: null,
modNoAmmo: null, modNoAmmo: null,
isModBulletsLastLonger: null, isModBulletsLastLonger: null,
modIsImmortal: null, isModImmortal: null,
modSpores: null, modSpores: null,
isModImmuneExplosion: null, isModImmuneExplosion: null,
isModDroneOnDamage: null, isModDroneOnDamage: null,
@@ -20,13 +20,14 @@ const b = {
annihilation: null, annihilation: null,
isModRecursiveHealing: null, isModRecursiveHealing: null,
modSquirrelFx: null, modSquirrelFx: null,
modIsCrit: null, isModCrit: null,
isModBayesian: null, isModBayesian: null,
isModLowHealthDmg: null, isModLowHealthDmg: null,
isModFarAwayDmg: null, isModFarAwayDmg: null,
isModEntanglement: null, isModEntanglement: null,
isModMassEnergy: null, isModMassEnergy: null,
modIsFourOptions: null, isModFourOptions: null,
modGuardianCount: null,
setModDefaults() { setModDefaults() {
b.modCount = 0; b.modCount = 0;
b.modFireRate = 1; b.modFireRate = 1;
@@ -38,180 +39,220 @@ const b = {
b.modHealthDrain = 0; b.modHealthDrain = 0;
b.modNoAmmo = 0; b.modNoAmmo = 0;
b.isModBulletsLastLonger = 1; b.isModBulletsLastLonger = 1;
b.modIsImmortal = false; b.isModImmortal = false;
b.modSpores = 0; b.modSpores = 0;
b.modExtraDmg = 0; b.modExtraDmg = 0;
b.modAnnihilation = false; b.isModAnnihilation = false;
b.isModRecursiveHealing = false; b.isModRecursiveHealing = false;
b.modSquirrelFx = 1; b.modSquirrelFx = 1;
b.modIsCrit = false; b.isModCrit = false;
b.isModBayesian = 0; b.isModBayesian = 0;
b.modIsFourOptions = false; b.isModFourOptions = false;
b.isModLowHealthDmg = false; b.isModLowHealthDmg = false;
b.isModFarAwayDmg = false; b.isModFarAwayDmg = false;
b.isModEntanglement = false; b.isModEntanglement = false;
b.isModMassEnergy = false; b.isModMassEnergy = false;
b.modGuardianCount = 0;
mech.Fx = 0.015; mech.Fx = 0.015;
mech.jumpForce = 0.38; mech.jumpForce = 0.38;
mech.throwChargeRate = 2; mech.throwChargeRate = 2;
mech.throwChargeMax = 50; mech.throwChargeMax = 50;
mech.maxHealth = 1; mech.maxHealth = 1;
for (let i = 0; i < b.mods.length; i++) { for (let i = 0; i < b.mods.length; i++) {
b.mods[i].have = false; b.mods[i].count = 0
} }
}, },
mods: [{ mods: [{
name: "depleted uranium rounds", name: "depleted uranium rounds",
description: "your <strong>bullets</strong> are 10% larger<br>increased mass and physical <strong class='color-d'>damage</strong>", description: `your <strong>bullets</strong> are 11% larger<br>increased mass and physical <strong class='color-d'>damage</strong>`,
have: false, //0 //0
effect: () => { count: 0,
//good for guns that do mostly projectile damage: maxCount: 4,
//testing at 1.08: spray(point blank)(+0.25), one shot(+0.16), wave beam(point blank)(+0.14) value: 1.11,
b.modBulletSize = 1.1; effect() {
b.modBulletSize *= this.value;
this.value -= 0.01
this.description = `your <strong>bullets</strong> are ${Math.floor((this.value-1)*100)}% larger<br>increased mass and physical <strong class='color-d'>damage</strong>`
} }
}, },
{ {
name: "fluoroantimonic acid", name: "fluoroantimonic acid",
description: "each <strong>bullet</strong> does extra chemical <strong class='color-d'>damage</strong><br>instant damage, unaffected by momentum", description: "each <strong>bullet</strong> does extra chemical <strong class='color-d'>damage</strong><br>instant damage, unaffected by momentum",
have: false, //1 //1
effect: () => { //good with guns that fire many bullets at low speeds, minigun, drones, junk-bots, shotgun, superballs, wavebeam maxCount: 4,
b.modExtraDmg = 0.25 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)" game.playerDmgColor = "rgba(0,80,80,0.9)"
} }
}, },
{ {
name: "fracture analysis", name: "fracture analysis",
description: "<strong>5x</strong> physical <strong class='color-d'>damage</strong> to unaware enemies<br><em>unaware enemies don't have a health bar</em>", description: "<strong>5x</strong> physical <strong class='color-d'>damage</strong> to unaware enemies<br><em>unaware enemies don't have a health bar</em>",
have: false, //2 //2
effect: () => { // good with high damage guns that strike from a distance: rail gun, drones, flechettes, spores, grenade, vacuum bomb maxCount: 1,
b.modIsCrit = true; 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", name: "kinetic bombardment",
description: "do extra <strong class='color-d'>damage</strong> from a distance<br><em>up to 50% increase at about 30 steps away</em>", description: "do extra <strong class='color-d'>damage</strong> from a distance<br><em>up to 50% increase at about 30 steps away</em>",
have: false, //3 //3
effect: () => { // good with annihilation, melee builds maxCount: 1,
count: 0,
effect() { // good with annihilation, melee builds
b.isModFarAwayDmg = true; //used in mob.damage() b.isModFarAwayDmg = true; //used in mob.damage()
} }
}, },
{ {
name: "quasistatic equilibrium", name: "quasistatic equilibrium",
description: "do extra <strong class='color-d'>damage</strong> at low health<br><em>up to 50% increase when near death</em>", description: "do extra <strong class='color-d'>damage</strong> at low health<br><em>up to 50% increase when near death</em>",
have: false, //4 //4
effect: () => { // good with annihilation, melee builds maxCount: 1,
count: 0,
effect() { // good with annihilation, melee builds
b.isModLowHealthDmg = true; //used in mob.damage() b.isModLowHealthDmg = true; //used in mob.damage()
} }
}, },
{ {
name: "auto-loading heuristics", name: "auto-loading heuristics",
description: "your <strong>delay</strong> after firing is 15% <strong>shorter</strong>", description: "your <strong>delay</strong> after firing is 12% <strong>shorter</strong>",
have: false, //5 //5
effect: () => { //good for guns with extra ammo: needles, M80, rapid fire, flak, super balls maxCount: 4,
b.modFireRate = 0.85 count: 0,
effect() { //good for guns with extra ammo: needles, M80, rapid fire, flak, super balls
b.modFireRate *= 0.88
} }
}, },
{ {
name: "desublimated ammunition", name: "desublimated ammunition",
description: "use 50% less <strong>ammo</strong> when <strong>crouching</strong>", description: "use 50% less <strong>ammo</strong> when <strong>crouching</strong>",
have: false, //6 //6
effect: () => { //good with guns that have less ammo: one shot, grenades, missiles, super balls, spray maxCount: 1,
count: 0,
effect() { //good with guns that have less ammo: one shot, grenades, missiles, super balls, spray
b.modNoAmmo = 1 b.modNoAmmo = 1
} }
}, },
{ {
name: "Lorentzian topology", name: "Lorentzian topology",
description: "your <strong>bullets</strong> last 33% <strong>longer</strong>", description: "your <strong>bullets</strong> last 33% <strong>longer</strong>",
have: false, //7 //7
effect: () => { //good with: drones, super balls, spore, missiles, wave beam(range), rapid fire(range), flak(range) maxCount: 4,
b.isModBulletsLastLonger = 1.33 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", name: "zoospore vector",
description: "enemies can discharge <strong style='letter-spacing: 2px;'>spores</strong> on <strong>death</strong><br><strong style='letter-spacing: 2px;'>spores</strong> seek out enemies", description: "enemies can discharge <strong style='letter-spacing: 2px;'>spores</strong> on <strong>death</strong><br><strong style='letter-spacing: 2px;'>spores</strong> seek out enemies",
have: false, //8 //8
effect: () => { //good late game maybe? maxCount: 4,
b.modSpores = 0.15; count: 0,
effect() { //good late game maybe?
b.modSpores += 0.15;
} }
}, },
{ {
name: "ablative synthesis", name: "ablative synthesis",
description: "rebuild your broken parts as <strong>drones</strong><br>chance to occur after being <strong>harmed</strong>", description: "rebuild your broken parts as <strong>drones</strong><br>chance to occur after being <strong>harmed</strong>",
have: false, //9 //9
effect: () => { //makes dangerous situations more survivable maxCount: 1,
count: 0,
effect() { //makes dangerous situations more survivable
b.isModDroneOnDamage = true; b.isModDroneOnDamage = true;
} }
}, },
{ {
name: "annihilation", name: "annihilation",
description: "after <strong>touching</strong> enemies, they are annihilated", description: "after <strong>touching</strong> enemies, they are annihilated",
have: false, //10 //10
effect: () => { //good with mods that heal: superconductive healing, entropy transfer maxCount: 1,
b.modAnnihilation = true count: 0,
effect() { //good with mods that heal: superconductive healing, entropy transfer
b.isModAnnihilation = true
} }
}, },
{ {
name: "high explosives", name: "high explosives",
description: "<strong class='color-e'>explosions</strong> are 33% <strong>larger</strong><br>immune to <strong>harm</strong> from <strong class='color-e'>explosions</strong>", description: "the radius of <strong class='color-e'>explosions</strong> are 20% <strong>larger</strong><br>immune to <strong>harm</strong> from <strong class='color-e'>explosions</strong>",
have: false, //11 //11
maxCount: 4,
count: 0,
effect: () => { effect: () => {
b.modExplosionRadius = 1.2; b.modExplosionRadius += 0.2;
b.isModImmuneExplosion = true; b.isModImmuneExplosion = true;
} }
}, },
{ {
name: "entanglement", name: "entanglement",
description: "using your first gun reduces <strong>harm</strong><br>scales by <strong>7%</strong> for each gun in your inventory", description: "using your first gun reduces <strong>harm</strong><br>scales by <strong>7%</strong> for each gun in your inventory",
have: false, //12 //12
effect: () => { // good with laser-bots maxCount: 1,
count: 0,
effect() { // good with laser-bots
b.isModEntanglement = true b.isModEntanglement = true
} }
}, },
{ {
name: "energy transfer", name: "energy transfer",
description: "gain <strong class='color-f'>energy</strong> proportional to <strong class='color-d'>damage</strong> done", description: "gain <strong class='color-f'>energy</strong> proportional to <strong class='color-d'>damage</strong> done",
have: false, //13 //13
effect: () => { //good with laser, and all fields maxCount: 4,
b.modEnergySiphon = 0.18; count: 0,
effect() { //good with laser, and all fields
b.modEnergySiphon += 0.18;
} }
}, },
{ {
name: "entropy transfer", name: "entropy transfer",
description: "<strong class='color-h'>heal</strong> proportional to <strong class='color-d'>damage</strong> done", description: "<strong class='color-h'>heal</strong> proportional to <strong class='color-d'>damage</strong> done",
have: false, //14 //14
effect: () => { //good with guns that overkill: one shot, grenade maxCount: 4,
b.modHealthDrain = 0.015; count: 0,
effect() { //good with guns that overkill: one shot, grenade
b.modHealthDrain += 0.015;
} }
}, },
{ {
name: "overcharge", name: "overcharge",
description: "charge <strong class='color-f'>energy</strong> <strong>33%</strong> beyond your <strong>maximum</strong>", description: "charge <strong class='color-f'>energy</strong> <strong>33%</strong> beyond your <strong>maximum</strong>",
have: false, //15 //15
effect: () => { maxCount: 4,
mech.fieldEnergyMax = 1.33 count: 0,
effect() {
mech.fieldEnergyMax += 0.33
} }
}, },
{ {
name: "supersaturation", name: "supersaturation",
description: "<strong class='color-h'>heal</strong> <strong>33%</strong> beyond your <strong>max health</strong>", description: "<strong class='color-h'>heal</strong> <strong>33%</strong> beyond your <strong>max health</strong>",
have: false, //16 //16
effect: () => { maxCount: 4,
mech.maxHealth = 1.33 count: 0,
effect() {
mech.maxHealth += 0.33
} }
}, },
{ {
name: "recursive healing", name: "recursive healing",
description: "<strong class='color-h'>healing</strong> power ups are twice as effective", description: "<strong class='color-h'>healing</strong> power ups are twice as effective",
have: false, //17 //17
effect: () => { // good with ablative synthesis, melee builds maxCount: 1,
count: 0,
effect() { // good with ablative synthesis, melee builds
b.isModRecursiveHealing = true b.isModRecursiveHealing = true
} }
}, },
{ {
name: "mass-energy equivalence", name: "mass-energy equivalence",
description: "convert the mass of <strong>power ups</strong> into <strong class='color-f'>energy</strong><br>power ups fill your <strong class='color-f'>energy</strong> and <strong class='color-h'>heal</strong> for +5%", description: "convert the mass of <strong>power ups</strong> into <strong class='color-f'>energy</strong><br>power ups fill your <strong class='color-f'>energy</strong> and <strong class='color-h'>heal</strong> for +5%",
have: false, //18 //18
maxCount: 1,
count: 0,
effect: () => { effect: () => {
b.isModMassEnergy = true // used in mech.usePowerUp b.isModMassEnergy = true // used in mech.usePowerUp
} }
@@ -219,34 +260,53 @@ const b = {
{ {
name: "+1 cardinality", name: "+1 cardinality",
description: "one extra <strong>choice</strong> when selecting <strong>power ups</strong>", description: "one extra <strong>choice</strong> when selecting <strong>power ups</strong>",
have: false, //19 //19
maxCount: 1,
count: 0,
effect: () => { effect: () => {
b.modIsFourOptions = true; b.isModFourOptions = true;
} }
}, },
{ {
name: "Bayesian inference", name: "Bayesian inference",
description: "<strong>25%</strong> chance for double <strong>power ups</strong> to drop<br>one fewer <strong>choice</strong> when selecting <strong>power ups</strong>", description: "<strong>20%</strong> chance for double <strong>power ups</strong> to drop<br>one fewer <strong>choice</strong> when selecting <strong>power ups</strong>",
have: false, //20 //20
maxCount: 1,
count: 0,
effect: () => { effect: () => {
b.isModBayesian = 0.25; b.isModBayesian = 0.20;
} }
}, },
{ {
name: "Gauss rifle", name: "Gauss rifle",
description: "<strong>launch blocks</strong> at much higher speeds<br><em>hold onto larger blocks even after getting hit</em>", description: "<strong>launch blocks</strong> at much higher speeds<br><em>hold onto larger blocks even after getting hit</em>",
have: false, //21 //21
effect: () => { // good with guns that run out of ammo maxCount: 1,
count: 0,
effect() { // good with guns that run out of ammo
mech.throwChargeRate = 4; mech.throwChargeRate = 4;
mech.throwChargeMax = 150; mech.throwChargeMax = 150;
mech.holdingMassScale = 0.05; //can hold heavier blocks with lower cost to jumping mech.holdingMassScale = 0.05; //can hold heavier blocks with lower cost to jumping
} }
}, },
{
name: "guardian",
description: "a bot <strong>protects</strong> the space around you<br>uses a <strong>short range</strong> laser that drains <strong class='color-f'>energy</strong>",
//22
maxCount: 4,
count: 0,
effect() { // good with melee builds, content skipping builds
b.modGuardianCount++;
b.guardian();
}
},
{ {
name: "squirrel-cage rotor", name: "squirrel-cage rotor",
description: "<strong>jump</strong> higher and <strong>move</strong> faster<br>reduced <strong>harm</strong> from <strong>falling</strong> ", description: "<strong>jump</strong> higher and <strong>move</strong> faster<br>reduced <strong>harm</strong> from <strong>falling</strong> ",
have: false, //22 //23
effect: () => { // good with melee builds, content skipping builds maxCount: 1,
count: 0,
effect() { // good with melee builds, content skipping builds
b.modSquirrelFx = 1.2; b.modSquirrelFx = 1.2;
mech.Fx = 0.015 * b.modSquirrelFx; mech.Fx = 0.015 * b.modSquirrelFx;
mech.jumpForce = 0.38 * 1.1; mech.jumpForce = 0.38 * 1.1;
@@ -255,9 +315,11 @@ const b = {
{ {
name: "quantum immortality", name: "quantum immortality",
description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br><em>guns, ammo, and field are randomized</em>", description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br><em>guns, ammo, and field are randomized</em>",
have: false, //23 //24
effect: () => { maxCount: 1,
b.modIsImmortal = true; count: 0,
effect() {
b.isModImmortal = true;
} }
}, },
], ],
@@ -265,7 +327,7 @@ const b = {
if (index === 'random') { if (index === 'random') {
let options = []; let options = [];
for (let i = 0; i < b.mods.length; i++) { 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 // give a random mod from the mods I don't have
@@ -275,8 +337,8 @@ const b = {
} }
} else { } else {
b.mods[index].effect(); //give specific mod b.mods[index].effect(); //give specific mod
b.modCount++ b.mods[index].count++
b.mods[index].have = true b.modCount++ //used in power up randomization
game.updateModHUD(); game.updateModHUD();
} }
}, },
@@ -756,8 +818,101 @@ const b = {
y: speed * Math.sin(dir) 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") { if (gun === "random") {
//find what guns player doesn't have //find what guns player doesn't have
options = [] options = []
@@ -768,12 +923,10 @@ const b = {
//randomly pick from list of possible guns //randomly pick from list of possible guns
gun = options[Math.floor(Math.random() * options.length)] gun = options[Math.floor(Math.random() * options.length)]
} }
if (gun === "all") { if (gun === "all") {
b.activeGun = 0; b.activeGun = 0;
b.inventoryGun = 0; b.inventoryGun = 0;
for (let i = 0; i < b.guns.length; i++) { for (let i = 0; i < b.guns.length; i++) {
b.guns[i].have = true;
b.guns[i].ammo = b.guns[i].ammoPack * ammoPacks; b.guns[i].ammo = b.guns[i].ammoPack * ammoPacks;
b.inventory[i] = i; b.inventory[i] = i;
} }
@@ -799,7 +952,7 @@ const b = {
const dir = mech.angle + (Math.random() - 0.5) * ((mech.crouch) ? 0.04 : 0.12); 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)); 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 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].frictionAir = mech.crouch ? 0.007 : 0.01;
bullet[me].do = function () { bullet[me].do = function () {
this.force.y += this.mass * 0.0005; this.force.y += this.mass * 0.0005;
@@ -829,7 +982,7 @@ const b = {
x: SPEED * Math.cos(dir), x: SPEED * Math.cos(dir),
y: SPEED * Math.sin(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].frictionAir = 0.03;
bullet[me].do = function () { bullet[me].do = function () {
this.force.y += this.mass * 0.001; this.force.y += this.mass * 0.001;
@@ -901,7 +1054,7 @@ const b = {
const me = bullet.length; 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] = 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].dmg = 1;
bullet[me].do = function () { bullet[me].do = function () {
if (this.speed < 10) this.force.y += this.mass * 0.0003; //no gravity until it slows don to improve aiming 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 this.isCharging = false
mech.fireCDcycle = mech.cycle + 2; // set fire cool down 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) 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 this.collisionFilter.category = cat.bullet
Matter.Body.setPosition(this, { Matter.Body.setPosition(this, {
x: mech.pos.x, x: mech.pos.x,
@@ -1233,7 +1386,6 @@ const b = {
this.lockedOn = null; this.lockedOn = null;
let closeDist = Infinity; let closeDist = Infinity;
//look for closest target to where the missile will be in 30 cycles //look for closest target to where the missile will be in 30 cycles
const futurePos = Vector.add(this.position, Vector.mult(this.velocity, 30)) const futurePos = Vector.add(this.position, Vector.mult(this.velocity, 30))
// ctx.beginPath(); //draw future pos // 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 mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 25 : 10) * b.modFireRate); // cool down
b.muzzleFlash(30); b.muzzleFlash(30);
const SPEED = mech.crouch ? 29 : 25 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 side1 = 17 * b.modBulletSize
const side2 = 4 * b.modBulletSize const side2 = 4 * b.modBulletSize
const totalBullets = 5 const totalBullets = 5
@@ -1351,7 +1503,7 @@ const b = {
b.fireProps(mech.crouch ? 30 : 20, mech.crouch ? 43 : 32, dir, me); //cd , speed b.fireProps(mech.crouch ? 30 : 20, mech.crouch ? 43 : 32, dir, me); //cd , speed
Matter.Body.setDensity(bullet[me], 0.0005); Matter.Body.setDensity(bullet[me], 0.0005);
bullet[me].totalCycles = 100; 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].restitution = 0.5;
bullet[me].explodeRad = 290; bullet[me].explodeRad = 290;
bullet[me].onEnd = b.explode; //makes bullet do explosive damage before despawn bullet[me].onEnd = b.explode; //makes bullet do explosive damage before despawn
@@ -1486,7 +1638,7 @@ const b = {
const dir = mech.angle; 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)); 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 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].restitution = 0.3;
// bullet[me].frictionAir = 0.01; // bullet[me].frictionAir = 0.01;
// bullet[me].friction = 0.15; // 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 mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 25 : 10) * b.modFireRate); // cool down
} }
}, },
{ // {
name: "guardian", //13 // name: "guardian", //13
description: "deploy a bot that <strong>protects</strong> you for <strong>one level</strong><br>uses a <strong>short range</strong> laser that drains <strong class='color-f'>energy</strong>", // description: "deploy a bot that <strong>protects</strong> you for <strong>one level</strong><br>uses a <strong>short range</strong> laser that drains <strong class='color-f'>energy</strong>",
ammo: 0, // ammo: 0,
ammoPack: 1, // ammoPack: 1,
have: false, // have: false,
isStarterGun: false, // isStarterGun: false,
fire() { // fire() {
const dir = mech.angle; // const dir = mech.angle;
const me = bullet.length; // const me = bullet.length;
const RADIUS = (13 + 10 * Math.random()) * b.modBulletSize //(22 + 10 * Math.random()) * b.modBulletSize // 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, { // bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 3, RADIUS, {
angle: dir, // angle: dir,
friction: 0, // friction: 0,
frictionStatic: 0, // frictionStatic: 0,
restitution: 0.5 + 0.5 * Math.random(), // restitution: 0.5 + 0.5 * Math.random(),
dmg: 0, // 0.14 //damage done in addition to the damage from momentum // dmg: 0, // 0.14 //damage done in addition to the damage from momentum
minDmgSpeed: 2, // minDmgSpeed: 2,
lookFrequency: 37 + Math.floor(27 * Math.random()), // lookFrequency: 37 + Math.floor(27 * Math.random()),
acceleration: 0.0015 + 0.0013 * Math.random(), // acceleration: 0.0015 + 0.0013 * Math.random(),
range: 500 + Math.floor(200 * Math.random()), // range: 500 + Math.floor(200 * Math.random()),
endCycle: Infinity, // endCycle: Infinity,
classType: "bullet", // classType: "bullet",
collisionFilter: { // collisionFilter: {
category: cat.bullet, // category: cat.bullet,
mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield // mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield
}, // },
lockedOn: null, // lockedOn: null,
onDmg() { // onDmg() {
this.lockedOn = null // this.lockedOn = null
}, // },
onEnd() {}, // onEnd() {},
do() { // do() {
if (!(game.cycle % this.lookFrequency)) { // if (!(game.cycle % this.lookFrequency)) {
this.lockedOn = null; // this.lockedOn = null;
let closeDist = this.range; // let closeDist = this.range;
for (let i = 0, len = mob.length; i < len; ++i) { // for (let i = 0, len = mob.length; i < len; ++i) {
const DIST = Vector.magnitude(Vector.sub(this.vertices[0], mob[i].position)); // const DIST = Vector.magnitude(Vector.sub(this.vertices[0], mob[i].position));
if (DIST - mob[i].radius < closeDist && // if (DIST - mob[i].radius < closeDist &&
Matter.Query.ray(map, this.vertices[0], mob[i].position).length === 0 && // Matter.Query.ray(map, this.vertices[0], mob[i].position).length === 0 &&
Matter.Query.ray(body, this.vertices[0], mob[i].position).length === 0) { // Matter.Query.ray(body, this.vertices[0], mob[i].position).length === 0) {
closeDist = DIST; // closeDist = DIST;
this.lockedOn = mob[i] // this.lockedOn = mob[i]
} // }
} // }
} // }
if (this.lockedOn && this.lockedOn.alive && mech.fieldMeter > 0.15) { //hit target with laser // if (this.lockedOn && this.lockedOn.alive && mech.fieldMeter > 0.15) { //hit target with laser
mech.fieldMeter -= 0.001 // mech.fieldMeter -= 0.001
//make sure you can still see target // //make sure you can still see target
const DIST = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.position)); // const DIST = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.position));
if (DIST - this.lockedOn.radius < this.range + 150 && // if (DIST - this.lockedOn.radius < this.range + 150 &&
Matter.Query.ray(map, this.vertices[0], this.lockedOn.position).length === 0 && // Matter.Query.ray(map, this.vertices[0], this.lockedOn.position).length === 0 &&
Matter.Query.ray(body, this.vertices[0], this.lockedOn.position).length === 0) { // Matter.Query.ray(body, this.vertices[0], this.lockedOn.position).length === 0) {
//find the closest vertex // //find the closest vertex
let bestVertexDistance = Infinity // let bestVertexDistance = Infinity
let bestVertex = null // let bestVertex = null
for (let i = 0; i < this.lockedOn.vertices.length; i++) { // for (let i = 0; i < this.lockedOn.vertices.length; i++) {
const dist = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.vertices[i])); // const dist = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.vertices[i]));
if (dist < bestVertexDistance) { // if (dist < bestVertexDistance) {
bestVertex = i // bestVertex = i
bestVertexDistance = dist // bestVertexDistance = dist
} // }
} // }
const dmg = b.dmgScale * 0.03; // const dmg = b.dmgScale * 0.03;
this.lockedOn.damage(dmg); // this.lockedOn.damage(dmg);
this.lockedOn.locatePlayer(); // this.lockedOn.locatePlayer();
//draw laser // //draw laser
ctx.beginPath(); // ctx.beginPath();
ctx.moveTo(this.vertices[0].x, this.vertices[0].y); // ctx.moveTo(this.vertices[0].x, this.vertices[0].y);
ctx.lineTo(this.lockedOn.vertices[bestVertex].x, this.lockedOn.vertices[bestVertex].y); // ctx.lineTo(this.lockedOn.vertices[bestVertex].x, this.lockedOn.vertices[bestVertex].y);
ctx.strokeStyle = "#f00"; // ctx.strokeStyle = "#f00";
ctx.lineWidth = "2" // ctx.lineWidth = "2"
ctx.lineDashOffset = 300 * Math.random() // ctx.lineDashOffset = 300 * Math.random()
ctx.setLineDash([50 + 100 * Math.random(), 100 * Math.random()]); // ctx.setLineDash([50 + 100 * Math.random(), 100 * Math.random()]);
ctx.stroke(); // ctx.stroke();
ctx.setLineDash([0, 0]); // ctx.setLineDash([0, 0]);
ctx.beginPath(); // ctx.beginPath();
ctx.arc(this.lockedOn.vertices[bestVertex].x, this.lockedOn.vertices[bestVertex].y, Math.sqrt(dmg) * 100, 0, 2 * Math.PI); // ctx.arc(this.lockedOn.vertices[bestVertex].x, this.lockedOn.vertices[bestVertex].y, Math.sqrt(dmg) * 100, 0, 2 * Math.PI);
ctx.fillStyle = "#f00"; // ctx.fillStyle = "#f00";
ctx.fill(); // ctx.fill();
} // }
} // }
const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos)) // const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos))
if (distanceToPlayer > this.range * 0.2) { //if far away move towards player // 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.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.acceleration)
this.frictionAir = 0.02 // this.frictionAir = 0.02
} else { //close to player // } else { //close to player
this.frictionAir = 0 // this.frictionAir = 0
//add player's velocity // //add player's velocity
Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 1), Vector.mult(player.velocity, 0.02))); // 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 // b.fireProps(mech.crouch ? 40 : 30, mech.crouch ? 50 : 15, dir, me); //cd , speed
} // }
}, // },
{ {
name: "laser", //14 name: "laser", //14
description: "drain <strong class='color-f'>energy</strong> to emit a beam of coherent <strong>light</strong><br>when crouched, initiate a fusion <strong class='color-e'>explosion</strong>", description: "drain <strong class='color-f'>energy</strong> to emit a beam of coherent <strong>light</strong><br>when crouched, initiate a fusion <strong class='color-e'>explosion</strong>",
@@ -1783,9 +1935,9 @@ const b = {
} }
//use energy to explode //use energy to explode
const energy = mech.fieldMeter * 0.25 const energy = 0.25 * Math.min(mech.fieldMeter, 1.5)
mech.fieldMeter -= energy 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 mech.fireCDcycle = mech.cycle + Math.floor(65 * b.modFireRate); // cool down
//draw laser beam //draw laser beam
@@ -2292,7 +2444,7 @@ const b = {
mask: cat.map | cat.body | cat.mob | cat.mobShield mask: cat.map | cat.body | cat.mob | cat.mobShield
}, },
minDmgSpeed: 0, minDmgSpeed: 0,
endCycle: Infinity, //game.cycle + Math.floor(265 * b.isModBulletsLastLonger), endCycle: Infinity,
count: 0, count: 0,
radius: RADIUS, radius: RADIUS,
target: null, target: null,

View File

@@ -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 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); mech.damage(dmg);
if (mob[k].onHit) mob[k].onHit(k); if (mob[k].onHit) mob[k].onHit(k);
if (b.modAnnihilation && mob[k].dropPowerUp) { if (b.isModAnnihilation && mob[k].dropPowerUp) {
mob[k].death(); mob[k].death();
game.drawList.push({ game.drawList.push({
//add dmg to draw queue //add dmg to draw queue
@@ -180,7 +180,7 @@ function mobCollisionChecks(event) {
if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) { 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))); // 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))) 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].foundPlayer();
mob[k].damage(dmg); mob[k].damage(dmg);
obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn

View File

@@ -168,9 +168,10 @@ const game = {
updateModHUD() { updateModHUD() {
let text = "" let text = ""
for (let i = 0, len = b.mods.length; i < len; i++) { //add mods 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 += "<br>" //add a new line, but not on the first line if (text) text += "<br>" //add a new line, but not on the first line
text += b.mods[i].name text += b.mods[i].name
if (b.mods[i].count > 1) text += ` (${b.mods[i].count}x)`
} }
} }
document.getElementById("mods").innerHTML = text document.getElementById("mods").innerHTML = text
@@ -447,7 +448,7 @@ const game = {
reset() { //run on first run, and each later run after you die reset() { //run on first run, and each later run after you die
b.inventory = []; //removes guns and ammo b.inventory = []; //removes guns and ammo
for (let i = 0, len = b.guns.length; i < len; ++i) { 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; if (b.guns[i].ammo != Infinity) b.guns[i].ammo = 0;
} }
b.activeGun = null; b.activeGun = null;

View File

@@ -2,16 +2,26 @@
/* TODO: ******************************************* /* 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 field graphics too dark at high energy
-max health not important
-fire rate
-slow life decay
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 mod: if you fire when out of ammo you gain 1 ammo pack at the cost of
10% max health 10% max health

View File

@@ -16,7 +16,7 @@ const level = {
// game.difficulty = 6; //for testing to simulate possible mobs spawns // game.difficulty = 6; //for testing to simulate possible mobs spawns
// b.giveGuns(0) // b.giveGuns(0)
// mech.setField(2) // mech.setField(2)
b.giveMod(20) // b.giveMod(20)
level.intro(); //starting level level.intro(); //starting level
// level.testingMap(); // level.testingMap();
@@ -36,6 +36,9 @@ const level = {
game.setZoom(); game.setZoom();
level.addToWorld(); //add bodies to game engine level.addToWorld(); //add bodies to game engine
game.draw.setPaths(); game.draw.setPaths();
for (let i = 0; i < b.modGuardianCount; i++) {
b.guardian()
}
}, },
isBuildRun: false, isBuildRun: false,
difficultyIncrease(num = 1) { difficultyIncrease(num = 1) {

View File

@@ -296,14 +296,14 @@ const mech = {
}, },
alive: true, alive: true,
death() { 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 spawn.setSpawnList(); //new mob types
game.clearNow = true; //triggers a map reset game.clearNow = true; //triggers a map reset
//count mods //count mods
let totalMods = -2; //lose 2 mods for balance reasons let totalMods = -2; //lose 2 mods for balance reasons
for (let i = 0; i < b.mods.length; i++) { for (let i = 0; i < b.mods.length; i++) {
if (b.mods[i].have) totalMods++ totalMods += b.mods[i].count
} }
function randomizeMods() { function randomizeMods() {
@@ -313,7 +313,7 @@ const mech = {
let options = []; let options = [];
for (let i = 0, len = b.mods.length; i < len; i++) { for (let i = 0, len = b.mods.length; i < len; i++) {
//can't get quantum immortality again //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 //add a new mod
if (options.length > 0) { if (options.length > 0) {
@@ -666,9 +666,11 @@ const mech = {
if (mech.fieldMeter < mech.fieldEnergyMax) { if (mech.fieldMeter < mech.fieldEnergyMax) {
mech.fieldMeter += mech.fieldRegen; mech.fieldMeter += mech.fieldRegen;
ctx.fillStyle = "rgba(0, 0, 0, 0.4)"; 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.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 { } else {
mech.fieldMeter = mech.fieldEnergyMax mech.fieldMeter = mech.fieldEnergyMax
} }

View File

@@ -107,7 +107,7 @@ const powerUps = {
choice3 = doNotHave(mech.fieldUpgrades, choice1, choice2) choice3 = doNotHave(mech.fieldUpgrades, choice1, choice2)
if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice3})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${mech.fieldUpgrades[choice3].name}</div> ${mech.fieldUpgrades[choice3].description}</div>` if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice3})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${mech.fieldUpgrades[choice3].name}</div> ${mech.fieldUpgrades[choice3].description}</div>`
} }
if (b.modIsFourOptions) { if (b.isModFourOptions) {
let choice4 = doNotHave(mech.fieldUpgrades, choice1, choice2, choice3) let choice4 = doNotHave(mech.fieldUpgrades, choice1, choice2, choice3)
if (choice4 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice4})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${mech.fieldUpgrades[choice4].name}</div> ${mech.fieldUpgrades[choice4].description}</div>` if (choice4 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice4})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${mech.fieldUpgrades[choice4].name}</div> ${mech.fieldUpgrades[choice4].description}</div>`
} }
@@ -129,7 +129,7 @@ const powerUps = {
function doNotHave(who, skip1 = -1, skip2 = -1, skip3 = -1) { function doNotHave(who, skip1 = -1, skip2 = -1, skip3 = -1) {
let options = []; let options = [];
for (let i = 0; i < who.length; i++) { 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)] if (options.length > 0) return options[Math.floor(Math.random() * options.length)]
} }
@@ -145,7 +145,7 @@ const powerUps = {
choice3 = doNotHave(b.mods, choice1, choice2) choice3 = doNotHave(b.mods, choice1, choice2)
if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice3})"><div class="grid-title"><div class="circle-grid mod"></div> &nbsp; ${b.mods[choice3].name}</div> ${b.mods[choice3].description}</div>` if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice3})"><div class="grid-title"><div class="circle-grid mod"></div> &nbsp; ${b.mods[choice3].name}</div> ${b.mods[choice3].description}</div>`
} }
if (b.modIsFourOptions) { if (b.isModFourOptions) {
let choice4 = doNotHave(b.mods, choice1, choice2, choice3) let choice4 = doNotHave(b.mods, choice1, choice2, choice3)
if (choice4 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice4})"><div class="grid-title"><div class="circle-grid mod"></div> &nbsp; ${b.mods[choice4].name}</div> ${b.mods[choice4].description}</div>` if (choice4 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice4})"><div class="grid-title"><div class="circle-grid mod"></div> &nbsp; ${b.mods[choice4].name}</div> ${b.mods[choice4].description}</div>`
} }
@@ -182,7 +182,7 @@ const powerUps = {
choice3 = doNotHave(b.guns, choice1, choice2) choice3 = doNotHave(b.guns, choice1, choice2)
if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice3})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice3].name}</div> ${b.guns[choice3].description}</div>` if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice3})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice3].name}</div> ${b.guns[choice3].description}</div>`
} }
if (b.modIsFourOptions) { if (b.isModFourOptions) {
let choice4 = doNotHave(b.guns, choice1, choice2, choice3) let choice4 = doNotHave(b.guns, choice1, choice2, choice3)
if (choice4 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice4})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice4].name}</div> ${b.guns[choice4].description}</div>` if (choice4 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice4})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice4].name}</div> ${b.guns[choice4].description}</div>`
} }