bug fixes, pulse stun mod

This commit is contained in:
landgreen
2020-04-14 19:00:29 -07:00
parent 9ea34d8c8d
commit 4e1c5467e3
5 changed files with 378 additions and 353 deletions

View File

@@ -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: "<strong>5x</strong> physical <strong class='color-d'>damage</strong> to unaware mobs<br><em>unaware mobs don't have a health bar</em>",
description: "<strong>bullets</strong> do <strong>5x</strong> <strong class='color-d'>damage</strong> to <strong>unaware</strong> mobs<br><em>unaware mobs don't have a health bar</em>",
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: "<strong>blocks</strong> do <strong>3x</strong> more <strong class='color-d'>damage</strong> to mobs<br>charge <strong>throws</strong> in <strong>3x</strong> less time",
description: "<strong>blocks</strong> do <strong>2x</strong> more <strong class='color-d'>damage</strong> to mobs<br>charge <strong>throws</strong> more <strong>quickly</strong> for less <strong class='color-f'>energy</strong>",
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: "<strong class='color-h'>heal</strong> up to <strong>1%</strong> of max health every second<br>active for <strong>5 seconds</strong> after a mob <strong>dies</strong>",
maxCount: 1,
count: 0,
allowed() {
return true
},
requires: "",
effect() {
b.isModHealthRecovery = true;
},
remove() {
b.isModHealthRecovery = false;
}
},
{
name: "waste energy recovery",
description: "regen <strong>7%</strong> of max <strong class='color-f'>energy</strong> every second<br>active for <strong>5 seconds</strong> after a mob <strong>dies</strong>",
@@ -418,31 +434,15 @@ const b = {
b.isModEnergyRecovery = false;
}
},
{
name: "scrap recycling",
description: "<strong class='color-h'>heal</strong> up to <strong>1%</strong> of max health every second<br>active for <strong>5 seconds</strong> after a mob <strong>dies</strong>",
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 <strong class='color-d'>damage</strong> by <strong>33%</strong><br>but, after a mob <strong>dies</strong> lose <strong>1/2</strong> your <strong class='color-f'>energy</strong>",
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 <strong>landings</strong> disrupt <strong class='color-p' style='letter-spacing: 2px;'>spores</strong> in the ground<br>immune to <strong>harm</strong> from <strong>falling</strong>",
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 <strong>collide</strong> with mobs for <strong>+2</strong> seconds<br>activates after being <strong>harmed</strong> 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 <strong class='color-f'>energy</strong> replaces your <strong>health</strong><br>you can't <strong>die</strong> if your <strong class='color-f'>energy</strong> is above <strong>zero</strong>",
description: "you can't <strong>die</strong> if your <strong class='color-f'>energy</strong> is above <strong>zero</strong><br>your <strong>health</strong> is permanently set to <strong>zero</strong>",
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 <strong>pulse's</strong> explosion are <strong>stunned</strong>",
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 <strong>perfect diamagnetism</strong><br><strong>stuns</strong> mobs for <strong>+1</strong> 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("<div style='font-size:140%;'>NO AMMO</div> <p style='font-size:90%;'><strong>Q</strong>, <strong>E</strong>, and <strong>mouse wheel</strong> change weapons</p>", 200);
}
mech.fireCDcycle = mech.cycle + 30; //fire cooldown
game.replaceTextLog = true;
game.makeTextLog("<div style='font-size:140%;'>NO AMMO</div> <p style='font-size:90%;'><strong>Q</strong>, <strong>E</strong>, and <strong>mouse wheel</strong> change weapons</p>", 200);
}
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);

View File

@@ -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,

View File

@@ -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 <strong>shields</strong> are permanently active<br><strong class='color-f'>energy</strong> 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 <strong class='color-f'>energy</strong> when <strong>blocking</strong><br>no <strong>recoil</strong> when <strong>blocking</strong>",
@@ -1320,97 +1360,192 @@ const mech = {
}
},
{
name: "time dilation field",
description: "use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 1px;'>stop time</strong><br><em>you can move and fire while time is stopped</em>",
name: "nano-scale manufacturing",
description: "excess <strong class='color-f'>energy</strong> used to build <strong>drones</strong><br><strong>2x</strong> <strong class='color-f'>energy</strong> 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 <strong class='color-f'>energy</strong> to nullify &nbsp; <strong style='letter-spacing: 12px;'>gravity</strong><br>reduce <strong>harm</strong> by <strong>80%</strong> while field is active", //<br><strong>launch</strong> 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 <strong class='color-f'>energy</strong> to emit <strong class='color-d'>damaging</strong> plasma<br><em>effective at close range</em>",
@@ -1578,228 +1713,93 @@ const mech = {
}
},
{
name: "negative mass field",
description: "use <strong class='color-f'>energy</strong> to nullify &nbsp; <strong style='letter-spacing: 12px;'>gravity</strong><br>reduce <strong>harm</strong> by <strong>80%</strong> while field is active", //<br><strong>launch</strong> larger blocks at much higher speeds
fieldDrawRadius: 0,
name: "time dilation field",
description: "use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 1px;'>stop time</strong><br><em>you can move and fire while time is stopped</em>",
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 <strong>shields</strong> are permanently active<br><strong class='color-f'>energy</strong> 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 <strong class='color-f'>energy</strong> used to build <strong>drones</strong><br><strong>2x</strong> <strong class='color-f'>energy</strong> 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

View File

@@ -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();

View File

@@ -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