diff --git a/js/bullet.js b/js/bullet.js
index ebe2c71..33df1a5 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -274,6 +274,307 @@ const b = {
}
}
},
+ grenade() {
+
+ },
+ setGrenadeMode() {
+ grenadeDefault = function(where = { x: mech.pos.x + 30 * Math.cos(mech.angle), y: mech.pos.y + 30 * Math.sin(mech.angle) }, angle = mech.angle) {
+ const me = bullet.length;
+ bullet[me] = Bodies.circle(where.x, where.y, 15, b.fireAttributes(angle, false));
+ Matter.Body.setDensity(bullet[me], 0.0005);
+ bullet[me].explodeRad = 275;
+ bullet[me].onEnd = function() {
+ b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
+ if (mod.grenadeFragments) b.targetedNail(this.position, mod.grenadeFragments)
+ }
+ bullet[me].minDmgSpeed = 1;
+ bullet[me].beforeDmg = function() {
+ this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion
+ };
+ speed = mech.crouch ? 43 : 32
+ Matter.Body.setVelocity(bullet[me], {
+ x: mech.Vx / 2 + speed * Math.cos(angle),
+ y: mech.Vy / 2 + speed * Math.sin(angle)
+ });
+ bullet[me].endCycle = game.cycle + Math.floor(mech.crouch ? 120 : 80);
+ bullet[me].restitution = 0.4;
+ bullet[me].do = function() {
+ this.force.y += this.mass * 0.0025; //extra gravity for harder arcs
+ };
+ World.add(engine.world, bullet[me]); //add bullet to world
+ }
+ grenadeRPG = function(where = { x: mech.pos.x + 30 * Math.cos(mech.angle), y: mech.pos.y + 30 * Math.sin(mech.angle) }, angle = mech.angle) {
+ const me = bullet.length;
+ bullet[me] = Bodies.circle(where.x, where.y, 15, b.fireAttributes(angle, false));
+ Matter.Body.setDensity(bullet[me], 0.0005);
+ bullet[me].explodeRad = 275;
+ bullet[me].onEnd = function() {
+ b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
+ if (mod.grenadeFragments) b.targetedNail(this.position, mod.grenadeFragments)
+ }
+ bullet[me].minDmgSpeed = 1;
+ bullet[me].beforeDmg = function() {
+ this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion
+ };
+ speed = mech.crouch ? 43 : 32
+ Matter.Body.setVelocity(bullet[me], {
+ x: mech.Vx / 2 + speed * Math.cos(angle),
+ y: mech.Vy / 2 + speed * Math.sin(angle)
+ });
+ World.add(engine.world, bullet[me]); //add bullet to world
+
+ bullet[me].endCycle = game.cycle + 70;
+ bullet[me].frictionAir = 0.07;
+ const MAG = 0.015
+ bullet[me].thrust = {
+ x: bullet[me].mass * MAG * Math.cos(angle),
+ y: bullet[me].mass * MAG * Math.sin(angle)
+ }
+ bullet[me].do = function() {
+ this.force.x += this.thrust.x;
+ this.force.y += this.thrust.y;
+ if (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length) {
+ this.endCycle = 0; //explode if touching map or blocks
+ }
+ };
+ }
+ grenadeVacuum = function(where = { x: mech.pos.x + 30 * Math.cos(mech.angle), y: mech.pos.y + 30 * Math.sin(mech.angle) }, angle = mech.angle) {
+ const me = bullet.length;
+ bullet[me] = Bodies.circle(where.x, where.y, 20, b.fireAttributes(angle, false));
+ Matter.Body.setDensity(bullet[me], 0.0003);
+ bullet[me].explodeRad = 325 + Math.floor(Math.random() * 50);;
+ bullet[me].onEnd = function() {
+ b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
+ if (mod.grenadeFragments) b.targetedNail(this.position, mod.grenadeFragments)
+ }
+ bullet[me].beforeDmg = function() {};
+ bullet[me].restitution = 0.4;
+ bullet[me].do = function() {
+ this.force.y += this.mass * 0.0025; //extra gravity for harder arcs
+
+ const suckCycles = 40
+ if (game.cycle > this.endCycle - suckCycles) { //suck
+ const that = this
+
+ function suck(who, radius = that.explodeRad * 3.2) {
+ for (i = 0, len = who.length; i < len; i++) {
+ const sub = Vector.sub(that.position, who[i].position);
+ const dist = Vector.magnitude(sub);
+ if (dist < radius && dist > 150) {
+ knock = Vector.mult(Vector.normalise(sub), mag * who[i].mass / Math.sqrt(dist));
+ who[i].force.x += knock.x;
+ who[i].force.y += knock.y;
+ }
+ }
+ }
+ let mag = 0.1
+ if (game.cycle > this.endCycle - 5) {
+ mag = -0.22
+ suck(mob, this.explodeRad * 3)
+ suck(body, this.explodeRad * 2)
+ suck(powerUp, this.explodeRad * 1.5)
+ suck(bullet, this.explodeRad * 1.5)
+ suck([player], this.explodeRad * 1.3)
+ } else {
+ mag = 0.11
+ suck(mob, this.explodeRad * 3)
+ suck(body, this.explodeRad * 2)
+ suck(powerUp, this.explodeRad * 1.5)
+ suck(bullet, this.explodeRad * 1.5)
+ suck([player], this.explodeRad * 1.3)
+ }
+ //keep bomb in place
+ Matter.Body.setVelocity(this, {
+ x: 0,
+ y: 0
+ });
+ //draw suck
+ const radius = 2.75 * this.explodeRad * (this.endCycle - game.cycle) / suckCycles
+ ctx.fillStyle = "rgba(0,0,0,0.1)";
+ ctx.beginPath();
+ ctx.arc(this.position.x, this.position.y, radius, 0, 2 * Math.PI);
+ ctx.fill();
+ }
+ };
+ speed = 35
+ bullet[me].endCycle = game.cycle + 70;
+ if (mech.crouch) {
+ speed += 9
+ bullet[me].endCycle += 20;
+ }
+ Matter.Body.setVelocity(bullet[me], {
+ x: mech.Vx / 2 + speed * Math.cos(angle),
+ y: mech.Vy / 2 + speed * Math.sin(angle)
+ });
+ World.add(engine.world, bullet[me]); //add bullet to world
+ }
+
+ grenadeNeutron = function(where = { x: mech.pos.x + 30 * Math.cos(mech.angle), y: mech.pos.y + 30 * Math.sin(mech.angle) }, angle = mech.angle) {
+ const me = bullet.length;
+ bullet[me] = Bodies.polygon(where.x, where.y, 10, 4, b.fireAttributes(angle, false));
+ b.fireProps(mech.crouch ? 45 : 25, mech.crouch ? 35 : 20, angle, me); //cd , speed
+ Matter.Body.setDensity(bullet[me], 0.000001);
+ bullet[me].endCycle = Infinity;
+ bullet[me].frictionAir = 0;
+ bullet[me].friction = 1;
+ bullet[me].frictionStatic = 1;
+ bullet[me].restitution = 0;
+ bullet[me].minDmgSpeed = 0;
+ bullet[me].damageRadius = 100;
+ bullet[me].maxDamageRadius = 450 + 130 * mod.isNeutronSlow + 130 * mod.isNeutronImmune //+ 150 * Math.random()
+ bullet[me].radiusDecay = (0.81 + 0.15 * mod.isNeutronSlow + 0.15 * mod.isNeutronImmune) / mod.isBulletsLastLonger
+ bullet[me].stuckTo = null;
+ bullet[me].stuckToRelativePosition = null;
+ bullet[me].vacuumSlow = 0.97;
+ if (mod.isRewindGrenade && input.down) {
+ Matter.Body.setVelocity(bullet[me], {
+ x: 0,
+ y: 0
+ });
+ bullet[me].maxDamageRadius *= 1.3
+ mech.rewind(200, false)
+ }
+ bullet[me].beforeDmg = function() {};
+ bullet[me].stuck = function() {};
+ bullet[me].do = function() {
+ function onCollide(that) {
+ that.collisionFilter.mask = 0; //non collide with everything
+ Matter.Body.setVelocity(that, {
+ x: 0,
+ y: 0
+ });
+ that.do = that.radiationMode;
+ }
+
+ const mobCollisions = Matter.Query.collides(this, mob)
+ if (mobCollisions.length) {
+ onCollide(this)
+ this.stuckTo = mobCollisions[0].bodyA
+ mobs.statusDoT(this.stuckTo, 0.5, 360) //apply radiation damage status effect on direct hits
+
+ if (this.stuckTo.isVerticesChange) {
+ this.stuckToRelativePosition = {
+ x: 0,
+ y: 0
+ }
+ } else {
+ //find the relative position for when the mob is at angle zero by undoing the mobs rotation
+ this.stuckToRelativePosition = Vector.rotate(Vector.sub(this.position, this.stuckTo.position), -this.stuckTo.angle)
+ }
+ this.stuck = function() {
+ if (this.stuckTo && this.stuckTo.alive) {
+ const rotate = Vector.rotate(this.stuckToRelativePosition, this.stuckTo.angle) //add in the mob's new angle to the relative position vector
+ Matter.Body.setPosition(this, Vector.add(Vector.add(rotate, this.stuckTo.velocity), this.stuckTo.position))
+ Matter.Body.setVelocity(this, this.stuckTo.velocity); //so that it will move properly if it gets unstuck
+ } else {
+ this.collisionFilter.mask = cat.map | cat.body | cat.player | cat.mob; //non collide with everything but map
+ this.stuck = function() {
+ this.force.y += this.mass * 0.001;
+ }
+ }
+ }
+ } else {
+ const bodyCollisions = Matter.Query.collides(this, body)
+ if (bodyCollisions.length) {
+ if (!bodyCollisions[0].bodyA.isNotHoldable) {
+ onCollide(this)
+ this.stuckTo = bodyCollisions[0].bodyA
+ //find the relative position for when the mob is at angle zero by undoing the mobs rotation
+ this.stuckToRelativePosition = Vector.rotate(Vector.sub(this.position, this.stuckTo.position), -this.stuckTo.angle)
+ } else {
+ this.do = this.radiationMode;
+ }
+ this.stuck = function() {
+ if (this.stuckTo) {
+ const rotate = Vector.rotate(this.stuckToRelativePosition, this.stuckTo.angle) //add in the mob's new angle to the relative position vector
+ Matter.Body.setPosition(this, Vector.add(Vector.add(rotate, this.stuckTo.velocity), this.stuckTo.position))
+ // Matter.Body.setVelocity(this, this.stuckTo.velocity); //so that it will move properly if it gets unstuck
+ } else {
+ this.force.y += this.mass * 0.001;
+ }
+ }
+ } else {
+ if (Matter.Query.collides(this, map).length) {
+ onCollide(this)
+ } else { //if colliding with nothing just fall
+ this.force.y += this.mass * 0.001;
+ }
+ }
+ }
+ }
+ bullet[me].radiationMode = function() { //the do code after the bullet is stuck on something, projects a damaging radiation field
+ this.stuck(); //runs different code based on what the bullet is stuck to
+ if (!mech.isBodiesAsleep) {
+ this.damageRadius = this.damageRadius * 0.85 + 0.15 * this.maxDamageRadius //smooth radius towards max
+ this.maxDamageRadius -= this.radiusDecay
+ if (this.damageRadius < 15) {
+ this.endCycle = 0;
+ } else {
+ //aoe damage to player
+ if (!mod.isNeutronImmune && Vector.magnitude(Vector.sub(player.position, this.position)) < this.damageRadius) {
+ const DRAIN = 0.0023
+ if (mech.energy > DRAIN) {
+ mech.energy -= DRAIN
+ } else {
+ mech.energy = 0;
+ mech.damage(0.00015)
+ }
+ }
+ //aoe damage to mobs
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (Vector.magnitude(Vector.sub(mob[i].position, this.position)) < this.damageRadius) {
+ let dmg = b.dmgScale * 0.082
+ if (Matter.Query.ray(map, mob[i].position, this.position).length > 0) dmg *= 0.25 //reduce damage if a wall is in the way
+ if (mob[i].shield) dmg *= 4 //x5 to make up for the /5 that shields normally take
+ mob[i].damage(dmg);
+ mob[i].locatePlayer();
+ if (mod.isNeutronSlow) {
+ Matter.Body.setVelocity(mob[i], {
+ x: mob[i].velocity.x * this.vacuumSlow,
+ y: mob[i].velocity.y * this.vacuumSlow
+ });
+ }
+ }
+ }
+ ctx.beginPath();
+ ctx.arc(this.position.x, this.position.y, this.damageRadius, 0, 2 * Math.PI);
+ ctx.globalCompositeOperation = "lighter"
+ ctx.fillStyle = `rgba(25,139,170,${0.2+0.06*Math.random()})`;
+ ctx.fill();
+ ctx.globalCompositeOperation = "source-over"
+ if (mod.isNeutronSlow) {
+ const that = this
+
+ function slow(who, radius = that.explodeRad * 3.2) {
+ for (i = 0, len = who.length; i < len; i++) {
+ const sub = Vector.sub(that.position, who[i].position);
+ const dist = Vector.magnitude(sub);
+ if (dist < radius) {
+ Matter.Body.setVelocity(who[i], {
+ x: who[i].velocity.x * that.vacuumSlow,
+ y: who[i].velocity.y * that.vacuumSlow
+ });
+ }
+ }
+ }
+ slow(body, this.damageRadius)
+ slow([player], this.damageRadius)
+ }
+ }
+ }
+ }
+ }
+
+ if (mod.isNeutronBomb) {
+ b.grenade = grenadeNeutron
+ } else if (mod.isVacuumBomb) {
+ b.grenade = grenadeVacuum
+ } else if (mod.isRPG) {
+ b.grenade = grenadeRPG
+ } else {
+ b.grenade = grenadeDefault
+ }
+ },
missile(where, angle, speed, size = 1, spawn = 0) {
const me = bullet.length;
bullet[me] = Bodies.rectangle(where.x, where.y, 30 * size, 4 * size, {
@@ -1237,16 +1538,16 @@ const b = {
}
}
},
- randomBot(where = mech.pos, isKeep = true) {
- if (Math.random() < 0.2) {
- b.orbitBot();
- if (isKeep) mod.orbitBotCount++;
- } else if (Math.random() < 0.25) {
- b.nailBot(where)
- if (isKeep) mod.nailBotCount++;
- } else if (Math.random() < 0.33) {
+ randomBot(where = mech.pos, isKeep = true, isAll = true) {
+ if (Math.random() < 0.2 && isAll) {
b.laserBot(where)
if (isKeep) mod.laserBotCount++;
+ } else if (Math.random() < 0.25 && isAll) {
+ b.orbitBot();
+ if (isKeep) mod.orbitBotCount++;
+ } else if (Math.random() < 0.33) {
+ b.nailBot(where)
+ if (isKeep) mod.nailBotCount++;
} else if (Math.random() < 0.5) {
b.foamBot(where)
if (isKeep) mod.foamBotCount++;
@@ -2334,32 +2635,6 @@ const b = {
const wiggle = Vector.mult(transverse, wiggleMag * Math.cos(this.cycle * 0.35) * ((i % 2) ? -1 : 1))
Matter.Body.setPosition(this, Vector.add(this.position, wiggle))
}
- // if (mod.isWaveReflect) { //single reflection
- // const sub = Vector.sub(this.position, mech.pos)
- // if (Vector.magnitude(sub) > 630) {
- // // Matter.Body.setPosition(this, Vector.add(this.position, Vector.mult(Vector.normalise(sub), -2 * POCKET_RANGE))) //teleport to opposite side
- // if (!this.isJustReflected) {
- // Matter.Body.setVelocity(this, Vector.mult(this.velocity, -1)); //reflect
- // this.isJustReflected = true;
- // }
- // }
- // }
-
- // if (mod.isWaveReflect) {
- // Matter.Body.setPosition(this, Vector.add(this.position, player.velocity)) //bullets move with player
-
- // Matter.Body.setPosition(this, Vector.add(this.position, Vector.mult(Vector.normalise(sub), -2 * POCKET_RANGE))) //teleport to opposite side
-
- // const sub = Vector.sub(this.position, mech.pos)
- // if (Vector.magnitude(sub) > 630) {
- // if (!this.isJustReflected) {
- // Matter.Body.setVelocity(this, Vector.mult(this.velocity, -1)); //reflect
- // this.isJustReflected = true;
- // }
- // } else {
- // this.isJustReflected = false
- // }
- // }
}
});
World.add(engine.world, bullet[me]); //add bullet to world
@@ -2431,48 +2706,6 @@ const b = {
}
}
},
- // {
- // name: "flak",
- // description: "fire a cluster of short range projectiles
explodes on contact or after half a second",
- // ammo: 0,
- // ammoPack: 4,
- // defaultAmmoPack: 4, //use to revert ammoPack after mod changes drop rate
- // have: false,
- // fire() {
- // mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 25 : 10) * b.fireCD); // cool down
- // b.muzzleFlash(30);
- // const SPEED = mech.crouch ? 29 : 25
- // const END = Math.floor(mech.crouch ? 30 : 18);
- // const side1 = 17
- // const side2 = 4
- // const totalBullets = 6
- // const angleStep = (mech.crouch ? 0.06 : 0.25) / totalBullets
- // let dir = mech.angle - angleStep * totalBullets / 2;
- // for (let i = 0; i < totalBullets; i++) { //5 -> 7
- // dir += angleStep
- // const me = bullet.length;
- // bullet[me] = Bodies.rectangle(mech.pos.x + 50 * Math.cos(mech.angle), mech.pos.y + 50 * Math.sin(mech.angle), side1, side2, b.fireAttributes(dir));
- // World.add(engine.world, bullet[me]); //add bullet to world
- // Matter.Body.setVelocity(bullet[me], {
- // x: (SPEED + 15 * Math.random() - 2 * i) * Math.cos(dir),
- // y: (SPEED + 15 * Math.random() - 2 * i) * Math.sin(dir)
- // });
- // bullet[me].endCycle = 2 * i + game.cycle + END
- // bullet[me].restitution = 0;
- // bullet[me].friction = 1;
- // bullet[me].explodeRad = (mech.crouch ? 95 : 75) + (Math.random() - 0.5) * 50;
- // bullet[me].onEnd = function() {
- // b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
- // }
- // bullet[me].beforeDmg = function() {
- // this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion
- // };
- // bullet[me].do = function() {
- // // this.force.y += this.mass * 0.0004;
- // }
- // }
- // }
- // },
{
name: "grenades",
description: "lob a single bouncy projectile
explodes on contact or after one second",
@@ -2480,46 +2713,8 @@ const b = {
ammoPack: 5,
have: false,
fire() {
-
- },
- fireNormal() {
- 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), 15, b.fireAttributes(dir, false));
- Matter.Body.setDensity(bullet[me], 0.0005);
- bullet[me].explodeRad = 275;
- bullet[me].onEnd = function() {
- b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
- if (mod.grenadeFragments) b.targetedNail(this.position, mod.grenadeFragments)
- }
- bullet[me].minDmgSpeed = 1;
- bullet[me].beforeDmg = function() {
- this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion
- };
- if (mod.isRPG) {
- b.fireProps(35, mech.crouch ? 60 : -15, dir, me); //cd , speed
- bullet[me].endCycle = game.cycle + 70;
- bullet[me].frictionAir = 0.07;
- const MAG = 0.015
- bullet[me].thrust = {
- x: bullet[me].mass * MAG * Math.cos(dir),
- y: bullet[me].mass * MAG * Math.sin(dir)
- }
- bullet[me].do = function() {
- this.force.x += this.thrust.x;
- this.force.y += this.thrust.y;
- if (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length) {
- this.endCycle = 0; //explode if touching map or blocks
- }
- };
- } else {
- b.fireProps(mech.crouch ? 40 : 30, mech.crouch ? 43 : 32, dir, me); //cd , speed
- bullet[me].endCycle = game.cycle + Math.floor(mech.crouch ? 120 : 80);
- bullet[me].restitution = 0.4;
- bullet[me].do = function() {
- this.force.y += this.mass * 0.0025; //extra gravity for harder arcs
- };
- }
+ mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 40 : 30) * b.fireCD); // cool down
+ b.grenade()
},
fireNeutron() {
const me = bullet.length;
@@ -2539,6 +2734,14 @@ const b = {
bullet[me].stuckTo = null;
bullet[me].stuckToRelativePosition = null;
bullet[me].vacuumSlow = 0.97;
+ if (mod.isRewindGrenade && input.down) {
+ Matter.Body.setVelocity(bullet[me], {
+ x: 0,
+ y: 0
+ });
+ bullet[me].maxDamageRadius *= 1.3
+ mech.rewind(200, false)
+ }
bullet[me].beforeDmg = function() {};
bullet[me].stuck = function() {};
bullet[me].do = function() {
@@ -2669,69 +2872,6 @@ const b = {
}
}
},
- fireVacuum() {
- 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.fireAttributes(dir, false));
- Matter.Body.setDensity(bullet[me], 0.0003);
- bullet[me].explodeRad = 350 + Math.floor(Math.random() * 50);;
- bullet[me].onEnd = function() {
- b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
- if (mod.grenadeFragments) b.targetedNail(this.position, mod.grenadeFragments)
- }
- bullet[me].beforeDmg = function() {};
- const cd = mech.crouch ? 90 : 75
- b.fireProps(cd, mech.crouch ? 46 : 35, dir, me); //cd , speed
- bullet[me].endCycle = game.cycle + cd;
- bullet[me].restitution = 0.4;
- bullet[me].do = function() {
- this.force.y += this.mass * 0.0025; //extra gravity for harder arcs
-
- const suckCycles = 40
- if (game.cycle > this.endCycle - suckCycles) { //suck
- const that = this
-
- function suck(who, radius = that.explodeRad * 3.2) {
- for (i = 0, len = who.length; i < len; i++) {
- const sub = Vector.sub(that.position, who[i].position);
- const dist = Vector.magnitude(sub);
- if (dist < radius && dist > 150) {
- knock = Vector.mult(Vector.normalise(sub), mag * who[i].mass / Math.sqrt(dist));
- who[i].force.x += knock.x;
- who[i].force.y += knock.y;
- }
- }
- }
- let mag = 0.1
- if (game.cycle > this.endCycle - 5) {
- mag = -0.22
- suck(mob, this.explodeRad * 3)
- suck(body, this.explodeRad * 2)
- suck(powerUp, this.explodeRad * 1.5)
- suck(bullet, this.explodeRad * 1.5)
- suck([player], this.explodeRad * 1.3)
- } else {
- mag = 0.11
- suck(mob, this.explodeRad * 3)
- suck(body, this.explodeRad * 2)
- suck(powerUp, this.explodeRad * 1.5)
- suck(bullet, this.explodeRad * 1.5)
- suck([player], this.explodeRad * 1.3)
- }
- //keep bomb in place
- Matter.Body.setVelocity(this, {
- x: 0,
- y: 0
- });
- //draw suck
- const radius = 2.75 * this.explodeRad * (this.endCycle - game.cycle) / suckCycles
- ctx.fillStyle = "rgba(0,0,0,0.1)";
- ctx.beginPath();
- ctx.arc(this.position.x, this.position.y, radius, 0, 2 * Math.PI);
- ctx.fill();
- }
- };
- }
},
{
name: "mine",
@@ -2959,7 +3099,7 @@ const b = {
if (mod.isRailAreaDamage) {
mob[i].force.x += 2 * FORCE.x;
mob[i].force.y += 2 * FORCE.y;
- const damage = b.dmgScale * 0.1 * Math.sqrt(DEPTH)
+ const damage = b.dmgScale * 0.13 * Math.sqrt(DEPTH)
mob[i].damage(damage);
mob[i].locatePlayer();
game.drawList.push({ //add dmg to draw queue
diff --git a/js/level.js b/js/level.js
index 48cf96a..e963f02 100644
--- a/js/level.js
+++ b/js/level.js
@@ -17,11 +17,11 @@ const level = {
// game.zoomScale = 1000;
// game.setZoom();
// mech.setField("wormhole")
- // b.giveGuns("shotgun")
+ // b.giveGuns("grenades")
// mod.isIncendiary = true
// mod.is3Missiles = true
- // mod.giveMod("shotgun slug")
- // mod.giveMod("diffuse beam")
+ // mod.giveMod("CPT reversal")
+ // mod.giveMod("causality bombs")
level.intro(); //starting level
// level.testing(); //not in rotation
diff --git a/js/mods.js b/js/mods.js
index d5a8957..d81d4e9 100644
--- a/js/mods.js
+++ b/js/mods.js
@@ -108,21 +108,6 @@ const mod = {
return mod.foamBotCount + mod.nailBotCount + mod.laserBotCount + mod.boomBotCount + mod.plasmaBotCount + mod.orbitBotCount
},
mods: [{
- name: "integrated armament",
- description: "increase damage by 25%
your inventory can only hold 1 gun",
- maxCount: 1,
- count: 0,
- allowed() {
- return b.inventory.length < 2
- },
- requires: "no more than 1 gun",
- effect() {
- mod.isOneGun = true;
- },
- remove() {
- mod.isOneGun = false;
- }
- }, {
name: "capacitor",
description: "increase damage by 1%
for every 7 stored energy",
maxCount: 1,
@@ -176,7 +161,7 @@ const mod = {
maxCount: 1,
count: 0,
allowed() {
- return mod.isEnergyLoss && mech.maxEnergy === 1 && !mod.isMissileField && !mod.isSporeField && !mod.isTimeAvoidDeath
+ return mod.isEnergyLoss && mech.maxEnergy === 1 && !mod.isMissileField && !mod.isSporeField && !mod.isRewindAvoidDeath
},
requires: "heat engine, not max energy increase, CPT, missile or spore nano-scale",
effect() {
@@ -210,9 +195,9 @@ const mod = {
maxCount: 6,
count: 0,
allowed() {
- return true
+ return mech.Fx === 0.016
},
- requires: "",
+ requires: "base movement speed",
effect: () => {
mod.restDamage += 0.25
},
@@ -252,6 +237,22 @@ const mod = {
mod.isAcidDmg = false;
}
},
+ {
+ name: "integrated armament",
+ description: "increase damage by 25%
your inventory can only hold 1 gun",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return b.inventory.length < 2
+ },
+ requires: "no more than 1 gun",
+ effect() {
+ mod.isOneGun = true;
+ },
+ remove() {
+ mod.isOneGun = false;
+ }
+ },
{
name: "negative feedback",
description: "increase damage by 6%
for every 10 missing base health",
@@ -371,78 +372,6 @@ const mod = {
mod.throwChargeRate = 1
}
},
- {
- name: "reaction inhibitor",
- description: "mobs spawn with 12% less health",
- maxCount: 3,
- count: 0,
- allowed() {
- return mod.nailsDeathMob || mod.sporesOnDeath || mod.isExplodeMob
- },
- requires: "zoospore vector or impact shear or thermal runaway",
- effect: () => {
- mod.mobSpawnWithHealth *= 0.88
-
- //set all mobs at full health to 0.85
- for (let i = 0; i < mob.length; i++) {
- if (mob.health > mod.mobSpawnWithHealth) mob.health = mod.mobSpawnWithHealth
- }
- },
- remove() {
- mod.mobSpawnWithHealth = 1;
- }
- },
- {
- name: "zoospore vector",
- description: "mobs produce spores when they die
9% chance",
- maxCount: 9,
- count: 0,
- allowed() {
- return !mod.nailsDeathMob && !mod.isExplodeMob
- },
- requires: "not impact shear or thermal runaway",
- effect() {
- mod.sporesOnDeath += 0.09;
- for (let i = 0; i < 8; i++) {
- b.spore(mech.pos)
- }
- },
- remove() {
- mod.sporesOnDeath = 0;
- }
- },
- {
- name: "impact shear",
- description: "mobs release a nail when they die
nails target nearby mobs",
- maxCount: 9,
- count: 0,
- allowed() {
- return !mod.sporesOnDeath && !mod.isExplodeMob
- },
- requires: "not zoospore vector or thermal runaway",
- effect: () => {
- mod.nailsDeathMob++
- },
- remove() {
- mod.nailsDeathMob = 0;
- }
- },
- {
- name: "thermal runaway",
- description: "mobs explode when they die
be careful",
- maxCount: 1,
- count: 0,
- allowed() {
- return (mod.haveGunCheck("missiles") || mod.isIncendiary || (mod.haveGunCheck("grenades") && !mod.isNeutronBomb) || mod.haveGunCheck("vacuum bomb") || mod.isPulseLaser || mod.isMissileField || mod.boomBotCount > 1 || mod.isFlechetteExplode) && !mod.sporesOnDeath && !mod.nailsDeathMob
- },
- requires: "an explosive damage source, not zoospore vector or impact shear",
- effect: () => {
- mod.isExplodeMob = true;
- },
- remove() {
- mod.isExplodeMob = false;
- }
- },
{
name: "ammonium nitrate",
description: "increase explosive damage by 20%
increase explosive radius by 20%",
@@ -508,15 +437,87 @@ const mod = {
mod.isImmuneExplosion = false;
}
},
+ {
+ name: "thermal runaway",
+ description: "mobs explode when they die
be careful",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return (mod.haveGunCheck("missiles") || mod.isIncendiary || (mod.haveGunCheck("grenades") && !mod.isNeutronBomb) || mod.haveGunCheck("vacuum bomb") || mod.isPulseLaser || mod.isMissileField || mod.boomBotCount > 1 || mod.isFlechetteExplode) && !mod.sporesOnDeath && !mod.nailsDeathMob && !mod.isBotSpawner
+ },
+ requires: "an explosive damage source, no other mob death mods",
+ effect: () => {
+ mod.isExplodeMob = true;
+ },
+ remove() {
+ mod.isExplodeMob = false;
+ }
+ },
+ {
+ name: "reaction inhibitor",
+ description: "mobs spawn with 12% less health",
+ maxCount: 3,
+ count: 0,
+ allowed() {
+ return mod.nailsDeathMob || mod.sporesOnDeath || mod.isExplodeMob || mod.isBotSpawner
+ },
+ requires: "any mob death mod",
+ effect: () => {
+ mod.mobSpawnWithHealth *= 0.88
+
+ //set all mobs at full health to 0.85
+ for (let i = 0; i < mob.length; i++) {
+ if (mob.health > mod.mobSpawnWithHealth) mob.health = mod.mobSpawnWithHealth
+ }
+ },
+ remove() {
+ mod.mobSpawnWithHealth = 1;
+ }
+ },
+ {
+ name: "zoospore vector",
+ description: "mobs produce spores when they die
9% chance",
+ maxCount: 9,
+ count: 0,
+ allowed() {
+ return !mod.nailsDeathMob && !mod.isExplodeMob && !mod.isBotSpawner
+ },
+ requires: "no other mob death mods",
+ effect() {
+ mod.sporesOnDeath += 0.09;
+ for (let i = 0; i < 8; i++) {
+ b.spore(mech.pos)
+ }
+ },
+ remove() {
+ mod.sporesOnDeath = 0;
+ }
+ },
+ {
+ name: "impact shear",
+ description: "mobs release a nail when they die
nails target nearby mobs",
+ maxCount: 9,
+ count: 0,
+ allowed() {
+ return !mod.sporesOnDeath && !mod.isExplodeMob && !mod.isBotSpawner
+ },
+ requires: "no other mob death mods",
+ effect: () => {
+ mod.nailsDeathMob++
+ },
+ remove() {
+ mod.nailsDeathMob = 0;
+ }
+ },
{
name: "scrap bots",
description: "20% chance to build a bot after killing a mob
the bot lasts for about 20 seconds",
maxCount: 3,
count: 0,
allowed() {
- return mod.totalBots() > 0
+ return mod.totalBots() > 0 && !mod.sporesOnDeath && !mod.nailsDeathMob && !mod.isExplodeMob
},
- requires: "a bot",
+ requires: "a bot and no other mob death mods",
effect() {
mod.isBotSpawner += 0.20;
},
@@ -524,23 +525,6 @@ const mod = {
mod.isBotSpawner = 0;
}
},
- {
- name: "bot fabrication",
- description: "anytime you collect 5 rerolls
use them to build a random bot",
- maxCount: 1,
- count: 0,
- allowed() {
- return powerUps.reroll.rerolls > 5 || build.isCustomSelection
- },
- requires: "at least 6 rerolls",
- effect() {
- mod.isRerollBots = true;
- powerUps.reroll.changeRerolls(0)
- },
- remove() {
- mod.isRerollBots = false;
- }
- },
{
name: "nail-bot",
description: "a bot fires nails at targets in line of sight",
@@ -664,9 +648,9 @@ const mod = {
maxCount: 9,
count: 0,
allowed() {
- return true
+ return mech.maxEnergy > 0.5
},
- requires: "",
+ requires: "maximum energy above 50%",
effect() {
mod.laserBotCount++;
b.laserBot();
@@ -746,6 +730,23 @@ const mod = {
}
}
},
+ {
+ name: "bot fabrication",
+ description: "anytime you collect 5 rerolls
use them to build a random bot",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return powerUps.reroll.rerolls > 5 || build.isCustomSelection
+ },
+ requires: "at least 6 rerolls",
+ effect() {
+ mod.isRerollBots = true;
+ powerUps.reroll.changeRerolls(0)
+ },
+ remove() {
+ mod.isRerollBots = false;
+ }
+ },
{
name: "perimeter defense",
description: "reduce harm by 3%
for each of your permanent bots",
@@ -1039,18 +1040,50 @@ const mod = {
},
{
name: "CPT reversal",
- description: "rewind 1.5 - 5 seconds to avoid harm
drains 66 - 220 energy",
+ description: "rewind 1.5 - 5 seconds to avoid harm
drains 66 - 220 energy",
maxCount: 1,
count: 0,
- allowed() {
- return mech.maxEnergy > 0.99 && (mech.fieldUpgrades[mech.fieldMode].name !== "nano-scale manufacturing" || mech.maxEnergy > 1) && mech.fieldUpgrades[mech.fieldMode].name !== "standing wave harmonics" && !mod.isEnergyHealth && !mod.isEnergyLoss && !mod.isPiezo
+ allowed() { //&& (mech.fieldUpgrades[mech.fieldMode].name !== "nano-scale manufacturing" || mech.maxEnergy > 1)
+ return mech.maxEnergy > 0.99 && mech.fieldUpgrades[mech.fieldMode].name !== "standing wave harmonics" && !mod.isEnergyHealth && !mod.isEnergyLoss && !mod.isPiezo
},
requires: "not nano-scale, mass-energy, standing wave, acute stress, piezoelectricity",
effect() {
- mod.isTimeAvoidDeath = true;
+ mod.isRewindAvoidDeath = true;
},
remove() {
- mod.isTimeAvoidDeath = false;
+ mod.isRewindAvoidDeath = false;
+ }
+ },
+ {
+ name: "causality bots",
+ description: "when you rewind, build some bots
that protect you for about 7 seconds",
+ maxCount: 3,
+ count: 0,
+ allowed() {
+ return mod.isRewindAvoidDeath || mod.isRewindEnergy
+ },
+ requires: "CPT",
+ effect() {
+ mod.isRewindBot++;
+ },
+ remove() {
+ mod.isRewindBot = 0;
+ }
+ },
+ {
+ name: "causality bombs",
+ description: "before you rewind drop some grenades",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return mod.isRewindAvoidDeath
+ },
+ requires: "CPT",
+ effect() {
+ mod.isRewindGrenade = true;
+ },
+ remove() {
+ mod.isRewindGrenade = false;
}
},
{
@@ -1059,7 +1092,7 @@ const mod = {
maxCount: 1,
count: 0,
allowed() {
- return !mod.isEnergyHealth && !mod.isTimeAvoidDeath
+ return !mod.isEnergyHealth && !mod.isRewindAvoidDeath
},
requires: "not mass-energy equivalence, CPT reversal",
effect() {
@@ -1094,7 +1127,7 @@ const mod = {
maxCount: 1,
count: 0,
allowed() {
- return !mod.isEnergyLoss && !mod.isPiezo && !mod.isTimeAvoidDeath && !mod.isSpeedHarm && mech.fieldUpgrades[mech.fieldMode].name !== "negative mass field"
+ return !mod.isEnergyLoss && !mod.isPiezo && !mod.isRewindAvoidDeath && !mod.isSpeedHarm && mech.fieldUpgrades[mech.fieldMode].name !== "negative mass field"
},
requires: "not piezoelectricity, acute stress response, 1st law, negative mass field",
effect: () => {
@@ -1163,7 +1196,7 @@ const mod = {
},
{
name: "energy conservation",
- description: "7% of damage done recovered as energy",
+ description: "6% of damage done recovered as energy",
maxCount: 9,
count: 0,
allowed() {
@@ -1171,7 +1204,7 @@ const mod = {
},
requires: "some increased damage",
effect() {
- mod.energySiphon += 0.07;
+ mod.energySiphon += 0.06;
},
remove() {
mod.energySiphon = 0;
@@ -2355,12 +2388,14 @@ const mod = {
allowed() {
return mod.haveGunCheck("grenades") && !mod.isVacuumBomb && !mod.isNeutronBomb
},
- requires: "grenades, not vacuum bomb",
+ requires: "grenades, not vacuum bomb, neutron",
effect() {
mod.isRPG = true;
+ b.setGrenadeMode()
},
remove() {
mod.isRPG = false;
+ b.setGrenadeMode()
}
},
{
@@ -2374,17 +2409,11 @@ const mod = {
requires: "grenades, not rocket-propelled",
effect() {
mod.isVacuumBomb = true;
- for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
- if (b.guns[i].name === "grenades") b.guns[i].fire = b.guns[i].fireVacuum
- }
+ b.setGrenadeMode()
},
remove() {
mod.isVacuumBomb = false;
- if (!mod.isNeutronBomb) {
- for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
- if (b.guns[i].name === "grenades") b.guns[i].fire = (mod.isNeutronBomb) ? b.guns[i].fireNeutron : b.guns[i].fireNormal
- }
- }
+ b.setGrenadeMode()
}
},
{
@@ -2398,15 +2427,11 @@ const mod = {
requires: "grenades, not rocket-propelled or fragmentation",
effect() {
mod.isNeutronBomb = true;
- for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
- if (b.guns[i].name === "grenades") b.guns[i].fire = b.guns[i].fireNeutron
- }
+ b.setGrenadeMode()
},
remove() {
mod.isNeutronBomb = false;
- for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
- if (b.guns[i].name === "grenades") b.guns[i].fire = (mod.isVacuumBomb) ? b.guns[i].fireVacuum : b.guns[i].fireNormal
- }
+ b.setGrenadeMode()
}
},
{
@@ -3671,5 +3696,7 @@ const mod = {
isBotDamage: null,
isBanish: null,
isMaxEnergyMod: null,
- isLowEnergyDamage: null
+ isLowEnergyDamage: null,
+ isRewindBot: null,
+ isRewindGrenade: null
}
\ No newline at end of file
diff --git a/js/player.js b/js/player.js
index 2a5cc64..7e7408a 100644
--- a/js/player.js
+++ b/js/player.js
@@ -485,65 +485,104 @@ const mech = {
if (mod.energyRegen === 0) dmg *= 0.4 //0.22 + 0.78 * mech.energy //77% damage reduction at zero energy
if (mod.isTurret && mech.crouch) dmg *= 0.5;
if (mod.isEntanglement && b.inventory[0] === b.activeGun) {
- for (let i = 0, len = b.inventory.length; i < len; i++) {
- dmg *= 0.85 // 1 - 0.15
- }
+ for (let i = 0, len = b.inventory.length; i < len; i++) dmg *= 0.85 // 1 - 0.15
}
return dmg
},
- damage(dmg) {
- if (mod.isTimeAvoidDeath && mech.energy > 0.66) {
- const steps = Math.floor(Math.min(299, 137 * mech.energy)) //go back 2 seconds at 100% energy
- let history = mech.history[(mech.cycle - steps) % 300]
- Matter.Body.setPosition(player, history.position);
- Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
- // move bots to follow player
- for (let i = 0; i < bullet.length; i++) {
- if (bullet[i].botType) {
- Matter.Body.setPosition(bullet[i], Vector.add(player.position, {
- x: 250 * (Math.random() - 0.5),
- y: 250 * (Math.random() - 0.5)
- }));
- Matter.Body.setVelocity(bullet[i], {
- x: 0,
- y: 0
- });
+ rewind(steps, isDrain = true) {
+ let history = mech.history[(mech.cycle - steps) % 300]
+ Matter.Body.setPosition(player, history.position);
+ Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
+ // move bots to follow player
+ for (let i = 0; i < bullet.length; i++) {
+ if (bullet[i].botType) {
+ Matter.Body.setPosition(bullet[i], Vector.add(player.position, {
+ x: 250 * (Math.random() - 0.5),
+ y: 250 * (Math.random() - 0.5)
+ }));
+ Matter.Body.setVelocity(bullet[i], {
+ x: 0,
+ y: 0
+ });
+ }
+ }
+ if (isDrain) {
+ mech.energy = Math.max(mech.energy - steps / 136, 0.01)
+ }
+ mech.immuneCycle = mech.cycle + 30; //player is immune to collision damage for 30 cycles
+
+ let isDrawPlayer = true
+ const shortPause = function() {
+ if (mech.defaultFPSCycle < mech.cycle) { //back to default values
+ game.fpsCap = game.fpsCapDefault
+ game.fpsInterval = 1000 / game.fpsCap;
+ document.getElementById("dmg").style.transition = "opacity 1s";
+ document.getElementById("dmg").style.opacity = "0";
+ } else {
+ requestAnimationFrame(shortPause);
+ if (isDrawPlayer) {
+ isDrawPlayer = false
+ ctx.save();
+ ctx.translate(canvas.width2, canvas.height2); //center
+ ctx.scale(game.zoom / game.edgeZoomOutSmooth, game.zoom / game.edgeZoomOutSmooth); //zoom in once centered
+ ctx.translate(-canvas.width2 + mech.transX, -canvas.height2 + mech.transY); //translate
+ for (let i = 1; i < steps; i++) {
+ history = mech.history[(mech.cycle - i) % 300]
+ mech.pos.x = history.position.x
+ mech.pos.y = history.position.y
+ mech.draw();
+ }
+ ctx.restore();
+ mech.resetHistory()
}
}
+ };
- mech.energy = Math.max(mech.energy - steps / 136, 0.01)
- mech.immuneCycle = mech.cycle + 30; //player is immune to collision damage for 30 cycles
-
- let isDrawPlayer = true
- const shortPause = function() {
- if (mech.defaultFPSCycle < mech.cycle) { //back to default values
- game.fpsCap = game.fpsCapDefault
- game.fpsInterval = 1000 / game.fpsCap;
- } else {
- requestAnimationFrame(shortPause);
- if (isDrawPlayer) {
- isDrawPlayer = false
-
- ctx.save();
- ctx.translate(canvas.width2, canvas.height2); //center
- ctx.scale(game.zoom / game.edgeZoomOutSmooth, game.zoom / game.edgeZoomOutSmooth); //zoom in once centered
- ctx.translate(-canvas.width2 + mech.transX, -canvas.height2 + mech.transY); //translate
- for (let i = 1; i < steps; i++) {
- history = mech.history[(mech.cycle - i) % 300]
- mech.pos.x = history.position.x
- mech.pos.y = history.position.y
- mech.draw();
- }
- ctx.restore();
- mech.resetHistory()
+ if (mech.defaultFPSCycle < mech.cycle) requestAnimationFrame(shortPause);
+ game.fpsCap = (isDrain ? 3 : 5) //1 is longest pause, 4 is standard
+ game.fpsInterval = 1000 / game.fpsCap;
+ mech.defaultFPSCycle = mech.cycle
+ if (mod.isRewindBot) {
+ const len = (isDrain ? steps * 0.042 : 2) * mod.isRewindBot
+ for (let i = 0; i < len; i++) {
+ where = mech.history[(mech.cycle - i * 40) % 300].position //spread out spawn locations along past history
+ b.randomBot({
+ x: where.x + 100 * (Math.random() - 0.5),
+ y: where.y + 100 * (Math.random() - 0.5)
+ }, false, false)
+ bullet[bullet.length - 1].endCycle = game.cycle + 360 + Math.floor(180 * Math.random()) //6-9 seconds
+ }
+ }
+ },
+ damage(dmg) {
+ if (mod.isRewindAvoidDeath && mech.energy > 0.66) {
+ const steps = Math.floor(Math.min(299, 137 * mech.energy)) //go back 2 seconds at 100% energy
+ if (mod.isRewindGrenade) {
+ for (let i = 1, len = Math.floor(3 + steps / 60); i < len; i++) {
+ b.grenade(Vector.add(mech.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -i * Math.PI / len) //fire different angles for each grenade
+ const who = bullet[bullet.length - 1]
+ if (mod.isVacuumBomb) {
+ Matter.Body.setVelocity(who, {
+ x: who.velocity.x * 0.5,
+ y: who.velocity.y * 0.5
+ });
+ } else if (mod.isRPG) {
+ who.endCycle = (who.endCycle - game.cycle) * 0.2 + game.cycle
+ } else if (mod.isNeutronBomb) {
+ Matter.Body.setVelocity(who, {
+ x: who.velocity.x * 0.3,
+ y: who.velocity.y * 0.3
+ });
+ } else {
+ Matter.Body.setVelocity(who, {
+ x: who.velocity.x * 0.5,
+ y: who.velocity.y * 0.5
+ });
+ who.endCycle = (who.endCycle - game.cycle) * 0.5 + game.cycle
}
}
- };
-
- if (mech.defaultFPSCycle < mech.cycle) requestAnimationFrame(shortPause);
- game.fpsCap = 3 //1 is shortest pause, 4 is standard
- game.fpsInterval = 1000 / game.fpsCap;
- mech.defaultFPSCycle = mech.cycle
+ }
+ mech.rewind(steps)
return
}
mech.lastHarmCycle = mech.cycle
@@ -1765,7 +1804,7 @@ const mech = {
mech.grabPowerUp();
mech.lookForPickUp(180);
- const DRAIN = 0.0011
+ const DRAIN = 0.0013
if (mech.energy > DRAIN) {
mech.energy -= DRAIN;
if (mech.energy < DRAIN) {
diff --git a/style.css b/style.css
index ca62443..f3e2516 100644
--- a/style.css
+++ b/style.css
@@ -517,13 +517,20 @@ em {
.color-harm {
/* color: */
/* text-shadow: #FC0 1px 0 10px; */
- background-color: hsla(325, 100%, 85%, 0.15);
+ background-color: hsla(51, 100%, 71%, 0.187);
padding: 2px;
border-radius: 4px;
letter-spacing: 1px;
font-weight: 100;
}
+/* .color-rewind {
+ background-image: linear-gradient(to left, #fff, #bbb);
+ border-radius: 5px;
+ padding: 2px;
+ letter-spacing: 1px;
+} */
+
.color-r {
color: #f7b;
letter-spacing: 1px;
diff --git a/todo.txt b/todo.txt
index 7ee8521..ba43a92 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,21 +1,19 @@
-*********** NEXT PATCH ***********
+******************************************************** NEXT PATCH ********************************************************
-added more requirements to various mods
+mod: causality bots - before you rewind, build bots that protect you for for 7 seconds
-CPT reversal is more flexible with energy
- 1.5-5 seconds of rewind drains 66% - 220% energy
+mod grenade: causality bombs - before you rewind, drop some grenades
-mod: exothermic process - renamed acute stress response
-mod: heat engine - reduce max energy by 50 increase damage by 40%
-mod: Gibbs free energy - gain 5% damage for every 10 energy below 100
-************** BUGS **************
+******************************************************** BUGS ********************************************************
-(fixed) red square mobs no longer die on contact
- might be side effects (we put the player invincibility after mob on damage code)
+mod and mob are too similar
(always) make it so that when you are immune to harm you can either jump on mobs or you pass through them
+(always) is there a way to check if the player is stuck inside the map or block
+ trigger a short term non-collide if that occurs
+
(4+ reports before potential fix) bug - crouch and worm hole? -> crouch locked in
players have extra gravity
might be from the short jump code
@@ -31,20 +29,39 @@ mod: Gibbs free energy - gain 5% damage for every 10 energy below 100
(repeatable almost every time) bug - mines spawn extra mines when fired at thin map wall while jumping
-************** TODO **************
+******************************************************** TODO ********************************************************
-mod that gives a bonus for low energy
- damage again or something different
- requires heat engine
+combine fragmentation grenades that that mod that makes railguns fragment into nails into one single mod, and let it apply to shotgun slug
-CPT like mods
- delayed rewind: after taking damage, play for 2 seconds, then rewind to just before you took damage
- and return lost health
- this might need code to run in a field to work
- time dilation field?
- gain a scrap bot after rewinding
- use ammo to rewind instead of energy
- explode the area where you were hit before rewinding
+mod: power up magnetism - power ups drift towards player
+ where would this code go?
+
+super balls start at 3, not 4
+ have to balance damage
+
+RPG might need a buff
+
+retrocausality bomb should fire 3 grenades at once that spread out a small bit before they explode?
+ this means you'd have to make grenades a method.
+
+make different move methods
+ mod: crouch charge jump
+ mod: double jump
+
+mod: when mobs are at full health you do 40% to them
+
+mechanic: failed technology - add mods to the mod pool with a dumb effect
+ don't show up in custom?
+ negative effect (one time effects are better to avoid code clutter)
+ remove all your energy
+ eject all your rerolls (not bad with dup)
+ teleport to the start of the level
+ remove your bots (requires you to have some bots)
+ your bots are changed to random bots
+
+mod - move super fast, go intangible, drain energy very fast
+ this is like a dodge roll
+ mod for standing wave?, cloaking?
spawn a few power ups on the final boss level
@@ -279,7 +296,7 @@ n-gon outreach ideas
javascript:(function(){var script=document.createElement('script');script.onload=function(){var stats=new Stats();document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//mrdoob.github.io/stats.js/build/stats.min.js';document.head.appendChild(script);})()
-************** LORE **************
+******************************************************** LORE ********************************************************
lore - a robot (the player) gains self awareness
each mod/gun/field is a new tech