CPT mods
mod: causality bots - before you rewind, build bots that protect you for for 7 seconds mod grenade: causality bombs - before you rewind, drop some grenades
This commit is contained in:
500
js/bullet.js
500
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 <strong>cluster</strong> of short range <strong>projectiles</strong><br><strong class='color-e'>explodes</strong> on <strong>contact</strong> 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 <strong>bouncy</strong> projectile<br><strong class='color-e'>explodes</strong> on <strong>contact</strong> 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
|
||||
|
||||
@@ -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
|
||||
|
||||
299
js/mods.js
299
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 <strong class='color-d'>damage</strong> by <strong>25%</strong><br>your inventory can only hold <strong>1 gun</strong>",
|
||||
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 <strong class='color-d'>damage</strong> by <strong>1%</strong><br>for every <strong>7</strong> stored <strong class='color-f'>energy</strong>",
|
||||
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 <strong class='color-d'>damage</strong> by <strong>25%</strong><br>your inventory can only hold <strong>1 gun</strong>",
|
||||
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 <strong class='color-d'>damage</strong> by <strong>6%</strong><br>for every <strong>10</strong> missing base <strong>health</strong>",
|
||||
@@ -371,78 +372,6 @@ const mod = {
|
||||
mod.throwChargeRate = 1
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "reaction inhibitor",
|
||||
description: "mobs spawn with <strong>12%</strong> less <strong>health</strong>",
|
||||
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 <strong class='color-p' style='letter-spacing: 2px;'>spores</strong> when they <strong>die</strong><br><strong>9%</strong> 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 <strong>nail</strong> when they <strong>die</strong><br>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 <strong class='color-e'>explode</strong> when they <strong>die</strong><br><em>be careful</em>",
|
||||
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 <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>20%</strong><br>increase <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>20%</strong>",
|
||||
@@ -508,15 +437,87 @@ const mod = {
|
||||
mod.isImmuneExplosion = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "thermal runaway",
|
||||
description: "mobs <strong class='color-e'>explode</strong> when they <strong>die</strong><br><em>be careful</em>",
|
||||
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 <strong>12%</strong> less <strong>health</strong>",
|
||||
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 <strong class='color-p' style='letter-spacing: 2px;'>spores</strong> when they <strong>die</strong><br><strong>9%</strong> 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 <strong>nail</strong> when they <strong>die</strong><br>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: "<strong>20%</strong> chance to build a <strong>bot</strong> after killing a mob<br>the bot lasts for about <strong>20</strong> 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 <strong>5</strong> <strong class='color-r'>rerolls</strong><br>use them to build a <strong>random bot</strong>",
|
||||
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 <strong>nails</strong> 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 <strong>5</strong> <strong class='color-r'>rerolls</strong><br>use them to build a <strong>random bot</strong>",
|
||||
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 <strong class='color-harm'>harm</strong> by <strong>3%</strong><br>for each of your permanent <strong>bots</strong>",
|
||||
@@ -1039,18 +1040,50 @@ const mod = {
|
||||
},
|
||||
{
|
||||
name: "CPT reversal",
|
||||
description: "<strong>rewind 1.5 - 5</strong> seconds to avoid <strong class='color-harm'>harm</strong><br>drains <strong>66 - 220</strong> <strong class='color-f'>energy</strong>",
|
||||
description: "<strong class='color-rewind'>rewind</strong> <strong>1.5 - 5</strong> seconds to avoid <strong class='color-harm'>harm</strong><br>drains <strong>66 - 220</strong> <strong class='color-f'>energy</strong>",
|
||||
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 <strong class='color-rewind'>rewind</strong>, build some <strong>bots</strong><br>that protect you for about <strong>7</strong> 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 <strong class='color-rewind'>rewind</strong> drop some <strong>grenades</strong>",
|
||||
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: "<strong>7%</strong> of <strong class='color-d'>damage</strong> done recovered as <strong class='color-f'>energy</strong>",
|
||||
description: "<strong>6%</strong> of <strong class='color-d'>damage</strong> done recovered as <strong class='color-f'>energy</strong>",
|
||||
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
|
||||
}
|
||||
59
js/player.js
59
js/player.js
@@ -485,15 +485,11 @@ 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
|
||||
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 });
|
||||
@@ -510,8 +506,9 @@ const mech = {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -519,11 +516,12 @@ const mech = {
|
||||
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
|
||||
@@ -541,9 +539,50 @@ const mech = {
|
||||
};
|
||||
|
||||
if (mech.defaultFPSCycle < mech.cycle) requestAnimationFrame(shortPause);
|
||||
game.fpsCap = 3 //1 is shortest pause, 4 is standard
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
63
todo.txt
63
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
|
||||
|
||||
Reference in New Issue
Block a user