added a few mods and added custom difficulty

This commit is contained in:
landgreen
2020-02-15 19:01:31 -08:00
parent d186ff7636
commit 749fd0f797
8 changed files with 167 additions and 91 deletions

View File

@@ -38,9 +38,13 @@ const b = {
isModStomp: null, isModStomp: null,
modSuperBallNumber: null, modSuperBallNumber: null,
modLaserReflections: null, modLaserReflections: null,
modLaserDamage: null,
modLaserFieldDrain: null,
isModNoAmmo: null, isModNoAmmo: null,
isModAmmoFromHealth: null, isModAmmoFromHealth: null,
mobDieAtHealth: null, mobDieAtHealth: null,
isModEnergyRecovery: null,
isModHealthRecovery: null,
setModDefaults() { setModDefaults() {
b.modCount = 0; b.modCount = 0;
b.modFireRate = 1; b.modFireRate = 1;
@@ -77,9 +81,14 @@ const b = {
b.modCollisionImmuneCycles = 30; b.modCollisionImmuneCycles = 30;
b.modSuperBallNumber = 4; b.modSuperBallNumber = 4;
b.modLaserReflections = 2; b.modLaserReflections = 2;
b.modLaserDamage = 0.05;
b.modLaserFieldDrain = 0.002;
b.isModNoAmmo = false; b.isModNoAmmo = false;
b.isModAmmoFromHealth = 0; b.isModAmmoFromHealth = 0;
b.mobDieAtHealth = 0.05; b.mobDieAtHealth = 0.05;
b.isModEnergyRecovery = false;
b.isModHealthRecovery = false;
mech.fieldRange = 175;
mech.Fx = 0.015; mech.Fx = 0.015;
mech.jumpForce = 0.38; mech.jumpForce = 0.38;
mech.maxHealth = 1; mech.maxHealth = 1;
@@ -94,7 +103,7 @@ const b = {
modOnHealthChange() { modOnHealthChange() {
if (b.isModAcidDmg && mech.health > 0.8) { if (b.isModAcidDmg && mech.health > 0.8) {
game.playerDmgColor = "rgba(0,80,80,0.9)" game.playerDmgColor = "rgba(0,80,80,0.9)"
b.modAcidDmg = 1.1 b.modAcidDmg = 0.9
} else { } else {
game.playerDmgColor = "rgba(0,0,0,0.7)" game.playerDmgColor = "rgba(0,0,0,0.7)"
b.modAcidDmg = 0 b.modAcidDmg = 0
@@ -224,7 +233,7 @@ const b = {
{ {
name: "reaction inhibitor", name: "reaction inhibitor",
description: "mobs <strong>die</strong> if their life goes below <strong>12%</strong>", description: "mobs <strong>die</strong> if their life goes below <strong>12%</strong>",
maxCount: 3, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return true return true
@@ -301,6 +310,18 @@ const b = {
b.modBlockDmg += 0.7 //if you change this value also update the for loop in the electricity graphics in mech.pushMass b.modBlockDmg += 0.7 //if you change this value also update the for loop in the electricity graphics in mech.pushMass
} }
}, },
{
name: "field superposition",
description: "increase your field <strong>radius</strong> by <strong>40%</strong>",
maxCount: 1,
count: 0,
allowed() {
return b.modBlockDmg > 0
},
effect() {
mech.fieldRange = 175 * 1.4 //175 is default
}
},
{ {
name: "entanglement", name: "entanglement",
description: "only when your <strong>first gun</strong> is equipped<br>reduce <strong>harm</strong> by <strong>10%</strong> for each gun you have", description: "only when your <strong>first gun</strong> is equipped<br>reduce <strong>harm</strong> by <strong>10%</strong> for each gun you have",
@@ -313,6 +334,30 @@ const b = {
b.isModEntanglement = true b.isModEntanglement = true
} }
}, },
{
name: "waste energy recycling",
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>",
maxCount: 1,
count: 0,
allowed() {
return true
},
effect() {
b.isModEnergyRecovery = true;
}
},
{
name: "waste scrap recycling",
description: "regen up to <strong>1%</strong> of max <strong class='color-h'>health</strong> every second<br>active for <strong>5 seconds</strong> after a mob <strong>dies</strong>",
maxCount: 1,
count: 0,
allowed() {
return b.isModEnergyRecovery
},
effect() {
b.isModHealthRecovery = true;
}
},
{ {
name: "squirrel-cage rotor", name: "squirrel-cage rotor",
description: "<strong>jump</strong> higher and <strong>move</strong> faster<br>reduced <strong>harm</strong> from <strong>falling</strong> ", description: "<strong>jump</strong> higher and <strong>move</strong> faster<br>reduced <strong>harm</strong> from <strong>falling</strong> ",
@@ -577,7 +622,7 @@ const b = {
}, },
{ {
name: "specular reflection", name: "specular reflection",
description: "your <strong>laser</strong> gains <strong>+1</strong> reflection", description: "your <strong>laser</strong> gains <strong>+1</strong> reflection<br><strong>+20%</strong> laser <strong class='color-d'>damage</strong> and <strong class='color-f'>energy</strong> drain",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
allowed() { allowed() {
@@ -585,6 +630,8 @@ const b = {
}, },
effect() { effect() {
b.modLaserReflections++; b.modLaserReflections++;
b.modLaserDamage += 0.010; //base is 0.05
b.modLaserFieldDrain += 0.0004 //base is 0.002
} }
}, },
{ {
@@ -2049,7 +2096,7 @@ const b = {
name: "rail gun", //13 name: "rail gun", //13
description: "use <strong class='color-f'>energy</strong> to launch a high-speed <strong>dense</strong> rod<br><strong>hold</strong> left mouse to charge, <strong>release</strong> to fire", description: "use <strong class='color-f'>energy</strong> to launch a high-speed <strong>dense</strong> rod<br><strong>hold</strong> left mouse to charge, <strong>release</strong> to fire",
ammo: 0, ammo: 0,
ammoPack: 2, ammoPack: 2.84,
have: false, have: false,
isStarterGun: false, isStarterGun: false,
fire() { fire() {
@@ -2067,7 +2114,17 @@ const b = {
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
}, },
minDmgSpeed: 5, minDmgSpeed: 5,
onDmg() {}, //this.endCycle = 0 //triggers despawn onDmg(who) {
if (who.shield) {
Matter.Body.setVelocity(this, {
x: -0.1 * this.velocity.x,
y: -0.1 * this.velocity.y
});
Matter.Body.setDensity(this, 0.001);
// this.endCycle = 0;
}
}, //this.endCycle = 0 //triggers despawn
onEnd() {} onEnd() {}
}); });
mech.fireCDcycle = Infinity; // cool down mech.fireCDcycle = Infinity; // cool down
@@ -2254,13 +2311,12 @@ const b = {
have: false, have: false,
isStarterGun: true, isStarterGun: true,
fire() { fire() {
const FIELD_DRAIN = 0.0018 //laser drains energy as well as bullets
const reflectivity = 1 - 1 / (b.modLaserReflections * 1.5) const reflectivity = 1 - 1 / (b.modLaserReflections * 1.5)
let damage = b.dmgScale * 0.05 let damage = b.dmgScale * b.modLaserDamage
if (mech.fieldMeter < FIELD_DRAIN) { if (mech.fieldMeter < b.modLaserFieldDrain) {
mech.fireCDcycle = mech.cycle + 100; // cool down if out of energy mech.fireCDcycle = mech.cycle + 100; // cool down if out of energy
} else { } else {
mech.fieldMeter -= mech.fieldRegen + FIELD_DRAIN mech.fieldMeter -= mech.fieldRegen + b.modLaserFieldDrain
let best = { let best = {
x: null, x: null,
y: null, y: null,

View File

@@ -664,7 +664,18 @@ const game = {
// } // }
} }
if (!(mech.cycle % 60)) { //once a second check if (!(mech.cycle % 60)) { //once a second checks
if (mech.lastKillCycle + 300 > mech.cycle) { //effects active for 5 seconds after killing a mob
if (b.isModEnergyRecovery) {
mech.fieldMeter += mech.fieldEnergyMax * 0.07
if (mech.fieldMeter > mech.fieldEnergyMax) mech.fieldMeter = mech.fieldEnergyMax;
}
if (b.isModHealthRecovery) {
mech.addHealth(0.01)
}
}
} }

View File

@@ -77,14 +77,14 @@ const build = {
} }
} }
// document.title = `effective starting level: ${build.list.length * game.difficultyMode}` // document.title = `effective starting level: ${build.list.length * game.difficultyMode}`
build.calculateCustomDifficulty() // build.calculateCustomDifficulty()
}, },
makeGrid() { makeGrid() {
let text = ` let text = `
<div style="display: flex; justify-content: space-around; align-items: center;"> <div style="display: flex; justify-content: space-around; align-items: center;">
<svg class="SVG-button" onclick="build.startBuildRun()" width="115" height="55"> <svg class="SVG-button" onclick="build.startBuildRun()" width="115" height="51">
<g stroke='none' fill='#333' stroke-width="2" font-size="40px" font-family="Ariel, sans-serif"> <g stroke='none' fill='#333' stroke-width="2" font-size="40px" font-family="Ariel, sans-serif">
<text x="18" y="40">start</text> <text x="18" y="38">start</text>
</g> </g>
</svg> </svg>
<svg class="SVG-button" onclick="build.reset()" width="70" height="35"> <svg class="SVG-button" onclick="build.reset()" width="70" height="35">
@@ -94,15 +94,15 @@ const build = {
</svg> </svg>
</div> </div>
<div style="align-items: center; text-align:center; font-size: 1.00em; line-height: 220%;background-color:#c4ccd8;"> <div style="align-items: center; text-align:center; font-size: 1.00em; line-height: 220%;background-color:#c4ccd8;">
<div id="starting-level"></div> <div>starting level: <input id='starting-level' type="number" step="1" value="0" min="0" max="99"></div>
<label for="difficulty-select" title="effects: number of mobs, damage done by mobs, damage done to mobs, mob speed, heal effects">difficulty:</label> <label for="difficulty-select" title="effects: number of mobs, damage done by mobs, damage done to mobs, mob speed, heal effects">difficulty:</label>
<select name="difficulty-select" id="difficulty-select-custom"> <select name="difficulty-select" id="difficulty-select-custom">
<option value="0">easy</option> <option value="0">easy</option>
<option value="1" selected>normal</option> <option value="1" selected>normal</option>
<option value="2">hard</option> <option value="2">hard</option>
<option value="4">why...</option> <option value="4">why...</option>
</select> </select>
</div>` </div>`
for (let i = 1, len = mech.fieldUpgrades.length; i < len; i++) { for (let i = 1, len = mech.fieldUpgrades.length; i < len; i++) {
text += `<div class="build-grid-module" onclick="build.choosePowerUp(this,${i},'field')"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${mech.fieldUpgrades[i].name}</div> ${mech.fieldUpgrades[i].description}</div>` text += `<div class="build-grid-module" onclick="build.choosePowerUp(this,${i},'field')"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${mech.fieldUpgrades[i].name}</div> ${mech.fieldUpgrades[i].description}</div>`
} }
@@ -125,14 +125,14 @@ const build = {
game.difficultyMode = Number(document.getElementById("difficulty-select-custom").value) game.difficultyMode = Number(document.getElementById("difficulty-select-custom").value)
localSettings.difficultyMode = game.difficultyMode localSettings.difficultyMode = game.difficultyMode
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
build.calculateCustomDifficulty() // build.calculateCustomDifficulty()
}); });
}, },
reset() { reset() {
build.list = [] build.list = []
build.makeGrid(); build.makeGrid();
document.getElementById("build-grid").style.display = "grid" document.getElementById("build-grid").style.display = "grid"
build.calculateCustomDifficulty() // build.calculateCustomDifficulty()
document.getElementById("difficulty-select-custom").value = localSettings.difficultyMode document.getElementById("difficulty-select-custom").value = localSettings.difficultyMode
}, },
pauseGrid() { pauseGrid() {
@@ -178,25 +178,23 @@ const build = {
document.getElementById("pause-grid-left").style.display = "none" document.getElementById("pause-grid-left").style.display = "none"
document.getElementById("pause-grid-right").style.display = "none" document.getElementById("pause-grid-right").style.display = "none"
}, },
calculateCustomDifficulty() { // calculateCustomDifficulty() {
let difficulty = build.list.length * game.difficultyMode // let difficulty = build.list.length * game.difficultyMode
if (game.difficultyMode === 0) difficulty = build.list.length * 1 - 6 // if (game.difficultyMode === 0) difficulty = build.list.length * 1 - 6
if (game.difficultyMode === 4) difficulty = build.list.length * 4 + 8 // if (game.difficultyMode === 4) difficulty = build.list.length * 4 + 8
document.getElementById("starting-level").innerHTML = `starting difficulty: <strong style="font-size:1.05em;">${difficulty}</strong>` // document.getElementById("starting-level").innerHTML = `starting difficulty: <strong style="font-size:1.05em;">${difficulty}</strong>`
}, // },
startBuildRun() { startBuildRun() {
spawn.setSpawnList(); //gives random mobs, not starter mobs spawn.setSpawnList(); //gives random mobs, not starter mobs
spawn.setSpawnList(); spawn.setSpawnList();
game.startGame(); game.startGame();
let difficulty = build.list.length * game.difficultyMode - 1
if (game.difficultyMode === 0) {
difficulty = build.list.length * 1 - 6 - 1
game.isEasyMode = true;
}
if (game.difficultyMode === 4) level.difficultyIncrease(6)
level.difficultyIncrease(difficulty)
level.isBuildRun = true; level.isBuildRun = true;
const increase = Number(document.getElementById("starting-level").value) * game.difficultyMode
level.levelsCleared += increase;
level.difficultyIncrease(increase) //increase difficulty based on modes
level.onLevel = 1;
build.givePowerUps(); build.givePowerUps();
}, },
givePowerUps() { givePowerUps() {
@@ -232,7 +230,7 @@ document.getElementById("build-button").addEventListener("click", () => {
document.body.style.overflowX = "hidden"; document.body.style.overflowX = "hidden";
document.getElementById("info").style.display = 'none' document.getElementById("info").style.display = 'none'
} }
build.calculateCustomDifficulty() // build.calculateCustomDifficulty()
}); });

View File

@@ -14,10 +14,11 @@ const level = {
start() { start() {
if (level.levelsCleared === 0) { if (level.levelsCleared === 0) {
// level.difficultyIncrease(5) // level.difficultyIncrease(5)
// b.giveGuns("wave beam") // b.giveGuns("laser")
// mech.setField("negative mass field") // mech.setField("negative mass field")
// for (let i = 0; i < 9; i++) { // for (let i = 0; i < 9; i++) {
// b.giveMod("reaction inhibitor"); // b.giveMod("waste energy recycling");
// b.giveMod("field superposition");
// } // }
level.intro(); //starting level level.intro(); //starting level
@@ -71,7 +72,7 @@ const level = {
game.lookFreqScale /= 0.98 //mob cycles between looks decreases each level game.lookFreqScale /= 0.98 //mob cycles between looks decreases each level
game.CDScale /= 0.97 //mob CD time decreases each level game.CDScale /= 0.97 //mob CD time decreases each level
} }
if (game.difficulty < 1) game.difficulty = 1; if (game.difficulty < 1) game.difficulty = 0;
game.healScale = 1 / (1 + game.difficulty * 0.09) game.healScale = 1 / (1 + game.difficulty * 0.09)
}, },
levelAnnounce() { levelAnnounce() {

View File

@@ -965,6 +965,7 @@ const mobs = {
this.alive = false; //triggers mob removal in mob[i].replace(i) this.alive = false; //triggers mob removal in mob[i].replace(i)
if (this.dropPowerUp) { if (this.dropPowerUp) {
powerUps.spawnRandomPowerUp(this.position.x, this.position.y, this.mass, radius); powerUps.spawnRandomPowerUp(this.position.x, this.position.y, this.mass, radius);
mech.lastKillCycle = mech.cycle; //tracks the last time a kill was made, mostly used in game.checks()
if (Math.random() < b.modSpores) { if (Math.random() < b.modSpores) {
const len = Math.min(30, Math.floor(4 + this.mass * Math.random())) const len = Math.min(30, Math.floor(4 + this.mass * Math.random()))
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {

View File

@@ -53,6 +53,7 @@ const mech = {
World.add(engine.world, mech.holdConstraint); World.add(engine.world, mech.holdConstraint);
}, },
cycle: 0, cycle: 0,
lastKillCycle: 0,
width: 50, width: 50,
radius: 30, radius: 30,
fillColor: "#fff", //changed by mod piezoelectric plating (damage immunity) fillColor: "#fff", //changed by mod piezoelectric plating (damage immunity)
@@ -652,7 +653,7 @@ const mech = {
throwChargeRate: 0, throwChargeRate: 0,
throwChargeMax: 0, throwChargeMax: 0,
fieldShieldingScale: 0, fieldShieldingScale: 0,
grabRange: 0, fieldRange: 0,
fieldArc: 0, fieldArc: 0,
fieldThreshold: 0, fieldThreshold: 0,
calculateFieldThreshold() { calculateFieldThreshold() {
@@ -669,7 +670,6 @@ const mech = {
mech.holdingMassScale = 0.5; mech.holdingMassScale = 0.5;
mech.throwChargeRate = 2; mech.throwChargeRate = 2;
mech.throwChargeMax = 50; mech.throwChargeMax = 50;
mech.grabRange = 175;
mech.fieldArc = 0.2; //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) mech.fieldArc = 0.2; //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
mech.calculateFieldThreshold(); //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) mech.calculateFieldThreshold(); //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
mech.isBodiesAsleep = true; mech.isBodiesAsleep = true;
@@ -846,7 +846,7 @@ const mech = {
ctx.strokeStyle = "rgba(110, 200, 235, " + (0.6 + 0.2 * Math.random()) + ")" //"#9bd" //"rgba(110, 200, 235, " + (0.5 + 0.1 * Math.random()) + ")" ctx.strokeStyle = "rgba(110, 200, 235, " + (0.6 + 0.2 * Math.random()) + ")" //"#9bd" //"rgba(110, 200, 235, " + (0.5 + 0.1 * Math.random()) + ")"
} }
// const off = 2 * Math.cos(game.cycle * 0.1) // const off = 2 * Math.cos(game.cycle * 0.1)
const range = mech.grabRange - 20; const range = mech.fieldRange - 20;
ctx.beginPath(); ctx.beginPath();
ctx.arc(mech.pos.x, mech.pos.y, range, mech.angle - Math.PI * mech.fieldArc, mech.angle + Math.PI * mech.fieldArc, false); ctx.arc(mech.pos.x, mech.pos.y, range, mech.angle - Math.PI * mech.fieldArc, mech.angle + Math.PI * mech.fieldArc, false);
ctx.lineWidth = 2; ctx.lineWidth = 2;
@@ -876,7 +876,7 @@ const mech = {
ctx.stroke(); ctx.stroke();
}, },
grabPowerUp() { //look for power ups to grab with field grabPowerUp() { //look for power ups to grab with field
const grabPowerUpRange2 = (mech.grabRange + 220) * (mech.grabRange + 220) const grabPowerUpRange2 = (mech.fieldRange + 220) * (mech.fieldRange + 220)
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
const dxP = mech.pos.x - powerUp[i].position.x; const dxP = mech.pos.x - powerUp[i].position.x;
const dyP = mech.pos.y - powerUp[i].position.y; const dyP = mech.pos.y - powerUp[i].position.y;
@@ -959,7 +959,7 @@ const mech = {
pushMobsFacing() { // find mobs in range and in direction looking pushMobsFacing() { // find mobs in range and in direction looking
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
if ( if (
Vector.magnitude(Vector.sub(mob[i].position, player.position)) < mech.grabRange && Vector.magnitude(Vector.sub(mob[i].position, player.position)) < mech.fieldRange &&
mech.lookingAt(mob[i]) && mech.lookingAt(mob[i]) &&
Matter.Query.ray(map, mob[i].position, mech.pos).length === 0 Matter.Query.ray(map, mob[i].position, mech.pos).length === 0
) { ) {
@@ -968,7 +968,7 @@ const mech = {
} }
} }
}, },
pushMobs360(range = mech.grabRange * 0.75) { // find mobs in range in any direction pushMobs360(range = mech.fieldRange * 0.75) { // find mobs in range in any direction
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
if ( if (
Vector.magnitude(Vector.sub(mob[i].position, mech.pos)) < range && Vector.magnitude(Vector.sub(mob[i].position, mech.pos)) < range &&
@@ -983,7 +983,7 @@ const mech = {
// for (let i = 0, len = body.length; i < len; ++i) { // for (let i = 0, len = body.length; i < len; ++i) {
// if ( // if (
// body[i].speed > 12 && body[i].mass > 2 && // body[i].speed > 12 && body[i].mass > 2 &&
// Vector.magnitude(Vector.sub(body[i].position, mech.pos)) < mech.grabRange && // Vector.magnitude(Vector.sub(body[i].position, mech.pos)) < mech.fieldRange &&
// mech.lookingAt(body[i]) && // mech.lookingAt(body[i]) &&
// Matter.Query.ray(map, body[i].position, mech.pos).length === 0 // Matter.Query.ray(map, body[i].position, mech.pos).length === 0
// ) { // ) {
@@ -991,7 +991,7 @@ const mech = {
// } // }
// } // }
// }, // },
// pushBody360(range = mech.grabRange * 0.75) { // push all body in range and in direction looking // pushBody360(range = mech.fieldRange * 0.75) { // push all body in range and in direction looking
// for (let i = 0, len = body.length; i < len; ++i) { // for (let i = 0, len = body.length; i < len; ++i) {
// if ( // if (
// body[i].speed > 12 && body[i].mass > 2 && // body[i].speed > 12 && body[i].mass > 2 &&
@@ -1004,7 +1004,7 @@ const mech = {
// } // }
// } // }
// }, // },
lookForPickUp(range = mech.grabRange) { //find body to pickup lookForPickUp(range = mech.fieldRange) { //find body to pickup
mech.fieldMeter -= mech.fieldRegen; mech.fieldMeter -= mech.fieldRegen;
const grabbing = { const grabbing = {
targetIndex: null, targetIndex: null,
@@ -1126,7 +1126,7 @@ const mech = {
description: "use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 1px;'>stop time</strong><br><em>can fire bullets while field is active</em>", description: "use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 1px;'>stop time</strong><br><em>can fire bullets while field is active</em>",
effect: () => { effect: () => {
mech.fieldFire = true; mech.fieldFire = true;
mech.grabRange = 130 // mech.fieldRange = 130
mech.isBodiesAsleep = false; mech.isBodiesAsleep = false;
mech.hold = function () { mech.hold = function () {
if (mech.isHolding) { if (mech.isHolding) {
@@ -1192,9 +1192,9 @@ const mech = {
description: "use <strong class='color-f'>energy</strong> to emit <strong class='color-d'>damaging</strong> plasma<br><em>effective at close range</em>", description: "use <strong class='color-f'>energy</strong> to emit <strong class='color-d'>damaging</strong> plasma<br><em>effective at close range</em>",
effect: () => { effect: () => {
// mech.fieldShieldingScale = 2; // mech.fieldShieldingScale = 2;
// mech.grabRange = 125; // mech.fieldRange = 125;
mech.fieldArc = 0.1 //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) // mech.fieldArc = 0.1 //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
mech.calculateFieldThreshold(); //run after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) // mech.calculateFieldThreshold(); //run after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
mech.hold = function () { mech.hold = function () {
if (mech.isHolding) { if (mech.isHolding) {
mech.drawHold(mech.holdingTarget); mech.drawHold(mech.holdingTarget);
@@ -1206,11 +1206,11 @@ const mech = {
mech.fieldMeter -= DRAIN; mech.fieldMeter -= DRAIN;
mech.grabPowerUp(); mech.grabPowerUp();
mech.lookForPickUp(); mech.lookForPickUp();
mech.pushMobs360(130); mech.pushMobs360();
//calculate laser collision //calculate laser collision
let best; let best;
let range = 80 + (mech.crouch ? 500 : 300) * Math.sqrt(Math.random()) //+ 100 * Math.sin(mech.cycle * 0.3); let range = mech.fieldRange * 0.5 + (mech.crouch ? 500 : 300) * Math.sqrt(Math.random()) //+ 100 * Math.sin(mech.cycle * 0.3);
const dir = mech.angle // + 0.04 * (Math.random() - 0.5) const dir = mech.angle // + 0.04 * (Math.random() - 0.5)
const path = [{ const path = [{
x: mech.pos.x + 20 * Math.cos(dir), x: mech.pos.x + 20 * Math.cos(dir),
@@ -1337,7 +1337,7 @@ const mech = {
ctx.stroke(); ctx.stroke();
//draw shield around player //draw shield around player
ctx.beginPath(); ctx.beginPath();
ctx.arc(mech.pos.x, mech.pos.y, 110, 0, 2 * Math.PI); ctx.arc(mech.pos.x, mech.pos.y, mech.fieldRange * 0.75, 0, 2 * Math.PI);
ctx.fillStyle = "rgba(255,0,255,0.05)" ctx.fillStyle = "rgba(255,0,255,0.05)"
ctx.fill(); ctx.fill();
// mech.pushBody360(100); //disabled because doesn't work at short range // mech.pushBody360(100); //disabled because doesn't work at short range
@@ -1356,6 +1356,7 @@ const mech = {
{ {
name: "negative mass field", name: "negative mass field",
description: "use <strong class='color-f'>energy</strong> to nullify &nbsp; <strong style='letter-spacing: 12px;'>gravity</strong><br><strong>launch</strong> larger blocks at much higher speeds", description: "use <strong class='color-f'>energy</strong> to nullify &nbsp; <strong style='letter-spacing: 12px;'>gravity</strong><br><strong>launch</strong> larger blocks at much higher speeds",
fieldDrawRadius: 0,
effect: () => { effect: () => {
mech.fieldFire = true; mech.fieldFire = true;
mech.throwChargeRate = 3; mech.throwChargeRate = 3;
@@ -1371,14 +1372,14 @@ const mech = {
const DRAIN = 0.00035 const DRAIN = 0.00035
if (mech.fieldMeter > DRAIN) { if (mech.fieldMeter > DRAIN) {
mech.grabPowerUp(); mech.grabPowerUp();
mech.lookForPickUp(150); mech.lookForPickUp();
mech.pushMobs360(150); mech.pushMobs360();
//look for nearby objects to make zero-g //look for nearby objects to make zero-g
function zeroG(who, mag = 1.06) { function zeroG(who, mag = 1.06) {
for (let i = 0, len = who.length; i < len; ++i) { for (let i = 0, len = who.length; i < len; ++i) {
sub = Vector.sub(who[i].position, mech.pos); sub = Vector.sub(who[i].position, mech.pos);
dist = Vector.magnitude(sub); dist = Vector.magnitude(sub);
if (dist < mech.grabRange) { if (dist < mech.fieldRange) {
who[i].force.y -= who[i].mass * (game.g * mag); //add a bit more then standard gravity who[i].force.y -= who[i].mass * (game.g * mag); //add a bit more then standard gravity
} }
} }
@@ -1388,18 +1389,18 @@ const mech = {
if (keys[83] || keys[40]) { //down if (keys[83] || keys[40]) { //down
player.force.y -= 0.5 * player.mass * mech.gravity; player.force.y -= 0.5 * player.mass * mech.gravity;
mech.grabRange = mech.grabRange * 0.97 + 400 * 0.03; this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 400 * 0.03;
zeroG(powerUp, 0.7); zeroG(powerUp, 0.7);
zeroG(body, 0.7); zeroG(body, 0.7);
} else if (keys[87] || keys[38]) { //up } else if (keys[87] || keys[38]) { //up
mech.fieldMeter -= 5 * DRAIN; mech.fieldMeter -= 5 * DRAIN;
mech.grabRange = mech.grabRange * 0.97 + 850 * 0.03; this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 850 * 0.03;
player.force.y -= 1.45 * player.mass * mech.gravity; player.force.y -= 1.45 * player.mass * mech.gravity;
zeroG(powerUp, 1.38); zeroG(powerUp, 1.38);
zeroG(body, 1.38); zeroG(body, 1.38);
} else { } else {
mech.fieldMeter -= DRAIN; mech.fieldMeter -= DRAIN;
mech.grabRange = mech.grabRange * 0.97 + 650 * 0.03; this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 650 * 0.03;
player.force.y -= 1.07 * player.mass * mech.gravity; // slow upward drift player.force.y -= 1.07 * player.mass * mech.gravity; // slow upward drift
zeroG(powerUp); zeroG(powerUp);
zeroG(body); zeroG(body);
@@ -1420,7 +1421,7 @@ const mech = {
//draw zero-G range //draw zero-G range
ctx.beginPath(); ctx.beginPath();
ctx.arc(mech.pos.x, mech.pos.y, mech.grabRange, 0, 2 * Math.PI); ctx.arc(mech.pos.x, mech.pos.y, this.fieldDrawRadius, 0, 2 * Math.PI);
ctx.fillStyle = "#f5f5ff"; ctx.fillStyle = "#f5f5ff";
ctx.globalCompositeOperation = "difference"; ctx.globalCompositeOperation = "difference";
ctx.fill(); ctx.fill();
@@ -1431,10 +1432,10 @@ const mech = {
} }
} else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released } else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released
mech.pickUp(); mech.pickUp();
mech.grabRange = 0 this.fieldDrawRadius = 0
} else { } 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) 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.grabRange = 0 this.fieldDrawRadius = 0
} }
mech.drawFieldMeter() mech.drawFieldMeter()
} }
@@ -1454,29 +1455,29 @@ const mech = {
mech.throwBlock(); mech.throwBlock();
} else if (((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle && mech.fieldMeter > 0)) { //not hold but field button is pressed } else if (((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle && mech.fieldMeter > 0)) { //not hold but field button is pressed
mech.grabPowerUp(); mech.grabPowerUp();
mech.lookForPickUp(180); mech.lookForPickUp();
} else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released } else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
mech.pickUp(); mech.pickUp();
} else { } 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) 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.fieldMeter > 0.1 && mech.fieldCDcycle < mech.cycle) { if (mech.fieldMeter > 0.1 && mech.fieldCDcycle < mech.cycle) {
const grabRange1 = 90 + 60 * Math.sin(mech.cycle / 23) const fieldRange1 = (0.55 + 0.35 * Math.sin(mech.cycle / 23)) * mech.fieldRange
const grabRange2 = 85 + 70 * Math.sin(mech.cycle / 37) const fieldRange2 = (0.5 + 0.4 * Math.sin(mech.cycle / 37)) * mech.fieldRange
const grabRange3 = 80 + 80 * Math.sin(mech.cycle / 47) const fieldRange3 = (0.45 + 0.45 * Math.sin(mech.cycle / 47)) * mech.fieldRange
const netGrabRange = Math.max(grabRange1, grabRange2, grabRange3) const netfieldRange = Math.max(fieldRange1, fieldRange2, fieldRange3)
ctx.fillStyle = "rgba(110,170,200," + (0.04 + mech.fieldMeter * (0.12 + 0.13 * Math.random())) + ")"; ctx.fillStyle = "rgba(110,170,200," + (0.04 + mech.fieldMeter * (0.12 + 0.13 * Math.random())) + ")";
ctx.beginPath(); ctx.beginPath();
ctx.arc(mech.pos.x, mech.pos.y, grabRange1, 0, 2 * Math.PI); ctx.arc(mech.pos.x, mech.pos.y, fieldRange1, 0, 2 * Math.PI);
ctx.fill(); ctx.fill();
ctx.beginPath(); ctx.beginPath();
ctx.arc(mech.pos.x, mech.pos.y, grabRange2, 0, 2 * Math.PI); ctx.arc(mech.pos.x, mech.pos.y, fieldRange2, 0, 2 * Math.PI);
ctx.fill(); ctx.fill();
ctx.beginPath(); ctx.beginPath();
ctx.arc(mech.pos.x, mech.pos.y, grabRange3, 0, 2 * Math.PI); ctx.arc(mech.pos.x, mech.pos.y, fieldRange3, 0, 2 * Math.PI);
ctx.fill(); ctx.fill();
mech.pushMobs360(netGrabRange); mech.pushMobs360(netfieldRange);
// mech.pushBody360(netGrabRange); //can't throw block when pushhing blocks away // mech.pushBody360(netfieldRange); //can't throw block when pushhing blocks away
} }
mech.drawFieldMeter() mech.drawFieldMeter()
} }
@@ -1515,7 +1516,7 @@ const mech = {
name: "phase decoherence field", name: "phase decoherence field",
description: "become <strong>intangible</strong> and <strong>invisible</strong><br>drains <strong class='color-f'>energy</strong> as you move", description: "become <strong>intangible</strong> and <strong>invisible</strong><br>drains <strong class='color-f'>energy</strong> as you move",
effect: () => { effect: () => {
// mech.grabRange = 230 // mech.fieldRange = 230
mech.hold = function () { mech.hold = function () {
mech.isStealth = false //isStealth disables most uses of foundPlayer() mech.isStealth = false //isStealth disables most uses of foundPlayer()
player.collisionFilter.mask = cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield //normal collisions player.collisionFilter.mask = cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield //normal collisions
@@ -1532,7 +1533,7 @@ const mech = {
player.collisionFilter.mask = cat.map player.collisionFilter.mask = cat.map
ctx.beginPath(); ctx.beginPath();
ctx.arc(mech.pos.x, mech.pos.y, mech.grabRange, 0, 2 * Math.PI); ctx.arc(mech.pos.x, mech.pos.y, mech.fieldRange, 0, 2 * Math.PI);
ctx.globalCompositeOperation = "destination-in"; //in or atop ctx.globalCompositeOperation = "destination-in"; //in or atop
ctx.fillStyle = `rgba(255,255,255,${mech.fieldMeter*0.5})`; ctx.fillStyle = `rgba(255,255,255,${mech.fieldMeter*0.5})`;
ctx.fill(); ctx.fill();
@@ -1542,7 +1543,7 @@ const mech = {
ctx.stroke(); ctx.stroke();
mech.grabPowerUp(); mech.grabPowerUp();
mech.lookForPickUp(110); mech.lookForPickUp();
} else { } else {
mech.fieldCDcycle = mech.cycle + 120; mech.fieldCDcycle = mech.cycle + 120;
} }
@@ -1563,7 +1564,7 @@ const mech = {
// mech.fieldText(); // mech.fieldText();
// mech.setHoldDefaults(); // mech.setHoldDefaults();
// mech.hackProgress = 0; // mech.hackProgress = 0;
// // mech.grabRange = 230 // // mech.fieldRange = 230
// mech.hold = function () { // mech.hold = function () {
// mech.isStealth = false //isStealth is checked in mob foundPlayer() // mech.isStealth = false //isStealth is checked in mob foundPlayer()
// player.collisionFilter.mask = 0x010011 // player.collisionFilter.mask = 0x010011
@@ -1580,7 +1581,7 @@ const mech = {
// //try to hack a mob // //try to hack a mob
// for (let i = 0, len = mob.length; i < len; ++i) { // for (let i = 0, len = mob.length; i < len; ++i) {
// if ( // if (
// Vector.magnitude(Vector.sub(mob[i].position, this.pos)) < this.grabRange && // Vector.magnitude(Vector.sub(mob[i].position, this.pos)) < this.fieldRange &&
// this.lookingAt(mob[i]) && // this.lookingAt(mob[i]) &&
// Matter.Query.ray(map, mob[i].position, this.pos).length === 0 // Matter.Query.ray(map, mob[i].position, this.pos).length === 0
// ) { // ) {
@@ -1594,7 +1595,7 @@ const mech = {
// } // }
// } else { //hold the mob still // } else { //hold the mob still
// mech.hackProgress++ // mech.hackProgress++
// range = this.grabRange * 0.9 // range = this.fieldRange * 0.9
// Matter.Body.setPosition(mob[i], { // Matter.Body.setPosition(mob[i], {
// x: mech.pos.x + range * Math.cos(mech.angle), // x: mech.pos.x + range * Math.cos(mech.angle),
// y: mech.pos.y + range * Math.sin(mech.angle), // y: mech.pos.y + range * Math.sin(mech.angle),

View File

@@ -16,11 +16,23 @@ canvas {
select { select {
font-size: 0.8em; font-size: 0.8em;
border: 1px #333 solid;
border-radius: 6px;
/* margin-bottom: -20px; */ /* margin-bottom: -20px; */
/* position: "relative"; /* position: "relative";
top: "-15px"; */ top: "-15px"; */
} }
input {
/* font-family: Monaco, monospace; */
padding: 0px 4px;
font-size: 0.8em;
border: 1px #333 solid;
border-radius: 4px;
/* margin: 0.2em; */
width: 38px;
}
a { a {
text-decoration: none; text-decoration: none;
color: #08c; color: #08c;
@@ -154,7 +166,7 @@ summary {
padding: 10px; padding: 10px;
line-height: 170%; line-height: 170%;
/* border-radius: 6px; */ /* border-radius: 6px; */
border: 2px #000 solid; border: 2px #333 solid;
background-color: #fff; background-color: #fff;
font-size: 0.65em; font-size: 0.65em;
} }
@@ -185,7 +197,7 @@ summary {
padding: 10px; padding: 10px;
line-height: 170%; line-height: 170%;
/* border-radius: 6px; */ /* border-radius: 6px; */
border: 2px #000 solid; border: 2px #333 solid;
background-color: #fff; background-color: #fff;
line-height: 170%; line-height: 170%;

10
todo.md
View File

@@ -1,10 +1,6 @@
make a var that tracks the last time a kill was made <!--
mod - squirrel cage rotor - effect is only active for 10 seconds after killing a mob
turn this off in game.checks()
mod - do more damage for 10 seconds after killing a mob
mod - energy or health regeneration for 10 seconds after killing a mob
run this effect in game.checks()
mod - nano scale field makes spores instead of drones
mod - mines - fire something instead of needles on activation mod - mines - fire something instead of needles on activation
foam?, flak?, vacuum bomb, super balls foam?, flak?, vacuum bomb, super balls
@@ -154,4 +150,4 @@ game mechanics
map zones map zones
water water
low friction ground low friction ground
bouncy ground bouncy ground -->