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:
landgreen
2020-11-16 14:10:44 -08:00
parent d1733a9153
commit 7c52af4b90
9 changed files with 244 additions and 291 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
.jsbeautifyrc .jsbeautifyrc
.DS_Store

View File

@@ -290,12 +290,14 @@ const b = {
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
}, },
minDmgSpeed: 10, minDmgSpeed: 10,
lookFrequency: Math.floor(15 + Math.random() * 3), lookFrequency: Math.floor(10 + Math.random() * 3),
explodeRad: 170 + 60 * Math.random(), explodeRad: 180 + 60 * Math.random(),
density: 0.02, //0.001 is normal
beforeDmg() { beforeDmg() {
Matter.Body.setDensity(this, 0.0001); //reduce density to normal
this.tryToLockOn(); this.tryToLockOn();
this.endCycle = 0; //bullet ends cycle after doing damage // also triggers explosion this.endCycle = 0; //bullet ends cycle after doing damage // also triggers explosion
}, //this.endCycle = 0 //triggers despawn },
onEnd() { onEnd() {
b.explosion(this.position, this.explodeRad * size); //makes bullet do explosive damage at end b.explosion(this.position, this.explodeRad * size); //makes bullet do explosive damage at end
if (spawn) { if (spawn) {
@@ -310,15 +312,14 @@ const b = {
lockedOn: null, lockedOn: null,
tryToLockOn() { tryToLockOn() {
let closeDist = Infinity; 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, 30)) //look for closest target to where the missile will be in 30 cycles
const futurePos = Vector.add(this.position, Vector.mult(this.velocity, 50))
this.lockedOn = null; this.lockedOn = null;
// const futurePos = this.lockedOn ? :Vector.add(this.position, Vector.mult(this.velocity, 50)) // const futurePos = this.lockedOn ? :Vector.add(this.position, Vector.mult(this.velocity, 50))
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
if ( if (
mob[i].alive && mob[i].dropPowerUp && mob[i].alive && mob[i].dropPowerUp &&
Matter.Query.ray(map, 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 // && Matter.Query.ray(body, this.position, mob[i].position).length === 0
) { ) {
const futureDist = Vector.magnitude(Vector.sub(futurePos, mob[i].position)); const futureDist = Vector.magnitude(Vector.sub(futurePos, mob[i].position));
if (futureDist < closeDist) { if (futureDist < closeDist) {
@@ -347,21 +348,20 @@ const b = {
y: Math.sin(this.angle) y: Math.sin(this.angle)
}; };
const target = Vector.normalise(Vector.sub(this.position, this.lockedOn.position)); 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));
if (Vector.cross(target, face) > 0) { const dot = Vector.dot(target, face)
Matter.Body.rotate(this, 0.1); const aim = Math.min(0.08, (1 + dot) * 1)
} else { if (Vector.cross(target, face) > 0) {
Matter.Body.rotate(this, -0.1); Matter.Body.rotate(this, aim);
}
this.frictionAir = 0.06; //extra friction if turning
} else { } 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 //accelerate in direction bullet is facing
const dir = this.angle; // + (Math.random() - 0.5); const dir = this.angle;
this.force.x += Math.cos(dir) * thrust; this.force.x += thrust * Math.cos(dir);
this.force.y += Math.sin(dir) * thrust; this.force.y += thrust * Math.sin(dir);
ctx.beginPath(); //draw rocket ctx.beginPath(); //draw rocket
ctx.arc(this.position.x - Math.cos(this.angle) * (25 * size - 3) + (Math.random() - 0.5) * 4, 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], { Matter.Body.setVelocity(bullet[me], {
x: mech.Vx / 2 + speed * Math.cos(angle), x: mech.Vx / 2 + speed * Math.cos(angle),
y: mech.Vy / 2 + speed * Math.sin(angle) y: mech.Vy / 2 + speed * Math.sin(angle)
@@ -2355,55 +2355,55 @@ const b = {
name: "missiles", name: "missiles",
description: "launch missiles that <strong>accelerate</strong> towards <strong>mobs</strong><br><strong class='color-e'>explodes</strong> when near target", description: "launch missiles that <strong>accelerate</strong> towards <strong>mobs</strong><br><strong class='color-e'>explodes</strong> when near target",
ammo: 0, ammo: 0,
ammoPack: 3, ammoPack: 3.3,
have: false, have: false,
fireCycle: 0, fireCycle: 0,
ammoLoaded: 0, ammoLoaded: 0,
fire() { fire() {
//missile(where, dir, speed, size = 1, spawn = 0) {
if (mod.is3Missiles) { if (mod.is3Missiles) {
if (mech.crouch) { if (mech.crouch) {
mech.fireCDcycle = mech.cycle + 50 * b.fireCD; // cool down mech.fireCDcycle = mech.cycle + 18 * 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)
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
//missile(where, dir, speed, size = 1, spawn = 0) {
b.missile({ b.missile({
x: mech.pos.x + 40 * direction.x, x: mech.pos.x,
y: mech.pos.y + 40 * direction.y y: mech.pos.y - 40
}, mech.angle + 0.06 * (1 - i), 0, 0.7, mod.recursiveMissiles) }, -Math.PI / 2 + 0.08 * (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);
} }
} else { } else {
mech.fireCDcycle = mech.cycle + 35 * b.fireCD; // cool down mech.fireCDcycle = mech.cycle + 55 * b.fireCD; // cool down
const direction = { const direction = {
x: Math.cos(mech.angle), x: Math.cos(mech.angle),
y: Math.sin(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++) { for (let i = 0; i < 3; i++) {
//missile(where, dir, speed, size = 1, spawn = 0) {
b.missile({ b.missile({
x: mech.pos.x + 40 * direction.x, x: mech.pos.x + 40 * direction.x,
y: mech.pos.y + 40 * direction.y 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.x += push.x * (i - 1);
bullet[bullet.length - 1].force.y += push.y * (i - 1); bullet[bullet.length - 1].force.y += push.y * (i - 1);
} }
} }
} else { } else {
mech.fireCDcycle = mech.cycle + Math.floor(mech.crouch ? 40 : 25) * b.fireCD; // cool down if (mech.crouch) {
b.missile({ mech.fireCDcycle = mech.cycle + 18 * b.fireCD; // cool down
x: mech.pos.x + 40 * Math.cos(mech.angle), b.missile({
y: mech.pos.y + 40 * Math.sin(mech.angle) - 3 x: mech.pos.x,
}, y: mech.pos.y - 40
mech.angle + (0.5 - Math.random()) * (mech.crouch ? 0 : 0.2), },
-3 * (0.5 - Math.random()) + (mech.crouch ? 25 : -8) * b.fireCD, -Math.PI / 2, 0, 1, mod.recursiveMissiles)
1, mod.recursiveMissiles) } else {
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.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), 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() { fireNormal() {
const me = bullet.length; const me = bullet.length;
const dir = mech.angle; // + Math.random() * 0.05; 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); Matter.Body.setDensity(bullet[me], 0.0005);
bullet[me].explodeRad = 275; bullet[me].explodeRad = 275;
bullet[me].onEnd = function() { 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() { fireVacuum() {
const me = bullet.length; const me = bullet.length;
const dir = mech.angle; // + Math.random() * 0.05; 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", name: "mine",
description: "toss a <strong>proximity</strong> mine that <strong>sticks</strong> to walls<br>fires <strong>nails</strong> at mobs within range", description: "toss a <strong>proximity</strong> mine that <strong>sticks</strong> to walls<br>fires <strong>nails</strong> at mobs within range",

View File

@@ -993,7 +993,6 @@ document.getElementById("updates").addEventListener("toggle", function() {
if (i < len - 1) text += "<hr>" if (i < len - 1) text += "<hr>"
} }
document.getElementById("updates-div").innerHTML = text.replace(/\n/g, "<br />") document.getElementById("updates-div").innerHTML = text.replace(/\n/g, "<br />")
console.log(text)
}, },
function(xhr) { function(xhr) {
console.error(xhr); console.error(xhr);

View File

@@ -12,12 +12,13 @@ const level = {
levels: [], levels: [],
start() { start() {
if (level.levelsCleared === 0) { //this code only runs on the first level 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.enableConstructMode() //used to build maps in testing mode
// game.zoomScale = 1000; // game.zoomScale = 1000;
// game.setZoom(); // game.setZoom();
// mech.setField("wormhole") // mech.setField("wormhole")
// b.giveGuns("super balls") // b.giveGuns("missiles")
// mod.is3Missiles = true
// mod.giveMod("incendiary ammunition") // mod.giveMod("incendiary ammunition")
// mod.giveMod("super ball") // mod.giveMod("super ball")
@@ -141,7 +142,7 @@ const level = {
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
// spawn.boost(1500, 0, 900); // spawn.boost(1500, 0, 900);
spawn.starter(1600, -500, 200) spawn.starter(1900, -500, 20)
// spawn.bomberBoss(2900, -500) // spawn.bomberBoss(2900, -500)
// spawn.launcherBoss(1200, -500) // spawn.launcherBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400) // spawn.laserTargetingBoss(1600, -400)
@@ -152,7 +153,7 @@ const level = {
// spawn.cellBossCulture(1600, -500) // spawn.cellBossCulture(1600, -500)
// spawn.spiderBoss(1600, -500) // spawn.spiderBoss(1600, -500)
// spawn.sniper(1200, -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.nodeBoss(1200, -500, "launcher")
// spawn.snakeBoss(1200, -500) // spawn.snakeBoss(1200, -500)

View File

@@ -996,7 +996,7 @@ const mobs = {
} }
}, },
damage(dmg, isBypassShield = false) { damage(dmg, isBypassShield = false) {
if (!this.isShielded || isBypassShield) { if ((!this.isShielded || isBypassShield) && this.alive) {
dmg *= mod.damageFromMods() dmg *= mod.damageFromMods()
//mobs specific damage changes //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 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

View File

@@ -408,7 +408,7 @@ const mod = {
maxCount: 9, maxCount: 9,
count: 0, count: 0,
allowed() { 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", requires: "an explosive damage source",
effect: () => { effect: () => {
@@ -424,7 +424,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { 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", requires: "an explosive damage source",
effect: () => { effect: () => {
@@ -440,7 +440,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { 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", requires: "an explosive damage source",
effect: () => { effect: () => {
@@ -457,7 +457,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { 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", requires: "an explosive damage source",
effect: () => { effect: () => {
@@ -922,7 +922,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { 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", requires: "a freezing or stunning effect",
effect() { effect() {
@@ -1580,7 +1580,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { 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", requires: "drones, super balls, nail gun, shotgun",
effect() { effect() {
@@ -1907,7 +1907,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { 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", requires: "radiation damage source",
effect() { effect() {
@@ -2021,9 +2021,9 @@ const mod = {
maxCount: 9, maxCount: 9,
count: 0, count: 0,
allowed() { allowed() {
return mod.haveGunCheck("grenades") return mod.haveGunCheck("grenades") && !mod.isNeutronBomb
}, },
requires: "grenades", requires: "grenades, not neutron bomb",
effect() { effect() {
mod.grenadeFragments += 5 mod.grenadeFragments += 5
}, },
@@ -2037,7 +2037,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return mod.haveGunCheck("grenades") && !mod.isVacuumBomb return mod.haveGunCheck("grenades") && !mod.isVacuumBomb && !mod.isNeutronBomb
}, },
requires: "grenades, not vacuum bomb", requires: "grenades, not vacuum bomb",
effect() { effect() {
@@ -2053,9 +2053,9 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { 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() { effect() {
mod.isVacuumBomb = true; mod.isVacuumBomb = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun 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", 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", description: "increase <strong>neutron bomb's</strong> range by <strong>20%</strong><br>player is <strong>immune</strong> to its harmful effects",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return mod.haveGunCheck("neutron bomb") return mod.isNeutronBomb
}, },
requires: "neutron bomb", requires: "neutron bomb",
effect() { effect() {
@@ -2085,22 +2107,6 @@ const mod = {
mod.isNeutronImmune = false 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", 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", 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",

View File

@@ -1342,21 +1342,15 @@ const mech = {
if (mech.energy > mech.maxEnergy - 0.02 && mech.fieldCDcycle < mech.cycle) { if (mech.energy > mech.maxEnergy - 0.02 && mech.fieldCDcycle < mech.cycle) {
if (mod.isSporeField) { if (mod.isSporeField) {
// mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones // 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; mech.energy -= len * 0.09;
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
b.spore(mech.pos) b.spore(mech.pos)
} }
} else if (mod.isMissileField) { } else if (mod.isMissileField) {
// mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones // mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones
mech.energy -= 0.5; mech.energy -= 0.45;
b.missile({ b.missile({ x: mech.pos.x, y: mech.pos.y - 40 }, -Math.PI / 2, 0, 1, mod.recursiveMissiles)
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)
} else if (mod.isIceField) { } else if (mod.isIceField) {
// mech.fieldCDcycle = mech.cycle + 17; // set cool down to prevent +energy from making huge numbers of drones // mech.fieldCDcycle = mech.cycle + 17; // set cool down to prevent +energy from making huge numbers of drones
mech.energy -= 0.04; mech.energy -= 0.04;

View File

@@ -405,7 +405,7 @@ const powerUps = {
// console.log(powerUps.gun.choiceLog) // console.log(powerUps.gun.choiceLog)
// console.log(choice1, choice2, choice3) // 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 document.getElementById("choose-grid").innerHTML = text
powerUps.showDraft(); powerUps.showDraft();
} else { } else {

View File

@@ -1,12 +1,9 @@
*********** NEXT PATCH *********** *********** 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) missiles aim better, accelerate quicker, push blocks out of the way better
bots that uses energy, stop when you hit 50% energy if you have mass-energy mod crouch fire mode rapidly launches missiles vertically
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
************** BUGS ************** ************** BUGS **************
@@ -29,24 +26,33 @@ mod: incendiary ammunition - bullets explode
************** TODO ************** ************** 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 new power up - increase damage and fire speed, for 15 seconds
+1 ball per shot from mods named boost?
small scale size increased enabled by a mod?
or incendiary and no size increase 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 mod - railgun's push effect is increased, and it does some damage to nearby mobs
maybe only triggers at max energy 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 mod - nano scale field could be a mod
excess energy is converted to bullets excess energy is converted to bullets
run this code in the energy overfill code check 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 cloaking field - maybe just don't spawn bullets when cloaked
Mod: "Solar Power": Energy regeneration is doubled while standing still Mod: "Solar Power": Energy regeneration is doubled while standing still
run in the 1 second check
mod - self destruct - drones explode when they die
drones lose extra time on collisions, so they often explode after a collision
mod - a bot that eats up health and ammo, but poops out a mod (10 power ups = 1 mod?) 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 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 moves slower then the player so you can get to it before the bot if you hurry
disable crystalized armor? 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 mod: take less harm if you are in the air
require squirrel cage rotor require squirrel cage rotor
mod - explosions apply radiation damage over time Laser mod: For each reflection of laser, damage increases by 10%
or spawn a neutron bomb with a short timer
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) mechanic - do something for 2 seconds after firing
mod - do something for 2 seconds after firing
if (mech.fireCDcycle + 120) if (mech.fireCDcycle + 120)
mod - do 50% more damage in close, but 50% less at a distance 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 wormholes need to give feedback on where a portal can go
or automatically put portals in safe places 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 repeat map in vertical and horizontal space
or at least vertical space or at least vertical space
camera looks strange when you teleport player with a high velocity 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 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 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) 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 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 add some more computer / AI stuff to the level lore text
general idea: shrink mech.baseHealth in a mod or field mechanic - shrink mech.baseHealth in a mod or field
change player color based on harm reduction
standing wave harmonics mod - push things away standing wave harmonics mod - push things away
push scales with mass up to about 4 push scales with mass up to about 4