RPG and MIRV mods + bug fixes
This commit is contained in:
184
js/bullets.js
184
js/bullets.js
@@ -80,6 +80,9 @@ const b = {
|
||||
isModEnergyHealth: null,
|
||||
isModPulseStun: null,
|
||||
isModPilotFreeze: null,
|
||||
isModRest: null,
|
||||
isModRPG: null,
|
||||
isMod3Missiles: null,
|
||||
modOnHealthChange() { //used with acid mod
|
||||
if (b.isModAcidDmg && mech.health > 0.8) {
|
||||
b.modAcidDmg = 0.5
|
||||
@@ -96,13 +99,13 @@ const b = {
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
if (b.isModLowHealthDmg) {
|
||||
if (!build.isCustomSelection) {
|
||||
setTimeout(function () {
|
||||
if (document.getElementById("mod-low-health-damage")) document.getElementById("mod-low-health-damage").innerHTML = " +" + (((3 / (2 + Math.min(mech.health, 1))) - 1) * 100).toFixed(0) + "%"
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
// if (b.isModLowHealthDmg) {
|
||||
// if (!build.isCustomSelection) {
|
||||
// setTimeout(function () {
|
||||
// if (document.getElementById("mod-low-health-damage")) document.getElementById("mod-low-health-damage").innerHTML = " +" + (((3 / (2 + Math.min(mech.health, 1))) - 1) * 100).toFixed(0) + "%"
|
||||
// }, 10);
|
||||
// }
|
||||
// }
|
||||
},
|
||||
resetModText() {
|
||||
setTimeout(function () {
|
||||
@@ -112,7 +115,7 @@ const b = {
|
||||
},
|
||||
mods: [{
|
||||
name: "capacitor",
|
||||
nameInfo: "<span id='mod-capacitor'></span>",
|
||||
// nameInfo: "<span id='mod-capacitor'></span>",
|
||||
description: "increase <strong class='color-d'>damage</strong> based on stored <strong class='color-f'>energy</strong><br><strong>+1%</strong> <strong class='color-d'>damage</strong> for every <strong>5%</strong> <strong class='color-f'>energy</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -127,6 +130,23 @@ const b = {
|
||||
b.isModEnergyDamage = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "rest frame",
|
||||
// nameInfo: "<span id='mod-rest'></span>",
|
||||
description: "increase <strong class='color-d'>damage</strong> by <strong>20%</strong> when at rest",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
effect: () => {
|
||||
b.isModRest = true // used in mech.grabPowerUp
|
||||
},
|
||||
remove() {
|
||||
b.isModRest = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "kinetic bombardment",
|
||||
description: "do up to <strong>33%</strong> more <strong class='color-d'>damage</strong> at a distance<br><em>increase maxes out at about 40 steps away</em>",
|
||||
@@ -181,7 +201,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
name: "negative feedback",
|
||||
nameInfo: "<span id='mod-low-health-damage'></span>",
|
||||
// nameInfo: "<span id='mod-low-health-damage'></span>",
|
||||
description: "do extra <strong class='color-d'>damage</strong> at low health<br><em>up to <strong>50%</strong> increase when near death</em>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -1057,7 +1077,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
name: "self-replication",
|
||||
description: "when <strong>missiles</strong> <strong class='color-e'>explode</strong><br>they fire <strong>+1</strong> smaller <strong>missiles</strong>",
|
||||
description: "after <strong>missiles</strong> <strong class='color-e'>explode</strong><br>they launch <strong>+1</strong> smaller <strong>missile</strong>",
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -1071,6 +1091,22 @@ const b = {
|
||||
b.modBabyMissiles = 0;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "MIRV",
|
||||
description: "launch <strong>3</strong> small <strong>missiles</strong> instead of 1<br><strong>2x</strong> increase in <strong>delay</strong> after firing",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return b.haveGunCheck("missiles")
|
||||
},
|
||||
requires: "missiles",
|
||||
effect() {
|
||||
b.isMod3Missiles = true;
|
||||
},
|
||||
remove() {
|
||||
b.isMod3Missiles = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "optimized shell packing",
|
||||
description: "<strong>flak</strong> ammo drops contain <strong>3x</strong> more shells",
|
||||
@@ -1107,6 +1143,22 @@ const b = {
|
||||
b.modGrenadeFragments = 0
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "rocket-propelled grenade",
|
||||
description: "<strong>grenades</strong> are rapidly <strong>accelerated</strong> forward<br>map <strong>collisions</strong> trigger an <strong class='color-e'>explosion</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return b.haveGunCheck("grenades")
|
||||
},
|
||||
requires: "grenades",
|
||||
effect() {
|
||||
b.isModRPG = true;
|
||||
},
|
||||
remove() {
|
||||
b.isModRPG = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "electromagnetic pulse",
|
||||
description: "<strong>vacuum bomb's </strong> <strong class='color-e'>explosion</strong> destroys <strong>shields</strong><br>and does <strong>20%</strong> more <strong class='color-d'>damage</strong>",
|
||||
@@ -1467,7 +1519,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
name: "renormalization",
|
||||
description: "<strong>phase decoherence field</strong> has increased <strong>visibility</strong><br>and <strong>3x</strong> less <strong class='color-f'>energy</strong> drain when <strong>firing</strong>",
|
||||
description: "<strong>phase decoherence</strong> has increased <strong>visibility</strong><br>and <strong>3x</strong> less <strong class='color-f'>energy</strong> drain when <strong>firing</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -1613,6 +1665,15 @@ const b = {
|
||||
}
|
||||
}
|
||||
},
|
||||
damageFromMods() {
|
||||
let dmg = 1
|
||||
if (b.isModLowHealthDmg) dmg *= (3 / (2 + Math.min(mech.health, 1))) //up to 50% dmg at zero player health //if this changes all update display in modOnHealthChange()
|
||||
if (b.isModHarmDamage && mech.lastHarmCycle + 300 > mech.cycle) dmg *= 2;
|
||||
if (b.isModEnergyLoss) dmg *= 1.33;
|
||||
if (b.isModRest && player.speed < 1) dmg *= 1.20;
|
||||
if (b.isModEnergyDamage) dmg *= 1 + mech.energy / 5;
|
||||
return dmg
|
||||
},
|
||||
bulletRemove() { //run in main loop
|
||||
//remove bullet if at end cycle for that bullet
|
||||
let i = bullet.length;
|
||||
@@ -1842,12 +1903,12 @@ const b = {
|
||||
bullet[me].onEnd = function () {
|
||||
b.explosion(this.position, this.explodeRad * size); //makes bullet do explosive damage at end
|
||||
for (let i = 0; i < spawn; i++) {
|
||||
b.missile(this.position, 2 * Math.PI * Math.random(), 0, 0.65)
|
||||
b.missile(this.position, 2 * Math.PI * Math.random(), 0, 0.7 * size)
|
||||
}
|
||||
}
|
||||
bullet[me].onDmg = function () {
|
||||
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
|
||||
};
|
||||
bullet[me].lockedOn = null;
|
||||
bullet[me].tryToLockOn = function () {
|
||||
@@ -1874,7 +1935,7 @@ const b = {
|
||||
if (this.lockedOn && Vector.magnitude(Vector.sub(this.position, this.lockedOn.position)) < this.explodeRad) {
|
||||
// console.log('hit')
|
||||
this.endCycle = 0; //bullet ends cycle after doing damage //also triggers explosion
|
||||
this.lockedOn.damage(b.dmgScale * 5 * size); //does extra damage to target
|
||||
this.lockedOn.damage(b.dmgScale * 4 * size); //does extra damage to target
|
||||
}
|
||||
};
|
||||
bullet[me].do = function () {
|
||||
@@ -2875,7 +2936,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
name: "missiles",
|
||||
description: "fire 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,
|
||||
ammoPack: 4,
|
||||
have: false,
|
||||
@@ -2884,15 +2945,51 @@ const b = {
|
||||
fireCycle: 0,
|
||||
ammoLoaded: 0,
|
||||
fire() {
|
||||
mech.fireCDcycle = mech.cycle + Math.floor(mech.crouch ? 50 : 25); // 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.modFireRate,
|
||||
1, b.modBabyMissiles)
|
||||
bullet[bullet.length - 1].force.y += 0.0006; //a small push down at first to make it seem like the missile is briefly falling
|
||||
if (b.isMod3Missiles) {
|
||||
if (mech.crouch) {
|
||||
mech.fireCDcycle = mech.cycle + 80; // 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++) {
|
||||
//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, b.modBabyMissiles)
|
||||
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 + 60; // cool down
|
||||
const direction = {
|
||||
x: Math.cos(mech.angle),
|
||||
y: Math.sin(mech.angle)
|
||||
}
|
||||
const push = Vector.mult(Vector.perp(direction), 0.0008)
|
||||
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, b.modBabyMissiles)
|
||||
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 ? 50 : 30); // 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.modFireRate,
|
||||
1, b.modBabyMissiles)
|
||||
bullet[bullet.length - 1].force.y += 0.0006; //a small push down at first to make it seem like the missile is briefly falling
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2953,11 +3050,7 @@ const b = {
|
||||
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, true));
|
||||
b.fireProps(mech.crouch ? 30 : 20, mech.crouch ? 43 : 32, dir, me); //cd , speed
|
||||
Matter.Body.setDensity(bullet[me], 0.0005);
|
||||
bullet[me].totalCycles = 100;
|
||||
bullet[me].endCycle = game.cycle + Math.floor(mech.crouch ? 120 : 80);
|
||||
bullet[me].restitution = 0.2;
|
||||
bullet[me].explodeRad = 275;
|
||||
bullet[me].onEnd = function () {
|
||||
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
|
||||
@@ -2997,10 +3090,35 @@ const b = {
|
||||
bullet[me].onDmg = function () {
|
||||
this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion
|
||||
};
|
||||
bullet[me].do = function () {
|
||||
//extra gravity for harder arcs
|
||||
this.force.y += this.mass * 0.0025;
|
||||
};
|
||||
|
||||
if (b.isModRPG) {
|
||||
b.fireProps(25, 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.2;
|
||||
bullet[me].explodeRad = 275;
|
||||
bullet[me].do = function () {
|
||||
//extra gravity for harder arcs
|
||||
this.force.y += this.mass * 0.0025;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -3195,7 +3313,7 @@ const b = {
|
||||
name: "drones",
|
||||
description: "deploy drones that <strong>crash</strong> into mobs<br>collisions reduce their <strong>lifespan</strong> by 1 second",
|
||||
ammo: 0,
|
||||
ammoPack: 12,
|
||||
ammoPack: 13,
|
||||
have: false,
|
||||
isStarterGun: true,
|
||||
isEasyToAim: true,
|
||||
|
||||
65
js/engine.js
65
js/engine.js
@@ -87,40 +87,41 @@ function collisionChecks(event) {
|
||||
|
||||
|
||||
//body + player collision
|
||||
// if (game.isBodyDamage) {
|
||||
// if (pairs[i].bodyA === playerBody || pairs[i].bodyA === playerHead) {
|
||||
// collidePlayer(pairs[i].bodyB)
|
||||
// } else if (pairs[i].bodyB === playerBody || pairs[i].bodyB === playerHead) {
|
||||
// collidePlayer(pairs[i].bodyA)
|
||||
// }
|
||||
// }
|
||||
if (game.isBodyDamage) {
|
||||
if (pairs[i].bodyA === playerBody || pairs[i].bodyA === playerHead) {
|
||||
collidePlayer(pairs[i].bodyB)
|
||||
} else if (pairs[i].bodyB === playerBody || pairs[i].bodyB === playerHead) {
|
||||
collidePlayer(pairs[i].bodyA)
|
||||
}
|
||||
}
|
||||
|
||||
// function collidePlayer(obj) {
|
||||
// //player dmg from hitting a body
|
||||
// if (obj.classType === "body" && mech.collisionImmuneCycle < mech.cycle) {
|
||||
// const velocityThreshold = 13
|
||||
// if (player.position.y > obj.position.y) { //block is above the player look at total momentum difference
|
||||
// const velocityDiffMag = Vector.magnitude(Vector.sub(player.velocity, obj.velocity))
|
||||
// if (velocityDiffMag > velocityThreshold) hit(velocityDiffMag - velocityThreshold)
|
||||
// } else { //block is below player only look at horizontal momentum difference
|
||||
// const velocityDiffMagX = Math.abs(obj.velocity.x - player.velocity.x)
|
||||
// if (velocityDiffMagX > velocityThreshold) hit(velocityDiffMagX - velocityThreshold)
|
||||
// }
|
||||
function collidePlayer(obj) {
|
||||
//player dmg from hitting a body
|
||||
// if ( mech.collisionImmuneCycle < mech.cycle) {
|
||||
if (obj.classType === "body" && obj.speed > 10 && mech.collisionImmuneCycle < mech.cycle) {
|
||||
const velocityThreshold = 30 //keep this lines up with player.enterLand numbers (130/5 = 26)
|
||||
if (player.position.y > obj.position.y) { //block is above the player look at total momentum difference
|
||||
const velocityDiffMag = Vector.magnitude(Vector.sub(player.velocity, obj.velocity))
|
||||
if (velocityDiffMag > velocityThreshold) hit(velocityDiffMag - velocityThreshold)
|
||||
} else { //block is below player only look at horizontal momentum difference
|
||||
const velocityDiffMagX = Math.abs(obj.velocity.x - player.velocity.x)
|
||||
if (velocityDiffMagX > velocityThreshold) hit(velocityDiffMagX - velocityThreshold)
|
||||
}
|
||||
|
||||
// function hit(dmg) {
|
||||
// mech.collisionImmuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
|
||||
// dmg = Math.min(Math.max(Math.sqrt(dmg) * obj.mass * 0.01, 0.02), 0.15);
|
||||
// mech.damage(dmg);
|
||||
// game.drawList.push({ //add dmg to draw queue
|
||||
// x: pairs[i].activeContacts[0].vertex.x,
|
||||
// y: pairs[i].activeContacts[0].vertex.y,
|
||||
// radius: dmg * 500,
|
||||
// color: game.mobDmgColor,
|
||||
// time: game.drawTime
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
function hit(dmg) {
|
||||
mech.collisionImmuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
|
||||
dmg = Math.min(Math.max(Math.sqrt(dmg) * obj.mass * 0.01, 0.02), 0.15);
|
||||
mech.damage(dmg);
|
||||
game.drawList.push({ //add dmg to draw queue
|
||||
x: pairs[i].activeContacts[0].vertex.x,
|
||||
y: pairs[i].activeContacts[0].vertex.y,
|
||||
radius: dmg * 500,
|
||||
color: game.mobDmgColor,
|
||||
time: game.drawTime
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// function collidePlayer(obj, speedThreshold = 12, massThreshold = 2) {
|
||||
// //player dmg from hitting a body
|
||||
|
||||
13
js/game.js
13
js/game.js
@@ -711,9 +711,16 @@ const game = {
|
||||
}
|
||||
}
|
||||
|
||||
if (b.isModEnergyDamage) {
|
||||
document.getElementById("mod-capacitor").innerHTML = `(+${(mech.energy/0.05).toFixed(0)}%)`
|
||||
}
|
||||
// if (b.isModEnergyDamage) {
|
||||
// document.getElementById("mod-capacitor").innerHTML = `(+${(mech.energy/0.05).toFixed(0)}%)`
|
||||
// }
|
||||
// if (b.isModRest) {
|
||||
// if (player.speed < 1) {
|
||||
// document.getElementById("mod-rest").innerHTML = `(+20%)`
|
||||
// } else {
|
||||
// document.getElementById("mod-rest").innerHTML = `(+0%)`
|
||||
// }
|
||||
// }
|
||||
|
||||
if (mech.lastKillCycle + 300 > mech.cycle) { //effects active for 5 seconds after killing a mob
|
||||
if (b.isModEnergyRecovery) {
|
||||
|
||||
@@ -83,8 +83,11 @@ const build = {
|
||||
<br>
|
||||
<br>health: ${(mech.health*100).toFixed(0)}% energy: ${(mech.energy*100).toFixed(0)}% mass: ${player.mass.toFixed(1)}
|
||||
<br>position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)}) velocity: (${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)})
|
||||
<br>global damage increase: ${((b.damageFromMods()-1)*100).toFixed(0)}%
|
||||
<br>global harm reduction: ${((1-mech.harmReduction())*100).toFixed(0)}%
|
||||
</div>`;
|
||||
|
||||
|
||||
let countGuns = 0
|
||||
let countMods = 0
|
||||
for (let i = 0, len = b.guns.length; i < len; i++) {
|
||||
|
||||
18
js/level.js
18
js/level.js
@@ -15,12 +15,12 @@ const level = {
|
||||
if (build.isURLBuild && level.levelsCleared === 0) build.onLoadPowerUps();
|
||||
if (level.levelsCleared === 0) { //this code only runs on the first level
|
||||
// level.difficultyIncrease(9)
|
||||
// b.giveGuns("wave beam")
|
||||
// mech.setField("phase decoherence field")
|
||||
// b.giveGuns("missiles")
|
||||
// mech.setField("time dilation field")
|
||||
// b.giveMod("renormalization");
|
||||
// b.giveMod("pocket universe");
|
||||
// b.giveMod("wave packet");
|
||||
// b.giveGuns("laser")
|
||||
// b.giveGuns("grenades")
|
||||
// b.giveMod("rocket-propelled grenade");
|
||||
// mech.setField("pilot wave")
|
||||
|
||||
level.intro(); //starting level
|
||||
@@ -154,7 +154,7 @@ const level = {
|
||||
|
||||
// spawn.bomberBoss(2900, -500)
|
||||
spawn.stabber(1200, -500)
|
||||
spawn.chaser(1200, -500)
|
||||
// spawn.chaser(1200, -500)
|
||||
// spawn.nodeBoss(1200, -500, "spiker")
|
||||
// spawn.hopper(1200, -500)
|
||||
// spawn.timeSkipBoss(2900, -500)
|
||||
@@ -264,7 +264,7 @@ const level = {
|
||||
y: -600,
|
||||
width: 400,
|
||||
height: 500,
|
||||
color: "#cee"
|
||||
color: "#dee"
|
||||
});
|
||||
|
||||
level.fill.push({
|
||||
@@ -272,7 +272,7 @@ const level = {
|
||||
y: -1000,
|
||||
width: 2750,
|
||||
height: 1000,
|
||||
color: "rgba(0,20,40,0.1)"
|
||||
color: "rgba(0,10,30,0.04)"
|
||||
});
|
||||
|
||||
const lineColor = "#ddd"
|
||||
@@ -606,6 +606,7 @@ const level = {
|
||||
level.exit.y = -300;
|
||||
spawn.mapRect(3600, -285, 100, 50); //ground bump wall
|
||||
//mobs that spawn in exit room
|
||||
spawn.bodyRect(4850, -750, 300, 25, 0.6); //
|
||||
spawn.randomSmallMob(4100, -100);
|
||||
spawn.randomSmallMob(4600, -100);
|
||||
spawn.randomMob(3765, -450, 0.3);
|
||||
@@ -629,7 +630,7 @@ const level = {
|
||||
level.exit.x = -550;
|
||||
level.exit.y = -2030;
|
||||
spawn.mapRect(-550, -2015, 100, 50); //ground bump wall
|
||||
spawn.boost(4950, 0, 1600);
|
||||
spawn.boost(4950, 0, 1100);
|
||||
level.fillBG.push({
|
||||
x: -650,
|
||||
y: -2300,
|
||||
@@ -761,7 +762,6 @@ const level = {
|
||||
spawn.mapRect(3450, -1000, 50, 580); //left building wall
|
||||
spawn.bodyRect(3460, -420, 30, 144);
|
||||
spawn.mapRect(5450, -775, 100, 875); //right building wall
|
||||
spawn.bodyRect(4850, -750, 300, 25, 0.8);
|
||||
spawn.bodyRect(3925, -1400, 100, 150, 0.8);
|
||||
spawn.mapRect(3450, -1250, 1090, 50);
|
||||
// spawn.mapRect(3450, -1225, 50, 75);
|
||||
|
||||
@@ -946,13 +946,13 @@ const mobs = {
|
||||
},
|
||||
damage(dmg, isBypassShield = false) {
|
||||
if (!this.isShielded || isBypassShield) {
|
||||
dmg *= b.damageFromMods()
|
||||
//mobs specific damage changes
|
||||
dmg /= Math.sqrt(this.mass)
|
||||
if (this.shield) dmg *= 0.04
|
||||
if (b.isModLowHealthDmg) dmg *= (3 / (2 + Math.min(mech.health, 1))) //up to 50% dmg at zero player health //if this changes all update display in modOnHealthChange()
|
||||
if (b.isModHarmDamage && mech.lastHarmCycle + 300 > mech.cycle) dmg *= 2;
|
||||
if (b.isModEnergyLoss) dmg *= 1.33;
|
||||
if (b.isModEnergyDamage) dmg *= 1 + mech.energy / 5;
|
||||
if (b.isModFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(500, Math.min(3000, this.distanceToPlayer())) - 500) * 0.0067 //up to 50% dmg at max range of 3500
|
||||
|
||||
//energy and heal drain should be calculated after damage boosts
|
||||
if (b.modEnergySiphon && dmg !== Infinity) mech.energy += Math.min(this.health, dmg) * b.modEnergySiphon
|
||||
if (b.modHealthDrain && dmg !== Infinity) mech.addHealth(Math.min(this.health, dmg) * b.modHealthDrain)
|
||||
this.health -= dmg
|
||||
|
||||
75
js/player.js
75
js/player.js
@@ -202,7 +202,7 @@ const mech = {
|
||||
} else {
|
||||
//sets a hard land where player stays in a crouch for a bit and can't jump
|
||||
//crouch is forced in keyMove() on ground section below
|
||||
const momentum = player.velocity.y * player.mass //player mass is 5 so this triggers at 20 down velocity, unless the player is holding something
|
||||
const momentum = player.velocity.y * player.mass //player mass is 5 so this triggers at 26 down velocity, unless the player is holding something
|
||||
if (momentum > 130) {
|
||||
mech.doCrouch();
|
||||
mech.yOff = mech.yOffWhen.jump;
|
||||
@@ -503,6 +503,17 @@ const mech = {
|
||||
},
|
||||
defaultFPSCycle: 0, //tracks when to return to normal fps
|
||||
collisionImmuneCycle: 0, //used in engine
|
||||
harmReduction() {
|
||||
let dmg = 1
|
||||
dmg *= mech.fieldDamageResistance
|
||||
if (b.modEnergyRegen === 0) dmg *= 0.5 //0.22 + 0.78 * mech.energy //77% damage reduction at zero energy
|
||||
if (b.isModEntanglement && b.inventory[0] === b.activeGun) {
|
||||
for (let i = 0, len = b.inventory.length; i < len; i++) {
|
||||
dmg *= 0.84 // 1 - 0.16
|
||||
}
|
||||
}
|
||||
return dmg
|
||||
},
|
||||
damage(dmg) {
|
||||
mech.lastHarmCycle = mech.cycle
|
||||
|
||||
@@ -522,14 +533,8 @@ const mech = {
|
||||
y: 0
|
||||
})
|
||||
}
|
||||
dmg *= mech.harmReduction()
|
||||
|
||||
dmg *= mech.fieldDamageResistance
|
||||
if (b.modEnergyRegen === 0) dmg *= 0.5 //0.22 + 0.78 * mech.energy //77% damage reduction at zero energy
|
||||
if (b.isModEntanglement && b.inventory[0] === b.activeGun) {
|
||||
for (let i = 0, len = b.inventory.length; i < len; i++) {
|
||||
dmg *= 0.84 // 1 - 0.16
|
||||
}
|
||||
}
|
||||
if (b.isModEnergyHealth) {
|
||||
mech.energy -= dmg;
|
||||
if (mech.energy < 0 || isNaN(mech.energy)) {
|
||||
@@ -1820,7 +1825,7 @@ const mech = {
|
||||
|
||||
mech.hold = function () {
|
||||
function drawField(radius) {
|
||||
radius *= 0.7 + 0.6 * mech.energy;
|
||||
radius *= 0.8 + 0.7 * mech.energy;
|
||||
const rotate = mech.cycle * 0.005;
|
||||
mech.fieldPhase += 0.5 - 0.5 * Math.sqrt(Math.max(0.01, Math.min(mech.energy, 1)));
|
||||
const off1 = 1 + 0.06 * Math.sin(mech.fieldPhase);
|
||||
@@ -1858,13 +1863,14 @@ const mech = {
|
||||
mech.lookForPickUp();
|
||||
|
||||
const DRAIN = 0.0004 + 0.0002 * player.speed + ((!b.modRenormalization && mech.fireCDcycle > mech.cycle) ? 0.005 : 0.0017)
|
||||
mech.energy -= DRAIN;
|
||||
if (mech.energy > DRAIN) {
|
||||
mech.energy -= DRAIN;
|
||||
if (mech.energy < 0.001) {
|
||||
mech.fieldCDcycle = mech.cycle + 120;
|
||||
mech.energy = 0;
|
||||
}
|
||||
this.fieldRange = this.fieldRange * 0.9 + 0.1 * 160
|
||||
// if (mech.energy < 0.001) {
|
||||
// mech.fieldCDcycle = mech.cycle + 120;
|
||||
// mech.energy = 0;
|
||||
// mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
|
||||
// }
|
||||
this.fieldRange = this.fieldRange * 0.87 + 0.13 * 160
|
||||
drawField(this.fieldRange)
|
||||
|
||||
mech.isStealth = true //isStealth disables most uses of foundPlayer()
|
||||
@@ -1903,32 +1909,33 @@ const mech = {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mech.fieldCDcycle = mech.cycle + 120;
|
||||
mech.energy = 0;
|
||||
mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
|
||||
drawField(this.fieldRange)
|
||||
}
|
||||
} else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
|
||||
mech.pickUp();
|
||||
} else {
|
||||
// this.fieldRange = 3000
|
||||
if (this.fieldRange < 2000 && mech.holdingTarget === null) {
|
||||
this.fieldRange += 20
|
||||
this.fieldRange += 40
|
||||
drawField(this.fieldRange)
|
||||
}
|
||||
mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
|
||||
}
|
||||
// mech.drawFieldMeter()
|
||||
|
||||
if (mech.energy < mech.fieldEnergyMax) {
|
||||
mech.energy += mech.fieldRegen;
|
||||
const xOff = mech.pos.x - mech.radius * mech.fieldEnergyMax
|
||||
const yOff = mech.pos.y - 50
|
||||
|
||||
ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
|
||||
ctx.fillRect(xOff, yOff, 60 * mech.fieldEnergyMax, 10);
|
||||
|
||||
ctx.fillStyle = mech.fieldMeterColor;
|
||||
ctx.fillRect(xOff, yOff, 60 * mech.energy, 10);
|
||||
|
||||
ctx.beginPath()
|
||||
ctx.rect(xOff, yOff, 60 * mech.fieldEnergyMax, 10);
|
||||
// ctx.fill();
|
||||
ctx.strokeStyle = "rgb(0, 0, 0)";
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
@@ -1992,7 +1999,31 @@ const mech = {
|
||||
y: mech.fieldPosition.y * smooth + game.mouseInGame.y * (1 - smooth),
|
||||
}
|
||||
}
|
||||
mech.grabPowerUp();
|
||||
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||
const dxP = mech.fieldPosition.x - powerUp[i].position.x;
|
||||
const dyP = mech.fieldPosition.y - powerUp[i].position.y;
|
||||
const dist2 = dxP * dxP + dyP * dyP;
|
||||
// float towards field if looking at and in range or if very close to player
|
||||
if (dist2 < mech.fieldRadius * mech.fieldRadius && (mech.lookingAt(powerUp[i]) || dist2 < 16000) && !(mech.health === mech.maxHealth && powerUp[i].name === "heal")) {
|
||||
powerUp[i].force.x += 7 * (dxP / dist2) * powerUp[i].mass;
|
||||
powerUp[i].force.y += 7 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * game.g; //negate gravity
|
||||
//extra friction
|
||||
Matter.Body.setVelocity(powerUp[i], {
|
||||
x: powerUp[i].velocity.x * 0.11,
|
||||
y: powerUp[i].velocity.y * 0.11
|
||||
});
|
||||
if (dist2 < 5000 && !game.isChoosing) { //use power up if it is close enough
|
||||
if (b.isModMassEnergy) mech.energy = mech.fieldEnergyMax * 2;
|
||||
powerUp[i].effect();
|
||||
Matter.World.remove(engine.world, powerUp[i]);
|
||||
powerUp.splice(i, 1);
|
||||
mech.fieldRadius += 50
|
||||
break; //because the array order is messed up after splice
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mech.energy > 0.01) {
|
||||
//find mouse velocity
|
||||
const diff = Vector.sub(mech.fieldPosition, mech.lastFieldPosition)
|
||||
|
||||
98
js/spawn.js
98
js/spawn.js
@@ -937,7 +937,7 @@ const spawn = {
|
||||
}
|
||||
},
|
||||
stabber(x, y, radius = 25 + Math.ceil(Math.random() * 15)) {
|
||||
mobs.spawn(x, y, 4, radius, "rgb(220,50,205)"); //can't have sides above 6 or collision events don't work (probably because of a convex problem)
|
||||
mobs.spawn(x, y, 6, radius, "rgb(220,50,205)"); //can't have sides above 6 or collision events don't work (probably because of a convex problem)
|
||||
let me = mob[mob.length - 1];
|
||||
me.accelMag = 0.0006 * game.accelScale;
|
||||
// me.g = 0.0002; //required if using 'gravity'
|
||||
@@ -948,54 +948,64 @@ const spawn = {
|
||||
me.isSpikeReset = true;
|
||||
Matter.Body.rotate(me, Math.PI * 0.1);
|
||||
spawn.shield(me, x, y);
|
||||
me.onDamage = function () {};
|
||||
me.do = function () {
|
||||
// this.gravity();
|
||||
this.seePlayerByLookingAt();
|
||||
this.checkStatus();
|
||||
this.attraction();
|
||||
|
||||
if (this.isSpikeReset) {
|
||||
if (this.seePlayer.recall) {
|
||||
const dist = Vector.sub(this.seePlayer.position, this.position);
|
||||
const distMag = Vector.magnitude(dist);
|
||||
if (distMag < this.radius * 7) {
|
||||
//find nearest vertex
|
||||
let nearestDistance = Infinity
|
||||
for (let i = 0, len = this.vertices.length; i < len; i++) {
|
||||
//find distance to player for each vertex
|
||||
const dist = Vector.sub(this.seePlayer.position, this.vertices[i]);
|
||||
const distMag = Vector.magnitude(dist);
|
||||
//save the closest distance
|
||||
if (distMag < nearestDistance) {
|
||||
this.spikeVertex = i
|
||||
nearestDistance = distMag
|
||||
}
|
||||
}
|
||||
this.spikeLength = 1
|
||||
this.isSpikeGrowing = true;
|
||||
this.isSpikeReset = false;
|
||||
Matter.Body.setAngularVelocity(this, 0)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.isSpikeGrowing) {
|
||||
this.spikeLength += 1
|
||||
if (this.spikeLength > 9) {
|
||||
this.isSpikeGrowing = false;
|
||||
}
|
||||
} else {
|
||||
this.spikeLength -= 0.1
|
||||
if (this.spikeLength < 1) {
|
||||
this.spikeLength = 1
|
||||
this.isSpikeReset = true
|
||||
}
|
||||
}
|
||||
// me.onDamage = function () {};
|
||||
me.onDeath = function () {
|
||||
if (this.spikeLength > 4) {
|
||||
this.spikeLength = 4
|
||||
const spike = Vector.mult(Vector.normalise(Vector.sub(this.vertices[this.spikeVertex], this.position)), this.radius * this.spikeLength)
|
||||
this.vertices[this.spikeVertex].x = this.position.x + spike.x
|
||||
this.vertices[this.spikeVertex].y = this.position.y + spike.y
|
||||
}
|
||||
};
|
||||
me.do = function () {
|
||||
if (!mech.isBodiesAsleep) {
|
||||
// this.gravity();
|
||||
this.seePlayerByLookingAt();
|
||||
this.checkStatus();
|
||||
this.attraction();
|
||||
|
||||
if (this.isSpikeReset) {
|
||||
if (this.seePlayer.recall) {
|
||||
const dist = Vector.sub(this.seePlayer.position, this.position);
|
||||
const distMag = Vector.magnitude(dist);
|
||||
if (distMag < this.radius * 7) {
|
||||
//find nearest vertex
|
||||
let nearestDistance = Infinity
|
||||
for (let i = 0, len = this.vertices.length; i < len; i++) {
|
||||
//find distance to player for each vertex
|
||||
const dist = Vector.sub(this.seePlayer.position, this.vertices[i]);
|
||||
const distMag = Vector.magnitude(dist);
|
||||
//save the closest distance
|
||||
if (distMag < nearestDistance) {
|
||||
this.spikeVertex = i
|
||||
nearestDistance = distMag
|
||||
}
|
||||
}
|
||||
this.spikeLength = 1
|
||||
this.isSpikeGrowing = true;
|
||||
this.isSpikeReset = false;
|
||||
Matter.Body.setAngularVelocity(this, 0)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.isSpikeGrowing) {
|
||||
this.spikeLength += 1
|
||||
if (this.spikeLength > 9) {
|
||||
this.isSpikeGrowing = false;
|
||||
}
|
||||
} else {
|
||||
this.spikeLength -= 0.1
|
||||
if (this.spikeLength < 1) {
|
||||
this.spikeLength = 1
|
||||
this.isSpikeReset = true
|
||||
}
|
||||
}
|
||||
const spike = Vector.mult(Vector.normalise(Vector.sub(this.vertices[this.spikeVertex], this.position)), this.radius * this.spikeLength)
|
||||
this.vertices[this.spikeVertex].x = this.position.x + spike.x
|
||||
this.vertices[this.spikeVertex].y = this.position.y + spike.y
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
striker(x, y, radius = 14 + Math.ceil(Math.random() * 25)) {
|
||||
mobs.spawn(x, y, 5, radius, "rgb(221,102,119)");
|
||||
|
||||
62
todo.txt
62
todo.txt
@@ -2,6 +2,38 @@
|
||||
|
||||
|
||||
************** TODO - n-gon **************
|
||||
foam - check for touching map / blocks and slow foam down rather then bounce off walls
|
||||
quantum foam should just skip the shield
|
||||
|
||||
red flashes when you take damage were replaced with the color of your energy bar
|
||||
When you have mass energy equivalence
|
||||
|
||||
mod - missiles: fire 3 small missiles
|
||||
disables missile replication mod
|
||||
|
||||
lore - a robot (the player) gains self awareness
|
||||
each mod/gun/field is a new tech
|
||||
all the technology leads to the singularity
|
||||
each game run is actually the mech simulating a possible escape
|
||||
this is why the graphics are so bad, its just a simulation
|
||||
final mod is "this is just a simulation"
|
||||
you get immortality and Infinity damage
|
||||
the next level is the final level
|
||||
when you die with Quantum Immortality there is a chance of lore text
|
||||
|
||||
atmosphere levels: change the pace, give the user a rest between combat
|
||||
low or no combat, but more graphics
|
||||
explore lore
|
||||
find power ups in "wrecked" mechs representing previous simulations
|
||||
how you could leave something in one simulation that effects a different simulation
|
||||
Maybe some strange quantum physics principle.
|
||||
add text for player thoughts?
|
||||
simple puzzles
|
||||
cool looking stuff
|
||||
large rotating fan that the player has to move through
|
||||
nonaggressive mobs
|
||||
in the final level you see your self at the starting level, with the wires
|
||||
you shoot your self to wake up?
|
||||
|
||||
bullets cost 5 life instead of ammo, but return 5 life when they hit a mob
|
||||
replace life with energy or ammo?
|
||||
@@ -37,8 +69,6 @@ boss mob - just a faster and larger version of a springer mob
|
||||
|
||||
mob - time skipper: sends a pulse wave out that will cause time to jump forward 1 second.
|
||||
|
||||
mob stabber - extends one vector like the shooter, but quickly in order to stab
|
||||
|
||||
mob sniper - targeting laser, then a high speed, no gravity bullet
|
||||
|
||||
mod - increase laser bot range, and reduce energy drain
|
||||
@@ -50,35 +80,9 @@ mod - blocks stun mobs
|
||||
|
||||
settings - custom keys binding
|
||||
|
||||
lore - a robot (the player) gains self awareness
|
||||
each mod/gun/field is a new tech
|
||||
all the technology leads to the singularity
|
||||
each game run is actually the mech simulating a possible escape
|
||||
this is why the graphics are so bad, its just a simulation
|
||||
final mod is "this is just a simulation"
|
||||
you get immortality and Infinity damage
|
||||
the next level is the final level
|
||||
when you die with Quantum Immortality there is a chance of lore text
|
||||
|
||||
atmosphere levels: change the pace, give the user a rest between combat
|
||||
low or no combat, but more graphics
|
||||
explore lore
|
||||
find power ups in "wrecked" mechs representing previous simulations
|
||||
how you could leave something in one simulation that effects a different simulation
|
||||
Maybe some strange quantum physics principle.
|
||||
add text for player thoughts?
|
||||
simple puzzles
|
||||
cool looking stuff
|
||||
large rotating fan that the player has to move through
|
||||
nonaggressive mobs
|
||||
in the final level you see your self at the starting level, with the wires
|
||||
you shoot your self to wake up?
|
||||
|
||||
css transition for pause menu
|
||||
|
||||
mod - do extra damage based on your speed
|
||||
do more damage when not moving?
|
||||
take less damage when not moving?
|
||||
mod - do more damage when not moving?
|
||||
|
||||
gun/field: portals
|
||||
use the code from mines to get them to stick to walls
|
||||
|
||||
Reference in New Issue
Block a user