diff --git a/js/bullets.js b/js/bullets.js
index 73ca1b0..7ae9c60 100644
--- a/js/bullets.js
+++ b/js/bullets.js
@@ -37,7 +37,6 @@ const b = {
isModPiezo: null,
isModDroneCollide: null,
isModFastSpores: null,
- isModStomp: null,
modSuperBallNumber: null,
modOneSuperBall: null,
modLaserReflections: null,
@@ -79,6 +78,7 @@ const b = {
isModSporeFollow: null,
isModNailPoison: null,
isModEnergyHealth: null,
+ isModPulseStun: null,
modOnHealthChange() { //used with acid mod
if (b.isModAcidDmg && mech.health > 0.8) {
b.modAcidDmg = 0.5
@@ -144,13 +144,13 @@ const b = {
},
{
name: "fracture analysis",
- description: "5x physical damage to unaware mobs
unaware mobs don't have a health bar",
+ description: "bullets do 5x damage to unaware mobs
unaware mobs don't have a health bar",
maxCount: 1,
count: 0,
allowed() {
- return b.isModFarAwayDmg
+ return true
},
- requires: "kinetic bombardment",
+ requires: "",
effect() {
b.isModCrit = true;
},
@@ -201,9 +201,9 @@ const b = {
maxCount: 1,
count: 0,
allowed() {
- return b.isModLowHealthDmg
+ return true
},
- requires: "negative feedback",
+ requires: "",
effect() {
b.isModHarmDamage = true;
},
@@ -261,7 +261,7 @@ const b = {
},
{
name: "mass driver",
- description: "blocks do 3x more damage to mobs
charge throws in 3x less time",
+ description: "blocks do 2x more damage to mobs
charge throws more quickly for less energy",
maxCount: 1,
count: 0,
allowed() {
@@ -269,7 +269,7 @@ const b = {
},
requires: "",
effect() {
- b.modThrowChargeRate = 3
+ b.modThrowChargeRate = 2
},
remove() {
b.modThrowChargeRate = 1
@@ -402,6 +402,22 @@ const b = {
b.modMobDieAtHealth = 0.05;
}
},
+ {
+ name: "scrap recycling",
+ description: "heal up to 1% of max health every second
active for 5 seconds after a mob dies",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return true
+ },
+ requires: "",
+ effect() {
+ b.isModHealthRecovery = true;
+ },
+ remove() {
+ b.isModHealthRecovery = false;
+ }
+ },
{
name: "waste energy recovery",
description: "regen 7% of max energy every second
active for 5 seconds after a mob dies",
@@ -418,31 +434,15 @@ const b = {
b.isModEnergyRecovery = false;
}
},
- {
- name: "scrap recycling",
- description: "heal up to 1% of max health every second
active for 5 seconds after a mob dies",
- maxCount: 1,
- count: 0,
- allowed() {
- return b.isModEnergyRecovery
- },
- requires: "waste energy recovery",
- effect() {
- b.isModHealthRecovery = true;
- },
- remove() {
- b.isModHealthRecovery = false;
- }
- },
{
name: "acute stress response",
description: "increase damage by 33%
but, after a mob dies lose 1/2 your energy",
maxCount: 1,
count: 0,
allowed() {
- return b.isModEnergyRecovery
+ return true
},
- requires: "waste energy recovery",
+ requires: "",
effect() {
b.isModEnergyLoss = true;
},
@@ -470,22 +470,6 @@ const b = {
mech.jumpForce = 0.42; //was 0.38 at 0.0019 gravity
}
},
- {
- name: "basidio-stomp",
- description: "hard landings disrupt spores in the ground
immune to harm from falling",
- maxCount: 1,
- count: 0,
- allowed() {
- return b.modSquirrelFx > 1
- },
- requires: "squirrel-cage rotor",
- effect() {
- b.isModStomp = true
- },
- remove() {
- b.isModStomp = false;
- }
- },
{
name: "Pauli exclusion",
description: `unable to collide with mobs for +2 seconds
activates after being harmed from a collision`,
@@ -525,9 +509,9 @@ const b = {
maxCount: 1,
count: 0,
allowed() {
- return b.isModImmortal
+ return true
},
- requires: "quantum immortality",
+ requires: "",
effect() {
b.isModDeathAvoid = true;
b.isModDeathAvoidOnCD = false;
@@ -560,7 +544,7 @@ const b = {
},
{
name: "mass-energy equivalence",
- description: "your energy replaces your health
you can't die if your energy is above zero",
+ description: "you can't die if your energy is above zero
your health is permanently set to zero",
maxCount: 1,
count: 0,
allowed() {
@@ -1175,7 +1159,7 @@ const b = {
maxCount: 1,
count: 0,
allowed() {
- return b.haveGunCheck("spores") || b.modSporesOnDeath > 0 || b.isModStomp || b.isModSporeField
+ return b.haveGunCheck("spores") || b.modSporesOnDeath > 0 || b.isModSporeField
},
requires: "spores",
effect() {
@@ -1191,7 +1175,7 @@ const b = {
maxCount: 1,
count: 0,
allowed() {
- return b.haveGunCheck("spores") || b.modSporesOnDeath > 0 || b.isModStomp || b.isModSporeField
+ return b.haveGunCheck("spores") || b.modSporesOnDeath > 0 || b.isModSporeField
},
requires: "spores",
effect() {
@@ -1301,6 +1285,22 @@ const b = {
b.modLaserFieldDrain = 0.002;
}
},
+ {
+ name: "shock wave",
+ description: "mobs caught in pulse's explosion are stunned",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return b.haveGunCheck("pulse")
+ },
+ requires: "pulse",
+ effect() {
+ b.isModPulseStun = true;
+ },
+ remove() {
+ b.isModPulseStun = false;
+ }
+ },
{
name: "flux pinning",
description: "blocking with perfect diamagnetism
stuns mobs for +1 second",
@@ -1568,14 +1568,21 @@ const b = {
game.updateGunHUD();
}
} else {
- if (b.isModAmmoFromHealth && mech.health > 0.05) {
- mech.damage(Math.max(0.01, b.isModAmmoFromHealth * mech.health));
- powerUps.spawn(mech.pos.x, mech.pos.y, "ammo");
- if (Math.random() < b.isModBayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "ammo");
+ if (b.isModAmmoFromHealth) {
+ if (mech.health > 0.05) {
+ mech.damage(Math.max(0.01, b.isModAmmoFromHealth * mech.health));
+ powerUps.spawn(mech.pos.x, mech.pos.y, "ammo");
+ if (Math.random() < b.isModBayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "ammo");
+ } else {
+ game.replaceTextLog = true;
+ game.makeTextLog("not enough health for catabolism to produce ammo", 120);
+ }
+
+ } else {
+ game.replaceTextLog = true;
+ game.makeTextLog("
NO AMMO
Q, E, and mouse wheel change weapons
", 200);
}
- mech.fireCDcycle = mech.cycle + 30; //fire cooldown
- game.replaceTextLog = true;
- game.makeTextLog("NO AMMO
Q, E, and mouse wheel change weapons
", 200);
+ mech.fireCDcycle = mech.cycle + 30; //fire cooldown
}
if (mech.holdingTarget) {
mech.drop();
@@ -2117,7 +2124,7 @@ const b = {
friction: 0,
frictionAir: 0.10,
restitution: 0.3,
- dmg: 0.18, //damage done in addition to the damage from momentum
+ dmg: 0.17, //damage done in addition to the damage from momentum
lookFrequency: 10 + Math.floor(7 * Math.random()),
endCycle: game.cycle + 120 * b.isModBulletsLastLonger, //Math.floor((1200 + 420 * Math.random()) * b.isModBulletsLastLonger),
classType: "bullet",
@@ -3286,7 +3293,7 @@ const b = {
if (who.shield) {
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].id === who.shieldTargetID) { //apply some knock back to shield mob before shield breaks
- const force = Matter.Vector.mult(this.velocity, 15 / mob[i].mass)
+ const force = Matter.Vector.mult(this.velocity, 7 / mob[i].mass)
Matter.Body.setVelocity(mob[i], {
x: mob[i].velocity.x + force.x,
y: mob[i].velocity.y + force.y
@@ -3757,6 +3764,16 @@ const b = {
if (best.who) b.explosion(path[1], 1000 * energy, true)
mech.fireCDcycle = mech.cycle + Math.floor(60 * b.modFireRate); // cool down
+ if (b.isModPulseStun) {
+ const range = 100 + 2000 * energy
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (mob[i].alive && !mob[i].isShielded) {
+ dist = Vector.magnitude(Vector.sub(path[1], mob[i].position)) - mob[i].radius;
+ if (dist < range) mobs.statusStun(mob[i], 30 + Math.floor(energy * 60))
+ }
+ }
+ }
+
//draw laser beam
ctx.beginPath();
ctx.moveTo(path[0].x, path[0].y);
diff --git a/js/level.js b/js/level.js
index 17b2da6..81b4f5b 100644
--- a/js/level.js
+++ b/js/level.js
@@ -146,9 +146,9 @@ const level = {
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
// spawn.laserBoss(2900, -500)
- // spawn.sucker(1200, -500)
+ spawn.striker(1200, -500)
// spawn.timeSkipBoss(2900, -500)
- spawn.randomMob(1600, -500)
+ // spawn.randomMob(1600, -500)
},
bosses() {
@@ -492,12 +492,12 @@ const level = {
spawn.mapRect(5200, -775, 100, 920);
spawn.mapRect(5300, -1075, 350, 1220);
spawn.boost(5825, 235, 1400);
- level.fillBG.push({
+ level.fill.push({
x: 5200,
y: 125,
width: 450,
height: 200,
- color: "rgba(0,20,40,0.2)"
+ color: "rgba(0,20,40,0.25)"
});
//structure bellow tall stairs
@@ -522,12 +522,12 @@ const level = {
spawn.mapRect(4100, -3450, 100, 700); //left top shelf
spawn.mapRect(4200, -3450, 100, 400); //left top shelf
spawn.mapRect(4300, -3450, 100, 100); //left top shelf
- level.fillBG.push({
+ level.fill.push({
x: 4100,
y: -3450,
width: 500,
height: 1750,
- color: "#d0d4d6"
+ color: "rgba(0,20,40,0.1)"
});
level.fill.push({
x: 4100,
diff --git a/js/player.js b/js/player.js
index 33ff1a9..6d81d1e 100644
--- a/js/player.js
+++ b/js/player.js
@@ -886,8 +886,8 @@ const mech = {
throwBlock() {
if (mech.holdingTarget) {
if (keys[32] || game.mouseDownRight) {
- if (mech.energy > 0.0007) {
- mech.energy -= 0.0007;
+ if (mech.energy > 0.001) {
+ mech.energy -= 0.001 / b.modThrowChargeRate;
mech.throwCharge += 0.5 * b.modThrowChargeRate / mech.holdingTarget.mass
//draw charge
const x = mech.pos.x + 15 * Math.cos(mech.angle);
@@ -1261,6 +1261,46 @@ const mech = {
}
}
},
+ {
+ name: "standing wave harmonics",
+ description: "three oscillating shields are permanently active
energy regenerates while field is active",
+ isEasyToAim: true,
+ effect: () => {
+ mech.hold = function () {
+ if (mech.isHolding) {
+ mech.drawHold(mech.holdingTarget);
+ mech.holding();
+ mech.throwBlock();
+ } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed
+ mech.grabPowerUp();
+ mech.lookForPickUp();
+ } else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
+ mech.pickUp();
+ } else {
+ 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)
+ }
+ if (mech.energy > 0.1 && mech.fieldCDcycle < mech.cycle) {
+ const fieldRange1 = (0.55 + 0.35 * Math.sin(mech.cycle / 23)) * mech.fieldRange
+ const fieldRange2 = (0.5 + 0.4 * Math.sin(mech.cycle / 37)) * mech.fieldRange
+ const fieldRange3 = (0.45 + 0.45 * Math.sin(mech.cycle / 47)) * mech.fieldRange
+ const netfieldRange = Math.max(fieldRange1, fieldRange2, fieldRange3)
+ ctx.fillStyle = "rgba(110,170,200," + (0.04 + mech.energy * (0.12 + 0.13 * Math.random())) + ")";
+ ctx.beginPath();
+ ctx.arc(mech.pos.x, mech.pos.y, fieldRange1, 0, 2 * Math.PI);
+ ctx.fill();
+ ctx.beginPath();
+ ctx.arc(mech.pos.x, mech.pos.y, fieldRange2, 0, 2 * Math.PI);
+ ctx.fill();
+ ctx.beginPath();
+ ctx.arc(mech.pos.x, mech.pos.y, fieldRange3, 0, 2 * Math.PI);
+ ctx.fill();
+ mech.pushMobs360(netfieldRange);
+ // mech.pushBody360(netfieldRange); //can't throw block when pushhing blocks away
+ }
+ mech.drawFieldMeter()
+ }
+ }
+ },
{
name: "perfect diamagnetism",
// description: "gain energy when blocking
no recoil when blocking",
@@ -1320,97 +1360,192 @@ const mech = {
}
},
{
- name: "time dilation field",
- description: "use energy to stop time
you can move and fire while time is stopped",
+ name: "nano-scale manufacturing",
+ description: "excess energy used to build drones
2x energy regeneration",
isEasyToAim: true,
effect: () => {
- // mech.fieldMeterColor = "#000"
- mech.fieldFire = true;
- mech.isBodiesAsleep = false;
+ // mech.fieldRegen *= 2;
mech.hold = function () {
+ if (mech.energy > mech.fieldEnergyMax - 0.02 && mech.fieldCDcycle < mech.cycle) {
+ if (b.isModSporeField) {
+ // 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())
+ mech.energy -= len * 0.074;
+ for (let i = 0; i < len; i++) {
+ b.spore(player)
+ }
+ } else if (b.isModMissileField) {
+ // 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.modFireRate,
+ 1, b.modBabyMissiles)
+ } else if (b.isModIceField) {
+ // mech.fieldCDcycle = mech.cycle + 17; // set cool down to prevent +energy from making huge numbers of drones
+ mech.energy -= 0.061;
+ b.iceIX(1)
+ } else {
+ // mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones
+ mech.energy -= 0.33;
+ b.drone(1)
+ }
+
+ }
if (mech.isHolding) {
- mech.wakeCheck();
mech.drawHold(mech.holdingTarget);
mech.holding();
mech.throwBlock();
- } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) {
+ } else if ((keys[32] || game.mouseDownRight && mech.fieldCDcycle < mech.cycle)) { //not hold but field button is pressed
mech.grabPowerUp();
- mech.lookForPickUp(180);
-
- const DRAIN = 0.0017
- if (mech.energy > DRAIN) {
- mech.energy -= DRAIN;
- if (mech.energy < DRAIN) {
- mech.fieldCDcycle = mech.cycle + 120;
- mech.energy = 0;
- mech.wakeCheck();
- }
- //draw field everywhere
- ctx.globalCompositeOperation = "saturation"
- // ctx.fillStyle = "rgba(100,200,230," + (0.25 + 0.06 * Math.random()) + ")";
- ctx.fillStyle = "#ccc";
- ctx.fillRect(-100000, -100000, 200000, 200000)
- ctx.globalCompositeOperation = "source-over"
- //stop time
- mech.isBodiesAsleep = true;
-
- function sleep(who) {
- for (let i = 0, len = who.length; i < len; ++i) {
- if (!who[i].isSleeping) {
- who[i].storeVelocity = who[i].velocity
- who[i].storeAngularVelocity = who[i].angularVelocity
- }
- Matter.Sleeping.set(who[i], true)
- }
- }
- sleep(mob);
- sleep(body);
- sleep(bullet);
- //doesn't really work, just slows down constraints
- for (let i = 0, len = cons.length; i < len; i++) {
- if (cons[i].stiffness !== 0) {
- cons[i].storeStiffness = cons[i].stiffness;
- cons[i].stiffness = 0;
- }
- }
-
- game.cycle--; //pause all functions that depend on game cycle increasing
- if (b.isModTimeSkip) {
- game.isTimeSkipping = true;
- mech.cycle++;
- game.gravity();
- Engine.update(engine, game.delta);
- // level.checkZones();
- // level.checkQuery();
- mech.move();
- game.checks();
- // mobs.loop();
- // mech.draw();
- mech.walk_cycle += mech.flipLegs * mech.Vx;
- // mech.hold();
- mech.energy += 0.5 * DRAIN; //x1 to undo the energy drain from time speed up, x1.5 to cut energy drain in half
- b.fire();
- // b.bulletRemove();
- b.bulletDo();
- game.isTimeSkipping = false;
- }
- // game.cycle--; //pause all functions that depend on game cycle increasing
- // if (b.isModTimeSkip && !game.isTimeSkipping) { //speed up the rate of time
- // game.timeSkip(1)
- // mech.energy += 1.5 * DRAIN; //x1 to undo the energy drain from time speed up, x1.5 to cut energy drain in half
- // }
+ mech.lookForPickUp();
+ if (mech.energy > 0.05) {
+ mech.drawField();
+ mech.pushMobsFacing();
}
} else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
- mech.wakeCheck();
mech.pickUp();
} else {
- mech.wakeCheck();
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.energy += mech.fieldRegen;
mech.drawFieldMeter()
}
}
},
+ {
+ name: "negative mass field",
+ description: "use energy to nullify gravity
reduce harm by 80% while field is active", //
launch larger blocks at much higher speeds
+ fieldDrawRadius: 0,
+ isEasyToAim: true,
+ effect: () => {
+ mech.fieldFire = true;
+ mech.holdingMassScale = 0.03; //can hold heavier blocks with lower cost to jumping
+ mech.fieldMeterColor = "#000"
+
+ mech.hold = function () {
+ mech.fieldDamageResistance = 1;
+ if (mech.isHolding) {
+ mech.drawHold(mech.holdingTarget);
+ mech.holding();
+ mech.throwBlock();
+ } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { //push away
+ mech.grabPowerUp();
+ mech.lookForPickUp();
+ const DRAIN = 0.00035
+ if (mech.energy > DRAIN) {
+ mech.fieldDamageResistance = 0.2; // 1 - 0.8
+ // mech.pushMobs360();
+
+ //repulse mobs
+ // for (let i = 0, len = mob.length; i < len; ++i) {
+ // sub = Vector.sub(mob[i].position, mech.pos);
+ // dist2 = Vector.magnitudeSquared(sub);
+ // if (dist2 < this.fieldDrawRadius * this.fieldDrawRadius && mob[i].speed > 6) {
+ // const force = Vector.mult(Vector.perp(Vector.normalise(sub)), 0.00004 * mob[i].speed * mob[i].mass)
+ // mob[i].force.x = force.x
+ // mob[i].force.y = force.y
+ // }
+ // }
+
+
+ //look for nearby objects to make zero-g
+ function zeroG(who, range, mag = 1.06) {
+ for (let i = 0, len = who.length; i < len; ++i) {
+ sub = Vector.sub(who[i].position, mech.pos);
+ dist = Vector.magnitude(sub);
+ if (dist < range) {
+ who[i].force.y -= who[i].mass * (game.g * mag); //add a bit more then standard gravity
+ }
+ }
+ }
+ // zeroG(bullet); //works fine, but not that noticeable and maybe not worth the possible performance hit
+ // zeroG(mob); //mobs are too irregular to make this work?
+
+ if (keys[83] || keys[40]) { //down
+ player.force.y -= 0.5 * player.mass * mech.gravity;
+ this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 400 * 0.03;
+ zeroG(powerUp, this.fieldDrawRadius, 0.7);
+ zeroG(body, this.fieldDrawRadius, 0.7);
+ } else if (keys[87] || keys[38]) { //up
+ mech.energy -= 5 * DRAIN;
+ this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 850 * 0.03;
+ player.force.y -= 1.45 * player.mass * mech.gravity;
+ zeroG(powerUp, this.fieldDrawRadius, 1.38);
+ zeroG(body, this.fieldDrawRadius, 1.38);
+ } else {
+ mech.energy -= DRAIN;
+ this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 650 * 0.03;
+ player.force.y -= 1.07 * player.mass * mech.gravity; // slow upward drift
+ zeroG(powerUp, this.fieldDrawRadius);
+ zeroG(body, this.fieldDrawRadius);
+ }
+ if (mech.energy < 0.001) {
+ mech.fieldCDcycle = mech.cycle + 120;
+ mech.energy = 0;
+ }
+ //add extra friction for horizontal motion
+ if (keys[65] || keys[68] || keys[37] || keys[39]) {
+ Matter.Body.setVelocity(player, {
+ x: player.velocity.x * 0.99,
+ y: player.velocity.y * 0.97
+ });
+ } else { //slow rise and fall
+ Matter.Body.setVelocity(player, {
+ x: player.velocity.x,
+ y: player.velocity.y * 0.97
+ });
+ }
+
+ //draw zero-G range
+ ctx.beginPath();
+ ctx.arc(mech.pos.x, mech.pos.y, this.fieldDrawRadius, 0, 2 * Math.PI);
+ ctx.fillStyle = "#f5f5ff";
+ ctx.globalCompositeOperation = "difference";
+ ctx.fill();
+ if (b.isModHawking) {
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (mob[i].distanceToPlayer2() < this.fieldDrawRadius * this.fieldDrawRadius && Matter.Query.ray(map, mech.pos, mob[i].position).length === 0 && Matter.Query.ray(body, mech.pos, mob[i].position).length === 0) {
+ mob[i].damage(b.dmgScale * 0.085);
+ mob[i].locatePlayer();
+
+ //draw electricity
+ const sub = Vector.sub(mob[i].position, mech.pos)
+ const unit = Vector.normalise(sub);
+ const steps = 6
+ const step = Vector.magnitude(sub) / steps;
+ ctx.beginPath();
+ let x = mech.pos.x + 30 * unit.x;
+ let y = mech.pos.y + 30 * unit.y;
+ ctx.moveTo(x, y);
+ for (let i = 0; i < steps; i++) {
+ x += step * (unit.x + 0.7 * (Math.random() - 0.5))
+ y += step * (unit.y + 0.7 * (Math.random() - 0.5))
+ ctx.lineTo(x, y);
+ }
+ ctx.lineWidth = 1;
+ ctx.strokeStyle = "rgba(0,255,0,0.5)" //"#fff";
+ ctx.stroke();
+
+ }
+ }
+ }
+ ctx.globalCompositeOperation = "source-over";
+ }
+ } else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
+ mech.pickUp();
+ this.fieldDrawRadius = 0
+ } else {
+ 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.fieldDrawRadius = 0
+ }
+ mech.drawFieldMeter("rgba(0,0,0,0.2)")
+ }
+ }
+ },
{
name: "plasma torch",
description: "use energy to emit damaging plasma
effective at close range",
@@ -1578,228 +1713,93 @@ const mech = {
}
},
{
- name: "negative mass field",
- description: "use energy to nullify gravity
reduce harm by 80% while field is active", //
launch larger blocks at much higher speeds
- fieldDrawRadius: 0,
+ name: "time dilation field",
+ description: "use energy to stop time
you can move and fire while time is stopped",
isEasyToAim: true,
effect: () => {
+ // mech.fieldMeterColor = "#000"
mech.fieldFire = true;
- mech.holdingMassScale = 0.03; //can hold heavier blocks with lower cost to jumping
- mech.fieldMeterColor = "#000"
-
+ mech.isBodiesAsleep = false;
mech.hold = function () {
- mech.fieldDamageResistance = 1;
if (mech.isHolding) {
+ mech.wakeCheck();
mech.drawHold(mech.holdingTarget);
mech.holding();
mech.throwBlock();
- } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { //push away
+ } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) {
mech.grabPowerUp();
- mech.lookForPickUp();
- const DRAIN = 0.00035
+ mech.lookForPickUp(180);
+
+ const DRAIN = 0.0017
if (mech.energy > DRAIN) {
- mech.fieldDamageResistance = 0.2; // 1 - 0.8
- // mech.pushMobs360();
-
- //repulse mobs
- // for (let i = 0, len = mob.length; i < len; ++i) {
- // sub = Vector.sub(mob[i].position, mech.pos);
- // dist2 = Vector.magnitudeSquared(sub);
- // if (dist2 < this.fieldDrawRadius * this.fieldDrawRadius && mob[i].speed > 6) {
- // const force = Vector.mult(Vector.perp(Vector.normalise(sub)), 0.00004 * mob[i].speed * mob[i].mass)
- // mob[i].force.x = force.x
- // mob[i].force.y = force.y
- // }
- // }
-
-
- //look for nearby objects to make zero-g
- function zeroG(who, range, mag = 1.06) {
- for (let i = 0, len = who.length; i < len; ++i) {
- sub = Vector.sub(who[i].position, mech.pos);
- dist = Vector.magnitude(sub);
- if (dist < range) {
- who[i].force.y -= who[i].mass * (game.g * mag); //add a bit more then standard gravity
- }
- }
- }
- // zeroG(bullet); //works fine, but not that noticeable and maybe not worth the possible performance hit
- // zeroG(mob); //mobs are too irregular to make this work?
-
- if (keys[83] || keys[40]) { //down
- player.force.y -= 0.5 * player.mass * mech.gravity;
- this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 400 * 0.03;
- zeroG(powerUp, this.fieldDrawRadius, 0.7);
- zeroG(body, this.fieldDrawRadius, 0.7);
- } else if (keys[87] || keys[38]) { //up
- mech.energy -= 5 * DRAIN;
- this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 850 * 0.03;
- player.force.y -= 1.45 * player.mass * mech.gravity;
- zeroG(powerUp, this.fieldDrawRadius, 1.38);
- zeroG(body, this.fieldDrawRadius, 1.38);
- } else {
- mech.energy -= DRAIN;
- this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 650 * 0.03;
- player.force.y -= 1.07 * player.mass * mech.gravity; // slow upward drift
- zeroG(powerUp, this.fieldDrawRadius);
- zeroG(body, this.fieldDrawRadius);
- }
- if (mech.energy < 0.001) {
+ mech.energy -= DRAIN;
+ if (mech.energy < DRAIN) {
mech.fieldCDcycle = mech.cycle + 120;
mech.energy = 0;
+ mech.wakeCheck();
}
- //add extra friction for horizontal motion
- if (keys[65] || keys[68] || keys[37] || keys[39]) {
- Matter.Body.setVelocity(player, {
- x: player.velocity.x * 0.99,
- y: player.velocity.y * 0.97
- });
- } else { //slow rise and fall
- Matter.Body.setVelocity(player, {
- x: player.velocity.x,
- y: player.velocity.y * 0.97
- });
- }
-
- //draw zero-G range
- ctx.beginPath();
- ctx.arc(mech.pos.x, mech.pos.y, this.fieldDrawRadius, 0, 2 * Math.PI);
- ctx.fillStyle = "#f5f5ff";
- ctx.globalCompositeOperation = "difference";
- ctx.fill();
- if (b.isModHawking) {
- for (let i = 0, len = mob.length; i < len; i++) {
- if (mob[i].distanceToPlayer2() < this.fieldDrawRadius * this.fieldDrawRadius && Matter.Query.ray(map, mech.pos, mob[i].position).length === 0 && Matter.Query.ray(body, mech.pos, mob[i].position).length === 0) {
- mob[i].damage(b.dmgScale * 0.085);
- mob[i].locatePlayer();
-
- //draw electricity
- const sub = Vector.sub(mob[i].position, mech.pos)
- const unit = Vector.normalise(sub);
- const steps = 6
- const step = Vector.magnitude(sub) / steps;
- ctx.beginPath();
- let x = mech.pos.x + 30 * unit.x;
- let y = mech.pos.y + 30 * unit.y;
- ctx.moveTo(x, y);
- for (let i = 0; i < steps; i++) {
- x += step * (unit.x + 0.7 * (Math.random() - 0.5))
- y += step * (unit.y + 0.7 * (Math.random() - 0.5))
- ctx.lineTo(x, y);
- }
- ctx.lineWidth = 1;
- ctx.strokeStyle = "rgba(0,255,0,0.5)" //"#fff";
- ctx.stroke();
+ //draw field everywhere
+ ctx.globalCompositeOperation = "saturation"
+ // ctx.fillStyle = "rgba(100,200,230," + (0.25 + 0.06 * Math.random()) + ")";
+ ctx.fillStyle = "#ccc";
+ ctx.fillRect(-100000, -100000, 200000, 200000)
+ ctx.globalCompositeOperation = "source-over"
+ //stop time
+ mech.isBodiesAsleep = true;
+ function sleep(who) {
+ for (let i = 0, len = who.length; i < len; ++i) {
+ if (!who[i].isSleeping) {
+ who[i].storeVelocity = who[i].velocity
+ who[i].storeAngularVelocity = who[i].angularVelocity
}
+ Matter.Sleeping.set(who[i], true)
}
}
- ctx.globalCompositeOperation = "source-over";
- }
- } else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
- mech.pickUp();
- this.fieldDrawRadius = 0
- } else {
- 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.fieldDrawRadius = 0
- }
- mech.drawFieldMeter("rgba(0,0,0,0.2)")
- }
- }
- },
- {
- name: "standing wave harmonics",
- description: "three oscillating shields are permanently active
energy regenerates while field is active",
- isEasyToAim: true,
- effect: () => {
- mech.hold = function () {
- if (mech.isHolding) {
- mech.drawHold(mech.holdingTarget);
- mech.holding();
- mech.throwBlock();
- } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed
- mech.grabPowerUp();
- mech.lookForPickUp();
- } else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
- mech.pickUp();
- } else {
- 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)
- }
- if (mech.energy > 0.1 && mech.fieldCDcycle < mech.cycle) {
- const fieldRange1 = (0.55 + 0.35 * Math.sin(mech.cycle / 23)) * mech.fieldRange
- const fieldRange2 = (0.5 + 0.4 * Math.sin(mech.cycle / 37)) * mech.fieldRange
- const fieldRange3 = (0.45 + 0.45 * Math.sin(mech.cycle / 47)) * mech.fieldRange
- const netfieldRange = Math.max(fieldRange1, fieldRange2, fieldRange3)
- ctx.fillStyle = "rgba(110,170,200," + (0.04 + mech.energy * (0.12 + 0.13 * Math.random())) + ")";
- ctx.beginPath();
- ctx.arc(mech.pos.x, mech.pos.y, fieldRange1, 0, 2 * Math.PI);
- ctx.fill();
- ctx.beginPath();
- ctx.arc(mech.pos.x, mech.pos.y, fieldRange2, 0, 2 * Math.PI);
- ctx.fill();
- ctx.beginPath();
- ctx.arc(mech.pos.x, mech.pos.y, fieldRange3, 0, 2 * Math.PI);
- ctx.fill();
- mech.pushMobs360(netfieldRange);
- // mech.pushBody360(netfieldRange); //can't throw block when pushhing blocks away
- }
- mech.drawFieldMeter()
- }
- }
- },
- {
- name: "nano-scale manufacturing",
- description: "excess energy used to build drones
2x energy regeneration",
- isEasyToAim: true,
- effect: () => {
- // mech.fieldRegen *= 2;
- mech.hold = function () {
- if (mech.energy > mech.fieldEnergyMax - 0.02 && mech.fieldCDcycle < mech.cycle) {
- if (b.isModSporeField) {
- // 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())
- mech.energy -= len * 0.074;
- for (let i = 0; i < len; i++) {
- b.spore(player)
+ sleep(mob);
+ sleep(body);
+ sleep(bullet);
+ //doesn't really work, just slows down constraints
+ for (let i = 0, len = cons.length; i < len; i++) {
+ if (cons[i].stiffness !== 0) {
+ cons[i].storeStiffness = cons[i].stiffness;
+ cons[i].stiffness = 0;
+ }
}
- } else if (b.isModMissileField) {
- // 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.modFireRate,
- 1, b.modBabyMissiles)
- } else if (b.isModIceField) {
- // mech.fieldCDcycle = mech.cycle + 17; // set cool down to prevent +energy from making huge numbers of drones
- mech.energy -= 0.061;
- b.iceIX(1)
- } else {
- // mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones
- mech.energy -= 0.33;
- b.drone(1)
- }
- }
- if (mech.isHolding) {
- mech.drawHold(mech.holdingTarget);
- mech.holding();
- mech.throwBlock();
- } else if ((keys[32] || game.mouseDownRight && mech.fieldCDcycle < mech.cycle)) { //not hold but field button is pressed
- mech.grabPowerUp();
- mech.lookForPickUp();
- if (mech.energy > 0.05) {
- mech.drawField();
- mech.pushMobsFacing();
+ game.cycle--; //pause all functions that depend on game cycle increasing
+ if (b.isModTimeSkip) {
+ game.isTimeSkipping = true;
+ mech.cycle++;
+ game.gravity();
+ Engine.update(engine, game.delta);
+ // level.checkZones();
+ // level.checkQuery();
+ mech.move();
+ game.checks();
+ // mobs.loop();
+ // mech.draw();
+ mech.walk_cycle += mech.flipLegs * mech.Vx;
+ // mech.hold();
+ mech.energy += 0.5 * DRAIN; //x1 to undo the energy drain from time speed up, x1.5 to cut energy drain in half
+ b.fire();
+ // b.bulletRemove();
+ b.bulletDo();
+ game.isTimeSkipping = false;
+ }
+ // game.cycle--; //pause all functions that depend on game cycle increasing
+ // if (b.isModTimeSkip && !game.isTimeSkipping) { //speed up the rate of time
+ // game.timeSkip(1)
+ // mech.energy += 1.5 * DRAIN; //x1 to undo the energy drain from time speed up, x1.5 to cut energy drain in half
+ // }
}
} else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
+ mech.wakeCheck();
mech.pickUp();
} else {
+ mech.wakeCheck();
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.energy += mech.fieldRegen;
mech.drawFieldMeter()
}
}
@@ -2009,6 +2009,7 @@ const mech = {
if (mech.energy > DRAIN) {
mech.energy -= DRAIN;
Matter.Body.setVelocity(body[i], velocity); //give block mouse velocity
+ Matter.Body.setAngularVelocity(body[i], body[i].angularVelocity * 0.8)
body[i].force.y -= body[i].mass * game.g; //remove gravity effects
} else {
mech.fieldOn = false
diff --git a/js/spawn.js b/js/spawn.js
index f36e92c..7fc169e 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -942,7 +942,8 @@ const spawn = {
me.g = 0.0002; //required if using 'gravity'
me.frictionStatic = 0;
me.friction = 0;
- me.delay = 100;
+ me.delay = 120 * game.CDScale;
+ me.cd = Infinity;
Matter.Body.rotate(me, Math.PI * 0.1);
spawn.shield(me, x, y);
me.onDamage = function () {
@@ -950,7 +951,20 @@ const spawn = {
};
me.do = function () {
this.gravity();
- this.seePlayerCheck();
+ if (!(game.cycle % this.seePlayerFreq)) { // this.seePlayerCheck(); from mobs
+ if (
+ this.distanceToPlayer2() < this.seeAtDistance2 &&
+ Matter.Query.ray(map, this.position, this.mechPosRange()).length === 0 &&
+ Matter.Query.ray(body, this.position, this.mechPosRange()).length === 0 &&
+ !mech.isStealth
+ ) {
+ this.foundPlayer();
+ if (this.cd === Infinity) this.cd = game.cycle + this.delay;
+ } else if (this.seePlayer.recall) {
+ this.lostPlayer();
+ this.cd = Infinity
+ }
+ }
this.checkStatus();
this.attraction();
this.strike();
diff --git a/todo.txt b/todo.txt
index ad610db..192bcad 100644
--- a/todo.txt
+++ b/todo.txt
@@ -3,26 +3,19 @@
************** TODO - n-gon **************
+an effect when canceling a power up
+ ammo? heals?
+ 50% chance for a mod, 25% heal, 25% ammo
+
+liquid nitrogen cooling
+ Mobs freeze on contact with the player
+
+uranium reactor core
+ Mobs get irradiated on contact with the player
+
add player Scent Trails for mod navigation
https://abitawake.com/news/articles/enemy-ai-chasing-a-player-without-navigation2d-or-a-star-pathfinding
-mod - energy replaces your health,
-
-field - pilot wave
- while mouse is down blocks (and mobs?) are move with the mouse
- players can do serious damage by flicking the mouse and firing blocks
- on mouse down calculate relative position of block to mouse and maintain that as mouse moves
- on mouse up give blocks the computed mouse velocity
- use a gravity effect that pulls blocks in range towards the center of the mouse
- maybe no force in the very center to prevent clumping
- draw a ellipse around the mouse that wobbles like phase decoherence field, and changes color maybe like negative mass field
-
-make flurooantimonic acid mod a damage over time
- rename to radiation damage?
-
-mod - radiation damage over time effects can spread to nearby mobs
- do a check for nearby mobs on each tick
-
try adding a subtile shift of color towards red, green or blue
block, map, background, text? color
could be random as each level loads