missile rework
mod - neutron bomb is a grenade mod, it's damage is 33% higher direct hits also apply radiation damage over time missiles aim better, accelerate quicker, push blocks out of the way better crouch fire mode rapidly launches missiles vertically
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
|
||||
.jsbeautifyrc
|
||||
.DS_Store
|
||||
|
||||
355
js/bullet.js
355
js/bullet.js
@@ -290,12 +290,14 @@ const b = {
|
||||
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
|
||||
},
|
||||
minDmgSpeed: 10,
|
||||
lookFrequency: Math.floor(15 + Math.random() * 3),
|
||||
explodeRad: 170 + 60 * Math.random(),
|
||||
lookFrequency: Math.floor(10 + Math.random() * 3),
|
||||
explodeRad: 180 + 60 * Math.random(),
|
||||
density: 0.02, //0.001 is normal
|
||||
beforeDmg() {
|
||||
Matter.Body.setDensity(this, 0.0001); //reduce density to normal
|
||||
this.tryToLockOn();
|
||||
this.endCycle = 0; //bullet ends cycle after doing damage // also triggers explosion
|
||||
}, //this.endCycle = 0 //triggers despawn
|
||||
},
|
||||
onEnd() {
|
||||
b.explosion(this.position, this.explodeRad * size); //makes bullet do explosive damage at end
|
||||
if (spawn) {
|
||||
@@ -310,15 +312,14 @@ const b = {
|
||||
lockedOn: null,
|
||||
tryToLockOn() {
|
||||
let closeDist = Infinity;
|
||||
//look for closest target to where the missile will be in 30 cycles
|
||||
const futurePos = Vector.add(this.position, Vector.mult(this.velocity, 50))
|
||||
const futurePos = Vector.add(this.position, Vector.mult(this.velocity, 30)) //look for closest target to where the missile will be in 30 cycles
|
||||
this.lockedOn = null;
|
||||
// const futurePos = this.lockedOn ? :Vector.add(this.position, Vector.mult(this.velocity, 50))
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (
|
||||
mob[i].alive && mob[i].dropPowerUp &&
|
||||
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
|
||||
Matter.Query.ray(body, this.position, mob[i].position).length === 0
|
||||
Matter.Query.ray(map, this.position, mob[i].position).length === 0
|
||||
// && Matter.Query.ray(body, this.position, mob[i].position).length === 0
|
||||
) {
|
||||
const futureDist = Vector.magnitude(Vector.sub(futurePos, mob[i].position));
|
||||
if (futureDist < closeDist) {
|
||||
@@ -347,21 +348,20 @@ const b = {
|
||||
y: Math.sin(this.angle)
|
||||
};
|
||||
const target = Vector.normalise(Vector.sub(this.position, this.lockedOn.position));
|
||||
if (Vector.dot(target, face) > -0.98) {
|
||||
// const target = Vector.normalise(Vector.sub(this.position, this.lockedOn.position));
|
||||
const dot = Vector.dot(target, face)
|
||||
const aim = Math.min(0.08, (1 + dot) * 1)
|
||||
if (Vector.cross(target, face) > 0) {
|
||||
Matter.Body.rotate(this, 0.1);
|
||||
Matter.Body.rotate(this, aim);
|
||||
} else {
|
||||
Matter.Body.rotate(this, -0.1);
|
||||
}
|
||||
this.frictionAir = 0.06; //extra friction if turning
|
||||
} else {
|
||||
this.frictionAir = 0.025; //low friction if not turning
|
||||
Matter.Body.rotate(this, -aim);
|
||||
}
|
||||
this.frictionAir = Math.min(0.1, Math.max(0.04, (1 + dot) * 1)) //0.08; //extra friction if turning
|
||||
}
|
||||
//accelerate in direction bullet is facing
|
||||
const dir = this.angle; // + (Math.random() - 0.5);
|
||||
this.force.x += Math.cos(dir) * thrust;
|
||||
this.force.y += Math.sin(dir) * thrust;
|
||||
const dir = this.angle;
|
||||
this.force.x += thrust * Math.cos(dir);
|
||||
this.force.y += thrust * Math.sin(dir);
|
||||
|
||||
ctx.beginPath(); //draw rocket
|
||||
ctx.arc(this.position.x - Math.cos(this.angle) * (25 * size - 3) + (Math.random() - 0.5) * 4,
|
||||
@@ -380,7 +380,7 @@ const b = {
|
||||
}
|
||||
},
|
||||
});
|
||||
const thrust = 0.0044 * bullet[me].mass;
|
||||
const thrust = 0.0065 * bullet[me].mass;
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: mech.Vx / 2 + speed * Math.cos(angle),
|
||||
y: mech.Vy / 2 + speed * Math.sin(angle)
|
||||
@@ -2355,55 +2355,55 @@ const b = {
|
||||
name: "missiles",
|
||||
description: "launch missiles that <strong>accelerate</strong> towards <strong>mobs</strong><br><strong class='color-e'>explodes</strong> when near target",
|
||||
ammo: 0,
|
||||
ammoPack: 3,
|
||||
ammoPack: 3.3,
|
||||
have: false,
|
||||
fireCycle: 0,
|
||||
ammoLoaded: 0,
|
||||
fire() {
|
||||
//missile(where, dir, speed, size = 1, spawn = 0) {
|
||||
if (mod.is3Missiles) {
|
||||
if (mech.crouch) {
|
||||
mech.fireCDcycle = mech.cycle + 50 * b.fireCD; // cool down
|
||||
const direction = {
|
||||
x: Math.cos(mech.angle),
|
||||
y: Math.sin(mech.angle)
|
||||
}
|
||||
const push = Vector.mult(Vector.perp(direction), 0.0007)
|
||||
mech.fireCDcycle = mech.cycle + 18 * b.fireCD; // cool down
|
||||
for (let i = 0; i < 3; i++) {
|
||||
//missile(where, dir, speed, size = 1, spawn = 0) {
|
||||
b.missile({
|
||||
x: mech.pos.x + 40 * direction.x,
|
||||
y: mech.pos.y + 40 * direction.y
|
||||
}, mech.angle + 0.06 * (1 - i), 0, 0.7, mod.recursiveMissiles)
|
||||
bullet[bullet.length - 1].force.x += push.x * (i - 1);
|
||||
bullet[bullet.length - 1].force.y += push.y * (i - 1);
|
||||
x: mech.pos.x,
|
||||
y: mech.pos.y - 40
|
||||
}, -Math.PI / 2 + 0.08 * (1 - i), 0, 0.7, mod.recursiveMissiles)
|
||||
}
|
||||
} else {
|
||||
mech.fireCDcycle = mech.cycle + 35 * b.fireCD; // cool down
|
||||
mech.fireCDcycle = mech.cycle + 55 * b.fireCD; // cool down
|
||||
const direction = {
|
||||
x: Math.cos(mech.angle),
|
||||
y: Math.sin(mech.angle)
|
||||
}
|
||||
const push = Vector.mult(Vector.perp(direction), 0.0008)
|
||||
const push = Vector.mult(Vector.perp(direction), 0.02)
|
||||
for (let i = 0; i < 3; i++) {
|
||||
//missile(where, dir, speed, size = 1, spawn = 0) {
|
||||
b.missile({
|
||||
x: mech.pos.x + 40 * direction.x,
|
||||
y: mech.pos.y + 40 * direction.y
|
||||
}, mech.angle, 0, 0.7, mod.recursiveMissiles)
|
||||
}, mech.angle + 0.1 * (Math.random() - 0.5), 5, 0.7, mod.recursiveMissiles)
|
||||
bullet[bullet.length - 1].force.x += push.x * (i - 1);
|
||||
bullet[bullet.length - 1].force.y += push.y * (i - 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mech.fireCDcycle = mech.cycle + Math.floor(mech.crouch ? 40 : 25) * b.fireCD; // cool down
|
||||
if (mech.crouch) {
|
||||
mech.fireCDcycle = mech.cycle + 18 * b.fireCD; // cool down
|
||||
b.missile({
|
||||
x: mech.pos.x,
|
||||
y: mech.pos.y - 40
|
||||
},
|
||||
-Math.PI / 2, 0, 1, mod.recursiveMissiles)
|
||||
} else {
|
||||
mech.fireCDcycle = mech.cycle + 55 * b.fireCD; // cool down
|
||||
b.missile({
|
||||
x: mech.pos.x + 40 * Math.cos(mech.angle),
|
||||
y: mech.pos.y + 40 * Math.sin(mech.angle) - 3
|
||||
},
|
||||
mech.angle + (0.5 - Math.random()) * (mech.crouch ? 0 : 0.2),
|
||||
-3 * (0.5 - Math.random()) + (mech.crouch ? 25 : -8) * b.fireCD,
|
||||
1, mod.recursiveMissiles)
|
||||
bullet[bullet.length - 1].force.y += 0.0006; //a small push down at first to make it seem like the missile is briefly falling
|
||||
mech.angle + (0.5 - Math.random()) * (mech.crouch ? 0 : 0.2), 20, 1, mod.recursiveMissiles)
|
||||
// bullet[bullet.length - 1].force.y += 0.01; //a small push down at first to make it seem like the missile is briefly falling
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2461,7 +2461,7 @@ const b = {
|
||||
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), 20, b.fireAttributes(dir, false));
|
||||
bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 15, b.fireAttributes(dir, false));
|
||||
Matter.Body.setDensity(bullet[me], 0.0005);
|
||||
bullet[me].explodeRad = 275;
|
||||
bullet[me].onEnd = function() {
|
||||
@@ -2497,6 +2497,129 @@ const b = {
|
||||
};
|
||||
}
|
||||
},
|
||||
fireNeutron() {
|
||||
const me = bullet.length;
|
||||
const dir = mech.angle;
|
||||
bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 10, 4, b.fireAttributes(dir, false));
|
||||
b.fireProps(mech.crouch ? 45 : 25, mech.crouch ? 30 : 20, dir, 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 = (435 + 150 * Math.random()) * (mod.isNeutronImmune ? 1.2 : 1)
|
||||
bullet[me].stuckTo = null;
|
||||
bullet[me].stuckToRelativePosition = null;
|
||||
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() {
|
||||
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 -= 0.8 / mod.isBulletsLastLonger //+ 0.5 * Math.sin(game.cycle * 0.1) //slowly shrink max radius
|
||||
|
||||
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.08
|
||||
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();
|
||||
}
|
||||
}
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
fireVacuum() {
|
||||
const me = bullet.length;
|
||||
const dir = mech.angle; // + Math.random() * 0.05;
|
||||
@@ -2561,156 +2684,6 @@ const b = {
|
||||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "neutron bomb",
|
||||
description: "toss a chunk of <strong class='color-p'>Cf-252</strong> which emits <strong class='color-p'>neutrons</strong><br>that do <strong class='color-d'>damage</strong>, <strong class='color-harm'>harm</strong>, and <strong class='color-f'>energy</strong> drain",
|
||||
ammo: 0,
|
||||
ammoPack: 5,
|
||||
have: false,
|
||||
fire() {
|
||||
const me = bullet.length;
|
||||
const dir = mech.angle;
|
||||
bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 10, 4, b.fireAttributes(dir, false));
|
||||
b.fireProps(mech.crouch ? 45 : 25, mech.crouch ? 30 : 20, dir, 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 = (435 + 150 * Math.random()) * (mod.isNeutronImmune ? 1.2 : 1)
|
||||
bullet[me].stuckTo = null;
|
||||
bullet[me].stuckToRelativePosition = null;
|
||||
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.frictionAir = 1;
|
||||
that.do = that.radiationMode;
|
||||
|
||||
if (mod.isNeutronStun) {
|
||||
//push blocks
|
||||
const dist = that.maxDamageRadius * 0.9
|
||||
for (let i = 0, len = body.length; i < len; ++i) {
|
||||
const SUB = Vector.sub(body[i].position, that.position)
|
||||
const DISTANCE = Vector.magnitude(SUB)
|
||||
if (DISTANCE < dist) {
|
||||
const FORCE = Vector.mult(Vector.normalise(SUB), 0.04 * body[i].mass)
|
||||
body[i].force.x += FORCE.x;
|
||||
body[i].force.y += FORCE.y - body[i].mass * game.g * 5; //kick up a bit to give them some arc
|
||||
}
|
||||
}
|
||||
//stun mobs
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (Vector.magnitude(Vector.sub(mob[i].position, that.position)) < dist) {
|
||||
mobs.statusStun(mob[i], mod.isNeutronStun)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mobCollisions = Matter.Query.collides(this, mob)
|
||||
if (mobCollisions.length) {
|
||||
onCollide(this)
|
||||
this.stuckTo = mobCollisions[0].bodyA
|
||||
|
||||
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() {
|
||||
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 -= 0.8 / mod.isBulletsLastLonger //+ 0.5 * Math.sin(game.cycle * 0.1) //slowly shrink max radius
|
||||
|
||||
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.0015
|
||||
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.05
|
||||
if (Matter.Query.ray(map, mob[i].position, this.position).length > 0) dmg *= 0.3 //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();
|
||||
}
|
||||
}
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "mine",
|
||||
description: "toss a <strong>proximity</strong> mine that <strong>sticks</strong> to walls<br>fires <strong>nails</strong> at mobs within range",
|
||||
|
||||
@@ -993,7 +993,6 @@ document.getElementById("updates").addEventListener("toggle", function() {
|
||||
if (i < len - 1) text += "<hr>"
|
||||
}
|
||||
document.getElementById("updates-div").innerHTML = text.replace(/\n/g, "<br />")
|
||||
console.log(text)
|
||||
},
|
||||
function(xhr) {
|
||||
console.error(xhr);
|
||||
|
||||
@@ -12,12 +12,13 @@ const level = {
|
||||
levels: [],
|
||||
start() {
|
||||
if (level.levelsCleared === 0) { //this code only runs on the first level
|
||||
level.difficultyIncrease(8)
|
||||
// level.difficultyIncrease(8)
|
||||
// game.enableConstructMode() //used to build maps in testing mode
|
||||
// game.zoomScale = 1000;
|
||||
// game.setZoom();
|
||||
// mech.setField("wormhole")
|
||||
// b.giveGuns("super balls")
|
||||
// b.giveGuns("missiles")
|
||||
// mod.is3Missiles = true
|
||||
// mod.giveMod("incendiary ammunition")
|
||||
// mod.giveMod("super ball")
|
||||
|
||||
@@ -141,7 +142,7 @@ const level = {
|
||||
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
|
||||
// spawn.boost(1500, 0, 900);
|
||||
|
||||
spawn.starter(1600, -500, 200)
|
||||
spawn.starter(1900, -500, 20)
|
||||
// spawn.bomberBoss(2900, -500)
|
||||
// spawn.launcherBoss(1200, -500)
|
||||
// spawn.laserTargetingBoss(1600, -400)
|
||||
@@ -152,7 +153,7 @@ const level = {
|
||||
// spawn.cellBossCulture(1600, -500)
|
||||
// spawn.spiderBoss(1600, -500)
|
||||
// spawn.sniper(1200, -500)
|
||||
// spawn.shield(mob[mob.length - 1], 1800, -120, 1);
|
||||
spawn.shield(mob[mob.length - 1], 1800, -120, 1);
|
||||
|
||||
// spawn.nodeBoss(1200, -500, "launcher")
|
||||
// spawn.snakeBoss(1200, -500)
|
||||
|
||||
@@ -996,7 +996,7 @@ const mobs = {
|
||||
}
|
||||
},
|
||||
damage(dmg, isBypassShield = false) {
|
||||
if (!this.isShielded || isBypassShield) {
|
||||
if ((!this.isShielded || isBypassShield) && this.alive) {
|
||||
dmg *= mod.damageFromMods()
|
||||
//mobs specific damage changes
|
||||
if (mod.isFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(500, Math.min(3000, this.distanceToPlayer())) - 500) * 0.0067 //up to 50% dmg at max range of 3500
|
||||
|
||||
64
js/mods.js
64
js/mods.js
@@ -408,7 +408,7 @@ const mod = {
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("missiles") || mod.isIncendiary || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.isPulseLaser || mod.isMissileField || mod.boomBotCount > 1 || mod.isFlechetteExplode
|
||||
return mod.haveGunCheck("missiles") || mod.isIncendiary || (mod.haveGunCheck("grenades") && !mod.isNeutronBomb) || mod.haveGunCheck("vacuum bomb") || mod.isPulseLaser || mod.isMissileField || mod.boomBotCount > 1 || mod.isFlechetteExplode
|
||||
},
|
||||
requires: "an explosive damage source",
|
||||
effect: () => {
|
||||
@@ -424,7 +424,7 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("missiles") || mod.isIncendiary || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.isPulseLaser || mod.isMissileField || mod.boomBotCount > 1 || mod.isFlechetteExplode
|
||||
return mod.haveGunCheck("missiles") || mod.isIncendiary || (mod.haveGunCheck("grenades") && !mod.isNeutronBomb) || mod.haveGunCheck("vacuum bomb") || mod.isPulseLaser || mod.isMissileField || mod.boomBotCount > 1 || mod.isFlechetteExplode
|
||||
},
|
||||
requires: "an explosive damage source",
|
||||
effect: () => {
|
||||
@@ -440,7 +440,7 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("missiles") || mod.isIncendiary || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.isPulseLaser || mod.isMissileField || mod.isFlechetteExplode
|
||||
return mod.haveGunCheck("missiles") || mod.isIncendiary || (mod.haveGunCheck("grenades") && !mod.isNeutronBomb) || mod.haveGunCheck("vacuum bomb") || mod.isPulseLaser || mod.isMissileField || mod.isFlechetteExplode
|
||||
},
|
||||
requires: "an explosive damage source",
|
||||
effect: () => {
|
||||
@@ -457,7 +457,7 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("missiles") || mod.isIncendiary || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.isMissileField || mod.isExplodeMob || mod.isFlechetteExplode || mod.isPulseLaser
|
||||
return mod.haveGunCheck("missiles") || mod.isIncendiary || (mod.haveGunCheck("grenades") && !mod.isNeutronBomb) || mod.haveGunCheck("vacuum bomb") || mod.isMissileField || mod.isExplodeMob || mod.isFlechetteExplode || mod.isPulseLaser
|
||||
},
|
||||
requires: "an explosive damage source",
|
||||
effect: () => {
|
||||
@@ -922,7 +922,7 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.isStunField || mod.isPulseStun || mod.isNeutronStun || mod.oneSuperBall || mod.isHarmFreeze || mod.isIceField || mod.isIceCrystals || mod.isSporeFreeze || mod.isAoESlow || mod.isFreezeMobs || mod.isPilotFreeze || mod.haveGunCheck("ice IX") || mod.isCloakStun || mod.orbitBotCount > 1 || mod.isWormholeDamage
|
||||
return mod.isStunField || mod.isPulseStun || mod.oneSuperBall || mod.isHarmFreeze || mod.isIceField || mod.isIceCrystals || mod.isSporeFreeze || mod.isAoESlow || mod.isFreezeMobs || mod.isPilotFreeze || mod.haveGunCheck("ice IX") || mod.isCloakStun || mod.orbitBotCount > 1 || mod.isWormholeDamage
|
||||
},
|
||||
requires: "a freezing or stunning effect",
|
||||
effect() {
|
||||
@@ -1580,7 +1580,7 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("drones") || mod.haveGunCheck("super balls") || (mod.haveGunCheck("nail gun") && !mod.isIceCrystals && !mod.isNailCrit) || (mod.haveGunCheck("shotgun") && !mod.isNailShot)
|
||||
return (mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(mod.isSporeField || mod.isMissileField || mod.isIceField)) || mod.haveGunCheck("drones") || mod.haveGunCheck("super balls") || (mod.haveGunCheck("nail gun") && !mod.isIceCrystals && !mod.isNailCrit) || (mod.haveGunCheck("shotgun") && !mod.isNailShot)
|
||||
},
|
||||
requires: "drones, super balls, nail gun, shotgun",
|
||||
effect() {
|
||||
@@ -1907,7 +1907,7 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("flechettes") || mod.isNailPoison || mod.isHeavyWater || mod.isWormholeDamage
|
||||
return mod.haveGunCheck("flechettes") || mod.isNailPoison || mod.isHeavyWater || mod.isWormholeDamage || mod.isNeutronBomb
|
||||
},
|
||||
requires: "radiation damage source",
|
||||
effect() {
|
||||
@@ -2021,9 +2021,9 @@ const mod = {
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("grenades")
|
||||
return mod.haveGunCheck("grenades") && !mod.isNeutronBomb
|
||||
},
|
||||
requires: "grenades",
|
||||
requires: "grenades, not neutron bomb",
|
||||
effect() {
|
||||
mod.grenadeFragments += 5
|
||||
},
|
||||
@@ -2037,7 +2037,7 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("grenades") && !mod.isVacuumBomb
|
||||
return mod.haveGunCheck("grenades") && !mod.isVacuumBomb && !mod.isNeutronBomb
|
||||
},
|
||||
requires: "grenades, not vacuum bomb",
|
||||
effect() {
|
||||
@@ -2053,9 +2053,9 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("grenades") && !mod.isRPG
|
||||
return mod.haveGunCheck("grenades") && !mod.isRPG && !mod.isNeutronBomb
|
||||
},
|
||||
requires: "grenades, not rocket-propelled",
|
||||
requires: "grenades, not rocket-propelled or neutron bomb",
|
||||
effect() {
|
||||
mod.isVacuumBomb = true;
|
||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||
@@ -2069,13 +2069,35 @@ const mod = {
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "neutron bomb",
|
||||
description: "<strong>grenades</strong> are irradiated with <strong class='color-p'>Cf-252</strong><br>does <strong class='color-d'>damage</strong>, <strong class='color-harm'>harm</strong>, and drains <strong class='color-f'>energy</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("grenades") && !mod.isRPG && !mod.isVacuumBomb && !mod.grenadeFragments
|
||||
},
|
||||
requires: "grenades, not rocket-propelled, vacuum bomb, 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
|
||||
}
|
||||
},
|
||||
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 = b.guns[i].fireNormal
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "water shielding",
|
||||
description: "increase <strong>neutron bomb's</strong> range by <strong>20%</strong><br>player is <strong>immune</strong> to its harmful effects",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("neutron bomb")
|
||||
return mod.isNeutronBomb
|
||||
},
|
||||
requires: "neutron bomb",
|
||||
effect() {
|
||||
@@ -2085,22 +2107,6 @@ const mod = {
|
||||
mod.isNeutronImmune = false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "inertial confinement",
|
||||
description: "<strong>neutron bomb's</strong> detonation <br><strong>stuns</strong> nearby mobs for <strong>1.5</strong> seconds",
|
||||
maxCount: 3,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("neutron bomb")
|
||||
},
|
||||
requires: "neutron bomb",
|
||||
effect() {
|
||||
mod.isNeutronStun += 90;
|
||||
},
|
||||
remove() {
|
||||
mod.isNeutronStun = 0;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "mine reclamation",
|
||||
description: "retrieve <strong class='color-g'>ammo</strong> from all undetonated <strong>mines</strong><br>and <strong>20%</strong> of <strong>mines</strong> after detonation",
|
||||
|
||||
12
js/player.js
12
js/player.js
@@ -1342,21 +1342,15 @@ const mech = {
|
||||
if (mech.energy > mech.maxEnergy - 0.02 && mech.fieldCDcycle < mech.cycle) {
|
||||
if (mod.isSporeField) {
|
||||
// mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones
|
||||
const len = Math.floor(6 + 4 * Math.random())
|
||||
const len = Math.floor(6 + 5 * Math.random())
|
||||
mech.energy -= len * 0.09;
|
||||
for (let i = 0; i < len; i++) {
|
||||
b.spore(mech.pos)
|
||||
}
|
||||
} else if (mod.isMissileField) {
|
||||
// mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones
|
||||
mech.energy -= 0.5;
|
||||
b.missile({
|
||||
x: mech.pos.x + 40 * Math.cos(mech.angle),
|
||||
y: mech.pos.y + 40 * Math.sin(mech.angle) - 3
|
||||
},
|
||||
mech.angle + (0.5 - Math.random()) * (mech.crouch ? 0 : 0.2),
|
||||
-3 * (0.5 - Math.random()) + (mech.crouch ? 25 : -8) * b.fireCD,
|
||||
1, mod.recursiveMissiles)
|
||||
mech.energy -= 0.45;
|
||||
b.missile({ x: mech.pos.x, y: mech.pos.y - 40 }, -Math.PI / 2, 0, 1, mod.recursiveMissiles)
|
||||
} else if (mod.isIceField) {
|
||||
// mech.fieldCDcycle = mech.cycle + 17; // set cool down to prevent +energy from making huge numbers of drones
|
||||
mech.energy -= 0.04;
|
||||
|
||||
@@ -405,7 +405,7 @@ const powerUps = {
|
||||
|
||||
// console.log(powerUps.gun.choiceLog)
|
||||
// console.log(choice1, choice2, choice3)
|
||||
if (mod.isOneGun) text += `<div style = "color: #f00">replaces your current gun</div>`
|
||||
if (mod.isOneGun) text += `<div style = "color: #f24">replaces your current gun</div>`
|
||||
document.getElementById("choose-grid").innerHTML = text
|
||||
powerUps.showDraft();
|
||||
} else {
|
||||
|
||||
79
todo.txt
79
todo.txt
@@ -1,12 +1,9 @@
|
||||
*********** NEXT PATCH ***********
|
||||
mod - neutron bomb is a grenade mod, it's damage is 33% higher
|
||||
direct hits also apply radiation damage over time
|
||||
|
||||
bug fix- spider boss moves at full speed again (watch out)
|
||||
bots that uses energy, stop when you hit 50% energy if you have mass-energy mod
|
||||
you get a warning before you overwrite your current gun due to integrated armament
|
||||
|
||||
gun - flak is removed
|
||||
mod: incendiary ammunition - bullets explode
|
||||
shotgun, nail gun, drones, super balls
|
||||
missiles aim better, accelerate quicker, push blocks out of the way better
|
||||
crouch fire mode rapidly launches missiles vertically
|
||||
|
||||
************** BUGS **************
|
||||
|
||||
@@ -29,24 +26,33 @@ mod: incendiary ammunition - bullets explode
|
||||
|
||||
************** TODO **************
|
||||
|
||||
rework missiles - move faster
|
||||
target more accurately
|
||||
don't get stuck thrusting into a wall
|
||||
less delay right after firing
|
||||
mods
|
||||
|
||||
recursive is kinda dumb
|
||||
|
||||
rework super balls - start with more damage, ramp slower from mods
|
||||
+1 ball per shot from mods
|
||||
small scale size increased
|
||||
or incendiary and no size increase
|
||||
new power up - increase damage and fire speed, for 15 seconds
|
||||
named boost?
|
||||
enabled by a mod?
|
||||
power up color: ?
|
||||
how to indicate effect duration
|
||||
or just give the effect after picking up a reroll
|
||||
|
||||
mod - make neutron bomb a grenade mod
|
||||
mod - overfilled energy decays slower
|
||||
|
||||
mod - remove max health, but you take 60% more harm
|
||||
|
||||
mod - taking damage fires your current weapon at the nearest mob
|
||||
requires? some harm reduction
|
||||
|
||||
mod - a 4th mod selection option that is always a bot
|
||||
|
||||
mod - railgun's push effect is increased, and it does some damage to nearby mobs
|
||||
maybe only triggers at max energy
|
||||
|
||||
mod - neutron bomb needs a method to "catch" mobs in it's field
|
||||
apply stun status effect
|
||||
too similar to the stun effect?
|
||||
|
||||
mod - a 4th mod selection option that is always a gun or field
|
||||
|
||||
mod - nano scale field could be a mod
|
||||
excess energy is converted to bullets
|
||||
run this code in the energy overfill code check
|
||||
@@ -56,9 +62,7 @@ mod - nano scale field could be a mod
|
||||
cloaking field - maybe just don't spawn bullets when cloaked
|
||||
|
||||
Mod: "Solar Power": Energy regeneration is doubled while standing still
|
||||
|
||||
mod - self destruct - drones explode when they die
|
||||
drones lose extra time on collisions, so they often explode after a collision
|
||||
run in the 1 second check
|
||||
|
||||
mod - a bot that eats up health and ammo, but poops out a mod (10 power ups = 1 mod?)
|
||||
or it poops a reroll after picking up 2 heal/ammo
|
||||
@@ -69,21 +73,14 @@ mod - a bot that eats up health and ammo, but poops out a mod (10 power ups = 1
|
||||
moves slower then the player so you can get to it before the bot if you hurry
|
||||
disable crystalized armor?
|
||||
|
||||
mod - rerolls give at least 1 mod that applies your field and gun if possible
|
||||
give fields and guns a tag
|
||||
also spawn a few rerolls for balance?
|
||||
|
||||
mod: take less harm if you are in the air
|
||||
require squirrel cage rotor
|
||||
|
||||
mod - explosions apply radiation damage over time
|
||||
or spawn a neutron bomb with a short timer
|
||||
Laser mod: For each reflection of laser, damage increases by 10%
|
||||
|
||||
mod - remove a random mod as a condition for picking up a really good mod
|
||||
mechanic - remove a random mod as a condition for picking up a really good mod
|
||||
|
||||
mod - double the player's time rate (like you do with the time dilation mod)
|
||||
|
||||
mod - do something for 2 seconds after firing
|
||||
mechanic - do something for 2 seconds after firing
|
||||
if (mech.fireCDcycle + 120)
|
||||
|
||||
mod - do 50% more damage in close, but 50% less at a distance
|
||||
@@ -111,16 +108,10 @@ field - one block orbits you, it can protect you a bit and do collision damage
|
||||
wormholes need to give feedback on where a portal can go
|
||||
or automatically put portals in safe places
|
||||
|
||||
find a way to automatically show patch information from github on n-gon main page
|
||||
|
||||
repeat map in vertical and horizontal space
|
||||
or at least vertical space
|
||||
camera looks strange when you teleport player with a high velocity
|
||||
|
||||
sucker mobs do something when they touch blocks
|
||||
heal
|
||||
remove the blocks from the map
|
||||
|
||||
add an ending to the game
|
||||
maybe the game ending should ask you to open the console and type in some commands like in the end of doki doki
|
||||
mirror ending (if no cheats)
|
||||
@@ -152,21 +143,9 @@ look for mods that could update description text with count and mod.is informat
|
||||
|
||||
mouse event e.which is deprecated
|
||||
|
||||
add a flag to some bullets to indicate that mobs can't learn the player position from bullet damage in bullet-mob collisions
|
||||
if isNotRevealPlayerLocation flag is true have the mob still know player location if nearby player
|
||||
on hide if bullet age is above 4 seconds?
|
||||
spores
|
||||
mines
|
||||
conditions to reveal player from damage?
|
||||
1. bullet spawned from player
|
||||
2. bullet is less than 4 seconds old
|
||||
3. damage is nearby player or in line of sight of player
|
||||
|
||||
add some more computer / AI stuff to the level lore text
|
||||
|
||||
general idea: shrink mech.baseHealth in a mod or field
|
||||
|
||||
change player color based on harm reduction
|
||||
mechanic - shrink mech.baseHealth in a mod or field
|
||||
|
||||
standing wave harmonics mod - push things away
|
||||
push scales with mass up to about 4
|
||||
|
||||
Reference in New Issue
Block a user