diff --git a/js/bullets.js b/js/bullets.js
index 2591a1f..191ccfd 100644
--- a/js/bullets.js
+++ b/js/bullets.js
@@ -27,7 +27,8 @@ const b = {
isModEntanglement: null,
isModMassEnergy: null,
isModFourOptions: null,
- modGuardianCount: null,
+ modLaserBotCount: null,
+ modNailBotCount: null,
modCollisionImmuneCycles: null,
modBlockDmg: null,
modPiezo: null,
@@ -55,7 +56,8 @@ const b = {
b.isModFarAwayDmg = false;
b.isModEntanglement = false;
b.isModMassEnergy = false;
- b.modGuardianCount = 0;
+ b.modLaserBotCount = 0;
+ b.modNailBotCount = 0;
b.modCollisionImmuneCycles = 30;
b.modBlockDmg = 0;
b.modPiezo = 0;
@@ -97,11 +99,29 @@ const b = {
},
{
name: "kinetic bombardment", //3
- description: "do extra damage from a distance
up to 50% increase at about 30 steps away",
+ description: "do up to 33% more damage at a distance
increase starts at about 6 steps away",
maxCount: 1,
count: 0,
effect() {
b.isModFarAwayDmg = true; //used in mob.damage()
+
+ game.drawList.push({ //draw range
+ //add dmg to draw queue
+ x: player.position.x,
+ y: player.position.y,
+ radius: 3000,
+ color: "rgba(255,0,0,0.05)",
+ time: 120
+ });
+ game.drawList.push({ //draw range
+ //add dmg to draw queue
+ x: player.position.x,
+ y: player.position.y,
+ radius: 500,
+ color: "rgba(0,0,0,0.2)",
+ time: 120
+ });
+
}
},
{
@@ -113,6 +133,16 @@ const b = {
b.isModLowHealthDmg = true; //used in mob.damage()
}
},
+ {
+ name: "high explosives", //15
+ description: "the radius of explosions are +20% larger
immune to harm from explosions",
+ maxCount: 4,
+ count: 0,
+ effect: () => {
+ b.modExplosionRadius += 0.2;
+ b.isModImmuneExplosion = true;
+ }
+ },
{
name: "auto-loading heuristics", //5
description: "your delay after firing is +12% shorter",
@@ -147,6 +177,29 @@ const b = {
count: 0,
effect() {
b.modSpores += 0.11;
+ for (let i = 0; i < 10; i++) {
+ b.spore(player) //spawn drone
+ }
+ }
+ },
+ {
+ name: "laser-bot", //10
+ description: "a bot protects the space around you
uses a short range laser that drains energy",
+ maxCount: 4,
+ count: 0,
+ effect() {
+ b.modLaserBotCount++;
+ b.guardian();
+ }
+ },
+ {
+ name: "nail-bot", //11
+ description: "a bot protects the space around you
fires a nail at targets in range",
+ maxCount: 4,
+ count: 0,
+ effect() {
+ b.modNailBotCount++;
+ b.nailBot();
}
},
{
@@ -156,29 +209,13 @@ const b = {
count: 0,
effect() {
b.isModDroneOnDamage = true;
+ for (let i = 0; i < 3; i++) {
+ b.drone() //spawn drone
+ }
}
},
{
- name: "guardian", //10
- description: "a bot protects the space around you
uses a short range laser that drains energy",
- maxCount: 4,
- count: 0,
- effect() {
- b.modGuardianCount++;
- b.guardian();
- }
- },
- {
- name: "Pauli exclusion", //11
- description: "unable to collide with enemies for +2 seconds
activates after being harmed from a collision",
- maxCount: 1,
- count: 0,
- effect() {
- b.modCollisionImmuneCycles += 120;
- }
- },
- {
- name: "bremsstrahlung radiation", //12
+ name: "bremsstrahlung radiation", //13
description: "when your field blocks it also does damage",
maxCount: 4,
count: 0,
@@ -187,27 +224,8 @@ const b = {
}
},
{
- name: "annihilation", //13
- description: "after touching enemies, they are annihilated",
- maxCount: 1,
- count: 0,
- effect() {
- b.isModAnnihilation = true
- }
- },
- {
- name: "high explosives", //14
- description: "the radius of explosions are +20% larger
immune to harm from explosions",
- maxCount: 4,
- count: 0,
- effect: () => {
- b.modExplosionRadius += 0.2;
- b.isModImmuneExplosion = true;
- }
- },
- {
- name: "entanglement", //15
- description: "using your first gun reduces harm
scales by 7% for each gun in your inventory",
+ name: "entanglement", //16
+ description: "using your first gun reduces harm
scales by 10% for each gun in your inventory",
maxCount: 1,
count: 0,
effect() {
@@ -215,88 +233,7 @@ const b = {
}
},
{
- name: "piezoelectricity", //16
- description: "gain energy proportional to harm received",
- maxCount: 4,
- count: 0,
- effect() {
- b.modPiezo += 2
- }
- },
- {
- name: "energy conservation", //17
- description: "gain energy proportional to damage done",
- maxCount: 4,
- count: 0,
- effect() {
- b.modEnergySiphon += 0.18;
- }
- },
- {
- name: "entropy exchange", //18
- description: "heal proportional to damage done",
- maxCount: 4,
- count: 0,
- effect() {
- b.modHealthDrain += 0.015;
- }
- },
- {
- name: "overcharge", //19
- description: "charge energy +33% beyond your maximum",
- maxCount: 4,
- count: 0,
- effect() {
- mech.fieldEnergyMax += 0.33
- }
- },
- {
- name: "supersaturation", //20
- description: "heal +33% beyond your max health",
- maxCount: 4,
- count: 0,
- effect() {
- mech.maxHealth += 0.33
- }
- },
- {
- name: "recursive healing", //21
- description: "healing power ups trigger an extra time.",
- maxCount: 4,
- count: 0,
- effect() {
- b.modRecursiveHealing += 1
- }
- },
- {
- name: "mass-energy equivalence", //22
- description: "convert the mass of power ups into energy
power ups fill your energy and heal for +5%",
- maxCount: 1,
- count: 0,
- effect: () => {
- b.isModMassEnergy = true // used in mech.usePowerUp
- }
- },
- {
- name: "+1 cardinality", //23
- description: "one extra choice when selecting power ups",
- maxCount: 1,
- count: 0,
- effect: () => {
- b.isModFourOptions = true;
- }
- },
- {
- name: "Bayesian inference", //24
- description: "20% chance for double power ups to drop
one fewer choice when selecting power ups",
- maxCount: 1,
- count: 0,
- effect: () => {
- b.isModBayesian = 0.20;
- }
- },
- {
- name: "squirrel-cage rotor", //25
+ name: "squirrel-cage rotor", //27
description: "jump higher and move faster
reduced harm from falling ",
maxCount: 1,
count: 0,
@@ -307,8 +244,124 @@ const b = {
}
},
{
- name: "quantum immortality", //26
- description: "after dying, continue in an alternate reality
guns, ammo, and field are randomized",
+ name: "Pauli exclusion", //12
+ description: "unable to collide with enemies for +2 seconds
activates after being harmed from a collision",
+ maxCount: 1,
+ count: 0,
+ effect() {
+ b.modCollisionImmuneCycles += 120;
+ mech.collisionImmune = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
+ }
+ },
+ {
+ name: "annihilation", //14
+ description: "after touching enemies, they are annihilated",
+ maxCount: 1,
+ count: 0,
+ effect() {
+ b.isModAnnihilation = true
+ }
+ },
+ {
+ name: "piezoelectricity", //17
+ description: "after colliding with enemies gain 50% energy",
+ maxCount: 1,
+ count: 0,
+ effect() {
+ b.modPiezo = 0.50
+ }
+ },
+ {
+ name: "energy conservation", //18
+ description: "gain energy proportional to damage done",
+ maxCount: 4,
+ count: 0,
+ effect() {
+ b.modEnergySiphon += 0.18;
+ mech.fieldMeter = mech.fieldEnergyMax
+ }
+ },
+ {
+ name: "entropy exchange", //19
+ description: "heal proportional to damage done",
+ maxCount: 4,
+ count: 0,
+ effect() {
+ b.modHealthDrain += 0.015;
+ }
+ },
+ {
+ name: "overcharge", //20
+ description: "charge energy +33% beyond your maximum",
+ maxCount: 4,
+ count: 0,
+ effect() {
+ mech.fieldEnergyMax += 0.33
+ mech.fieldMeter += 0.33
+ }
+ },
+ {
+ name: "supersaturation", //21
+ description: "heal +33% beyond your max health",
+ maxCount: 4,
+ count: 0,
+ effect() {
+ mech.maxHealth += 0.33
+ mech.addHealth(0.33)
+ }
+ },
+ {
+ name: "recursive healing", //22
+ description: "healing power ups trigger an extra time.",
+ maxCount: 4,
+ count: 0,
+ effect() {
+ b.modRecursiveHealing += 1
+ }
+ },
+ {
+ name: "mass-energy equivalence", //23
+ description: "convert the mass of power ups into energy
power ups fill your energy and heal for +5%",
+ maxCount: 1,
+ count: 0,
+ effect: () => {
+ b.isModMassEnergy = true // used in mech.usePowerUp
+ mech.fieldMeter = mech.fieldEnergyMax
+ }
+ },
+ {
+ name: "+1 cardinality", //24
+ description: "one extra choice when selecting power ups",
+ maxCount: 1,
+ count: 0,
+ effect: () => {
+ b.isModFourOptions = true;
+ }
+ },
+ {
+ name: "Bayesian inference", //25
+ description: "20% chance for double power ups to drop
one fewer choice when selecting power ups",
+ maxCount: 1,
+ count: 0,
+ effect: () => {
+ b.isModBayesian = 0.20;
+ }
+ },
+ {
+ name: "Born rule", //26
+ description: "remove all current mods
spawn new mods to replace them",
+ maxCount: 1,
+ count: 0,
+ effect: () => {
+ for (let i = 0; i < b.modCount; i++) { // spawn new mods
+ powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
+ }
+ b.setModDefaults(); // remove all mods
+ }
+ },
+ {
+ name: "quantum immortality", //28
+ description: "after dying, continue in an alternate reality
guns, ammo, field, and mods are randomized",
maxCount: 1,
count: 0,
effect() {
@@ -461,6 +514,21 @@ const b = {
}
}
},
+ onCollision(event) {
+ const pairs = event.pairs;
+ for (let i = 0, j = pairs.length; i != j; i++) {
+ //map + bullet collisions
+ if (pairs[i].bodyA.collisionFilter.category === cat.map && pairs[i].bodyB.collisionFilter.category === cat.bullet) {
+ collideBulletStatic(pairs[i].bodyB)
+ } else if (pairs[i].bodyB.collisionFilter.category === cat.map && pairs[i].bodyA.collisionFilter.category === cat.bullet) {
+ collideBulletStatic(pairs[i].bodyA)
+ }
+
+ function collideBulletStatic(obj) {
+ if (obj.onWallHit) obj.onWallHit();
+ }
+ }
+ },
explosion(where, radius) {
radius *= b.modExplosionRadius
// typically explode is used for some bullets with .onEnd
@@ -718,7 +786,7 @@ const b = {
const THRUST = 0.0015
const dir = mech.angle + 0.2 * (Math.random() - 0.5);
const RADIUS = (4.5 + 3 * Math.random()) * b.modBulletSize
- bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), RADIUS, {
+ bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 8, RADIUS, {
angle: dir,
inertia: Infinity,
friction: 0.05,
@@ -813,6 +881,75 @@ const b = {
y: speed * Math.sin(dir)
});
},
+ nail(pos, velocity, dmg = 0) {
+ const me = bullet.length;
+ bullet[me] = Bodies.rectangle(pos.x, pos.y, 25 * b.modBulletSize, 2 * b.modBulletSize, b.fireAttributes(Math.atan2(velocity.y, velocity.x)));
+ Matter.Body.setVelocity(bullet[me], velocity);
+ World.add(engine.world, bullet[me]); //add bullet to world
+ bullet[me].endCycle = game.cycle + 60 + 18 * Math.random();
+ bullet[me].dmg = dmg
+ bullet[me].do = function () {};
+ },
+ nailBot(speed = 1) {
+ const me = bullet.length;
+ const dir = mech.angle;
+ const RADIUS = (10 + 5 * Math.random()) * b.modBulletSize
+ bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 4, RADIUS, {
+ angle: dir,
+ friction: 0,
+ frictionStatic: 0,
+ restitution: 0.4 + 0.5 * Math.random(),
+ dmg: 0, // 0.14 //damage done in addition to the damage from momentum
+ minDmgSpeed: 2,
+ lookFrequency: 45 + Math.floor(17 * Math.random()),
+ acceleration: 0.0025 + 0.001 * Math.random(),
+ range: 300 + Math.floor(70 * 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)) {
+ let target
+ for (let i = 0, len = mob.length; i < len; i++) {
+ const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
+ if (dist < 2000000 && //1400*1400
+ Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
+ Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
+ target = Vector.add(mob[i].position, Vector.mult(mob[i].velocity, Math.sqrt(dist) / 60))
+ const SPEED = 50
+ b.nail(this.position, Vector.mult(Vector.normalise(Vector.sub(target, this.position)), SPEED), 0.5)
+ break;
+ }
+ }
+ }
+
+
+
+ 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.04
+ } else { //close to player
+ this.frictionAir = 0.005
+ //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)
+ });
+ },
guardian(speed = 1) {
const me = bullet.length;
const dir = mech.angle;
@@ -920,7 +1057,9 @@ const b = {
gun = options[Math.floor(Math.random() * options.length)]
}
if (gun === "all") {
+ if (b.guns[b.activeGun].switchOff) b.guns[b.activeGun].switchOff(); //run code when switching away from a gun
b.activeGun = 0;
+ if (b.guns[b.activeGun].switchOn) b.guns[b.activeGun].switchOn(); //run code when switching to a new gun
b.inventoryGun = 0;
for (let i = 0; i < b.guns.length; i++) {
b.inventory[i] = i;
@@ -930,6 +1069,7 @@ const b = {
} else {
if (!b.guns[gun].have) b.inventory.push(gun);
if (b.activeGun === null) b.activeGun = gun //if no active gun switch to new gun
+ if (b.guns[b.activeGun].switchOn) b.guns[b.activeGun].switchOn(); //run code when switching to a new gun
b.guns[gun].have = true;
b.guns[gun].ammo = b.guns[gun].ammoPack * ammoPacks;
}
@@ -1009,7 +1149,7 @@ const b = {
let dir = mech.angle - SPREAD * 2;
for (let i = 0; i < 5; i++) {
const me = bullet.length;
- bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 7 * b.modBulletSize, b.fireAttributes(dir, false));
+ bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 10, 7 * b.modBulletSize, b.fireAttributes(dir, false));
World.add(engine.world, bullet[me]); //add bullet to world
Matter.Body.setVelocity(bullet[me], {
x: SPEED * Math.cos(dir),
@@ -1077,7 +1217,7 @@ const b = {
const dir = mech.angle
const SCALE = (mech.crouch ? 0.963 : 0.95)
const wiggleMag = ((mech.crouch) ? 0.004 : 0.005) * ((mech.flipLegs === 1) ? 1 : -1)
- bullet[me] = Bodies.circle(mech.pos.x + 25 * Math.cos(dir), mech.pos.y + 25 * Math.sin(dir), 10 * b.modBulletSize, {
+ bullet[me] = Bodies.polygon(mech.pos.x + 25 * Math.cos(dir), mech.pos.y + 25 * Math.sin(dir), 10, 10 * b.modBulletSize, {
angle: dir,
cycle: -0.43, //adjust this number until the bullets line up with the cross hairs
endCycle: game.cycle + Math.floor((mech.crouch ? 155 : 120) * b.isModBulletsLastLonger),
@@ -1461,19 +1601,19 @@ const b = {
name: "grenades", //8
description: "lob a single bouncy projectile
explodes on contact or after one second",
ammo: 0,
- ammoPack: 4,
+ ammoPack: 6,
have: false,
isStarterGun: false,
fire() {
const me = bullet.length;
const dir = mech.angle; // + Math.random() * 0.05;
- bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 20 * 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), 20 * b.modBulletSize, b.fireAttributes(dir, true));
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);
- bullet[me].restitution = 0.5;
- bullet[me].explodeRad = 310;
+ bullet[me].restitution = 0.2;
+ bullet[me].explodeRad = 275;
bullet[me].onEnd = b.explode; //makes bullet do explosive damage before despawn
bullet[me].minDmgSpeed = 1;
bullet[me].onDmg = function () {
@@ -1595,87 +1735,110 @@ const b = {
}
}, {
name: "mine", //10
- description: "drop a proximity mine that ejects nails
arms after being still for 1 second",
+ description: "drop a proximity mine that sticks to walls
fires nails at enemies within range",
ammo: 0,
- ammoPack: 8,
+ ammoPack: 6,
have: false,
isStarterGun: false,
fire() {
const me = bullet.length;
const dir = mech.angle;
- bullet[me] = Bodies.rectangle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 45 * b.modBulletSize, 16 * b.modBulletSize, {
- angle: 0,
- friction: 0.3,
- frictionAir: 0,
- dmg: 0, //damage done in addition to the damage from momentum
- classType: "bullet",
- collisionFilter: {
- category: cat.bullet,
- mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield | cat.bullet
- },
- minDmgSpeed: 5,
- onDmg() {},
- onEnd() {}
- });
- b.fireProps(mech.crouch ? 40 : 20, mech.crouch ? 24 : 7, dir, me); //cd , speed
- bullet[me].torque += bullet[me].inertia * 0.0001 * (0.5 - Math.random())
+ if (mech.crouch) {
+ bullet[me] = Bodies.rectangle(mech.pos.x + 35 * Math.cos(mech.angle), mech.pos.y + 35 * Math.sin(mech.angle), 45 * b.modBulletSize, 16 * b.modBulletSize, {
+ angle: 0,
+ friction: 1,
+ frictionAir: 0,
+ dmg: 0, //damage done in addition to the damage from momentum
+ classType: "bullet",
+ collisionFilter: {
+ category: cat.bullet,
+ mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield | cat.bullet
+ },
+ minDmgSpeed: 5,
+ onDmg() {},
+ onEnd() {}
+ });
+ mech.fireCDcycle = mech.cycle + Math.floor(35 * b.modFireRate); // cool down
+ Matter.Body.setVelocity(bullet[me], {
+ x: mech.Vx / 2 + 26 * Math.cos(dir),
+ y: mech.Vy / 2 + 26 * Math.sin(dir)
+ });
+ bullet[me].torque += bullet[me].inertia * 0.0001 * (0.5 - Math.random())
+ } else {
+ bullet[me] = Bodies.rectangle(mech.pos.x, mech.pos.y + 25, 45 * b.modBulletSize, 16 * b.modBulletSize, {
+ angle: 0,
+ friction: 1,
+ frictionAir: 0,
+ dmg: 0, //damage done in addition to the damage from momentum
+ classType: "bullet",
+ collisionFilter: {
+ category: cat.bullet,
+ mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield | cat.bullet
+ },
+ minDmgSpeed: 5,
+ onDmg() {},
+ onEnd() {}
+ });
+ mech.fireCDcycle = mech.cycle + Math.floor(20 * b.modFireRate); // cool down
+ Matter.Body.setVelocity(bullet[me], {
+ x: mech.Vx,
+ y: mech.Vy
+ });
+ }
+ World.add(engine.world, bullet[me]); //add bullet to world
bullet[me].endCycle = game.cycle + 1800 + 360 * Math.random();
- bullet[me].cycle = 0
+ bullet[me].seeFrom = null;
bullet[me].restitution = 0;
- bullet[me].lookFrequency = 37 + Math.floor(37 * Math.random())
+ bullet[me].lookFrequency = 41 + Math.floor(23 * Math.random())
bullet[me].range = 700
+ bullet[me].arm = function () {
+ this.do = function () { //overwrite the do method for this bullet
+ this.force.y += this.mass * 0.002; //extra gravity
+ if (!(game.cycle % this.lookFrequency)) { //find mob targets
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (Vector.magnitudeSquared(Vector.sub(this.seeFrom, mob[i].position)) < 500000 &&
+ mob[i].dropPowerUp &&
+ Matter.Query.ray(map, this.seeFrom, mob[i].position).length === 0 &&
+ Matter.Query.ray(body, this.seeFrom, mob[i].position).length === 0) {
+ this.endCycle = 0 //end life if mob is near and visible
+ }
+ }
+ }
+ }
+ }
bullet[me].do = function () {
this.force.y += this.mass * 0.002; //extra gravity
-
- ctx.beginPath(); //draw block as grey
- ctx.moveTo(this.vertices[0].x, this.vertices[0].y);
- for (let j = 1; j < this.vertices.length; j += 1) {
- ctx.lineTo(this.vertices[j].x, this.vertices[j].y);
- }
- ctx.lineTo(this.vertices[0].x, this.vertices[0].y);
- ctx.fillStyle = "#457";
- ctx.fill();
-
- if (this.speed < 1 && !mech.isBodiesAsleep) this.cycle++
- if (this.cycle > 40) {
- this.do = function () {
- this.force.y += this.mass * 0.002; //extra gravity
- if (!(game.cycle % this.lookFrequency)) { //find mob targets
- const pos = {
- x: this.position.x,
- y: this.position.y - 8 //look from a bit higher to see things even with debris
- }
-
- for (let i = 0, len = mob.length; i < len; ++i) {
- const dist = Vector.magnitudeSquared(Vector.sub(pos, mob[i].position));
- if (dist < 500000 && //range2 = 700*700
- mob[i].dropPowerUp &&
- Matter.Query.ray(map, pos, mob[i].position).length === 0 &&
- Matter.Query.ray(body, pos, mob[i].position).length === 0) {
- this.endCycle = 0 //end life if mob is near and visible
- }
+ let collide = Matter.Query.collides(this, map) //check if collides with map
+ if (collide.length > 0) {
+ for (let i = 0; i < collide.length; i++) {
+ if (collide[i].bodyA.collisionFilter.category === cat.map || collide[i].bodyB.collisionFilter.category === cat.map) {
+ this.seeFrom = Vector.add(this.position, Vector.mult(collide[i].normal, -20)) //find the location 20 pixels perpendicular to the map
+ Matter.Body.setStatic(this, true)
+ this.arm();
+ }
+ }
+ } else { //check if collides with a body
+ collide = Matter.Query.collides(this, body)
+ if (collide.length > 0) {
+ for (let i = 0; i < collide.length; i++) {
+ if (collide[i].bodyA.collisionFilter.category === cat.body || collide[i].bodyB.collisionFilter.category === cat.body) {
+ this.seeFrom = this.position
+ this.arm();
}
}
}
}
}
bullet[me].onEnd = function () {
- const pos = {
- x: this.position.x,
- y: this.position.y - 8 //aim from a bit higher to hit things even with debris
- }
- ctx.beginPath();
- ctx.arc(pos.x, pos.y, 5, 0, 2 * Math.PI);
- ctx.fill();
+ if (!this.seeFrom) this.seeFrom = this.position
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(pos, mob[i].position));
+ const dist = Vector.magnitudeSquared(Vector.sub(this.seeFrom, mob[i].position));
if (dist < 1440000 && //1200*1200
- Matter.Query.ray(map, pos, mob[i].position).length === 0 &&
- Matter.Query.ray(body, pos, mob[i].position).length === 0) {
- //predict where the mob will be in a few cycles
- targets.push(Vector.add(mob[i].position, Vector.mult(mob[i].velocity, Math.sqrt(dist) / 60)))
+ Matter.Query.ray(map, this.seeFrom, mob[i].position).length === 0 &&
+ Matter.Query.ray(body, this.seeFrom, 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
}
}
}
@@ -1688,28 +1851,19 @@ const b = {
x: targets[index].x + SPREAD * (Math.random() - 0.5),
y: targets[index].y + SPREAD * (Math.random() - 0.5)
}
- needle(pos, Vector.mult(Vector.normalise(Vector.sub(WHERE, pos)), speed))
+ b.nail(this.seeFrom, Vector.mult(Vector.normalise(Vector.sub(WHERE, this.seeFrom)), speed), 0.5)
} else { // aim in random direction
const ANGLE = 2 * Math.PI * Math.random()
- needle(pos, {
+ b.nail(this.seeFrom, {
x: speed * Math.cos(ANGLE),
y: speed * Math.sin(ANGLE)
})
}
-
- function needle(pos, velocity) {
- const me = bullet.length;
- bullet[me] = Bodies.rectangle(pos.x, pos.y, 25 * b.modBulletSize, 2 * b.modBulletSize, b.fireAttributes(Math.atan2(velocity.y, velocity.x)));
- Matter.Body.setVelocity(bullet[me], velocity);
- World.add(engine.world, bullet[me]); //add bullet to world
- bullet[me].endCycle = game.cycle + 60 + 18 * Math.random();
- bullet[me].dmg = 0.8
- bullet[me].do = function () {};
- }
}
}
}
- }, {
+ },
+ {
name: "spores", //11
description: "fire orbs that discharge spores
spores seek out enemies",
ammo: 0,
@@ -2034,7 +2188,7 @@ const b = {
},
{
name: "pulse", //15
- description: "pump a laser that initiates a fusion explosion
each pulse drains 25% of your current energy",
+ description: "convert 25% of your energy into a pulsed laser
instantly initiates a fusion explosion",
ammo: 0,
ammoPack: Infinity,
have: false,
diff --git a/js/engine.js b/js/engine.js
index 8fc27cd..f28f3eb 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -74,10 +74,22 @@ function playerHeadCheck(event) {
}
}
-function mobCollisionChecks(event) {
+function collisionChecks(event) {
const pairs = event.pairs;
for (let i = 0, j = pairs.length; i != j; i++) {
+ // //map + bullet collisions
+ // if (pairs[i].bodyA.collisionFilter.category === cat.map && pairs[i].bodyB.collisionFilter.category === cat.bullet) {
+ // collideBulletStatic(pairs[i].bodyB)
+ // } else if (pairs[i].bodyB.collisionFilter.category === cat.map && pairs[i].bodyA.collisionFilter.category === cat.bullet) {
+ // collideBulletStatic(pairs[i].bodyA)
+ // }
+ // //triggers when the bullets hits something static
+ // function collideBulletStatic(obj, speedThreshold = 12, massThreshold = 2) {
+ // if (obj.onWallHit) obj.onWallHit();
+ // }
+
+
//body + player collision
if (game.isBodyDamage) {
if (pairs[i].bodyA === playerBody || pairs[i].bodyA === playerHead) {
@@ -126,6 +138,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);
+ mech.fieldMeter += b.modPiezo
if (b.isModAnnihilation && mob[k].dropPowerUp && !mob[k].isShielded) {
mob[k].death();
game.drawList.push({
@@ -205,7 +218,7 @@ function mobCollisionChecks(event) {
Events.on(engine, "collisionStart", function (event) {
playerOnGroundCheck(event);
playerHeadCheck(event);
- mobCollisionChecks(event);
+ collisionChecks(event);
});
Events.on(engine, "collisionActive", function (event) {
playerOnGroundCheck(event);
diff --git a/js/game.js b/js/game.js
index 4f3e9ff..780dde7 100644
--- a/js/game.js
+++ b/js/game.js
@@ -213,7 +213,9 @@ const game = {
},
switchGun() {
if (b.modNoAmmo) b.modNoAmmo = 1 //this prevents hacking the mod by switching guns
+ // if (b.guns[b.activeGun].switchOff) b.guns[b.activeGun].switchOff(); //run code when switching away from a gun
b.activeGun = b.inventory[b.inventoryGun];
+ // if (b.guns[b.activeGun].switchOn) b.guns[b.activeGun].switchOn(); //run code when switching to a new gun
game.updateGunHUD();
game.boldActiveGunHUD();
// mech.drop();
@@ -435,6 +437,7 @@ const game = {
b.guns[i].have = false;
if (b.guns[i].ammo != Infinity) b.guns[i].ammo = 0;
}
+ // if (b.activeGun && b.guns[b.activeGun].switchOff) b.guns[b.activeGun].switchOff(); //run code when switching away from a gun
b.activeGun = null;
b.setModDefaults(); //remove mods
game.updateModHUD();
diff --git a/js/index.js b/js/index.js
index f1c25f2..3f70747 100644
--- a/js/index.js
+++ b/js/index.js
@@ -2,12 +2,30 @@
/* TODO: *******************************************
*****************************************************
-add new power up class: rerolls
- let you repopulate a power up selection menu
+add setting for random drops instead of choosing
+
+mines: move targeting position to be perpendicular to stuck wall
+mines change shape of mine (maybe a octagon?)
+mines: collide with bots
+ probably don't have to fix...
+mines: add high friction, like vacuum bomb and trigger static mode after not moving for a bit
+ no need to watch collisions
+
+rework custom mode
+ custom mode grey out mods that are bad, like selection based mods
+ enable recursive mods
+ remove 5 mod cap on custom mode
+
+change nail-bot's movement
+ maybe have it move in a circle around player?
+ high friction very high acceleration towards circle location
+
+add mouse constraint in testing mode
+ https://github.com/liabru/matter-js/blob/master/examples/events.js
weekly random challenge where everyone playing each week gets the same random setup.
The randomness would be determined by the date so it would sync everyone.
- powerups still drop, but the drops are determined by a preset list that changes each week.
+ power ups still drop, but the drops are determined by a preset list that changes each week.
mod: do something at the end of each level
heal to full
@@ -18,28 +36,10 @@ mod: do something at the end of each level
take no damage
don't shoot
-selection options for field to stay with current
-
-custom mode grey out mods that are bad, like selection based mods
- not important
-
-custom mode can't use recursive mods
-
-field graphics too dark at high energy
- not important
-
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: gain energy after taking damage
- use piezoelectric name (already used)
-
mod: ground stomp on enterLand()
mod: if you fire when out of ammo you gain 1 ammo pack at the cost of
@@ -89,7 +89,7 @@ new map with repeating endlessness
field power up effects
field allows player to hold and throw living mobs
- of hack mobs
+ and hack mobs
give mobs more animal-like behaviors
like rain world
diff --git a/js/level.js b/js/level.js
index c9730c9..4f3df45 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(10)
// mech.setField(3)
- // b.giveMod(16);
+ // b.giveMod(3);
level.intro(); //starting level
// level.testingMap();
@@ -37,9 +37,12 @@ const level = {
game.setZoom();
level.addToWorld(); //add bodies to game engine
game.draw.setPaths();
- for (let i = 0; i < b.modGuardianCount; i++) {
+ for (let i = 0; i < b.modLaserBotCount; i++) {
b.guardian()
}
+ for (let i = 0; i < b.modNailBotCount; i++) {
+ b.nailBot()
+ }
},
isBuildRun: false,
difficultyIncrease(num = 1) {
diff --git a/js/mobs.js b/js/mobs.js
index e9677c3..c716a63 100644
--- a/js/mobs.js
+++ b/js/mobs.js
@@ -936,7 +936,9 @@ const mobs = {
dmg /= Math.sqrt(this.mass)
if (this.shield) dmg *= 0.04
if (b.isModLowHealthDmg) dmg *= (3 / (2 + mech.health)) //up to 50% dmg at zero player health
- if (b.isModFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(1000, Math.min(3500, this.distanceToPlayer())) - 1000) * 0.01 //up to 50% dmg at max range of 3500
+
+ // if (b.isModFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(1000, Math.min(3500, this.distanceToPlayer())) - 1000) * 0.01 //up to 50% dmg at max range of 3500
+ if (b.isModFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(500, Math.min(3000, this.distanceToPlayer())) - 500) * 0.0067 //up to 50% dmg at max range of 3500
if (b.modEnergySiphon && dmg !== Infinity) mech.fieldMeter += Math.min(this.health, dmg) * b.modEnergySiphon
if (b.modHealthDrain && dmg !== Infinity) mech.addHealth(Math.min(this.health, dmg) * b.modHealthDrain)
this.health -= dmg
diff --git a/js/player.js b/js/player.js
index a935203..26bc956 100644
--- a/js/player.js
+++ b/js/player.js
@@ -311,8 +311,10 @@ const mech = {
//find what mods I don't have
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].count < b.mods[i].maxCount) options.push(i);
+ //can't get quantum immortality or multiverse
+ if (b.mods[i].name !== "quantum immortality" &&
+ b.mods[i].name !== "level II multiverse" &&
+ b.mods[i].count < b.mods[i].maxCount) options.push(i);
}
//add a new mod
if (options.length > 0) {
@@ -439,12 +441,9 @@ const mech = {
damage(dmg) {
if (b.isModEntanglement && b.inventory[0] === b.activeGun) {
for (let i = 0, len = b.inventory.length; i < len; i++) {
- dmg *= 0.93
+ dmg *= 0.9
}
}
- if (b.modPiezo) {
- mech.fieldMeter += dmg * b.modPiezo
- }
mech.health -= dmg;
if (mech.health < 0) {
mech.health = 0;
diff --git a/js/powerups.js b/js/powerups.js
index 158b747..7915ecb 100644
--- a/js/powerups.js
+++ b/js/powerups.js
@@ -217,12 +217,12 @@ const powerUps = {
if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "ammo");
return;
}
- if (Math.random() < 0.0035 * (3 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun up to 4
+ if (Math.random() < 0.0025 * (3 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun up to 3
powerUps.spawn(x, y, "gun");
if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "gun");
return;
}
- if (Math.random() < 0.0032 * (10 - b.modCount)) { //a new mod has a low chance for each not acquired mod up to 7
+ if (Math.random() < 0.003 * (11 - b.modCount)) { //a new mod has a low chance for each not acquired mod up to 7
powerUps.spawn(x, y, "mod");
if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "mod");
return;
@@ -237,13 +237,13 @@ const powerUps = {
if (mech.fieldMode === 0) {
powerUps.spawn(x, y, "field")
if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "field")
- } else if (Math.random() < 0.6) {
+ } else if (Math.random() < 0.65) {
powerUps.spawn(x, y, "mod")
if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "mod")
- } else if (Math.random() < 0.1) {
+ } else if (Math.random() < 0.06) {
powerUps.spawn(x, y, "gun")
if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "gun")
- } else if (Math.random() < 0.1) {
+ } else if (Math.random() < 0.15) {
powerUps.spawn(x, y, "field");
if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "field");
} else if (mech.health < 0.65) {
diff --git a/style.css b/style.css
index 173b06c..e82112d 100644
--- a/style.css
+++ b/style.css
@@ -330,6 +330,13 @@ em {
letter-spacing: 1px;
}
+.color-m {
+ color: rgb(115, 61, 202);
+ letter-spacing: 1px;
+}
+
+
+
.faded {
opacity: 0.7;
font-size: 90%;