mod- pulse

gun: pulse is now a mod for laser
  mod: beam splitter applies to pulse

difficulty balancing
  (this needs to be done as more mods are added to the game to prevent power creep)
  all modes are a bit harder
    if you used to play why, try the new hard
    if you used to play hard try the new normal
  power ups drop more often from bosses on all modes
This commit is contained in:
landgreen
2020-10-25 15:09:55 -07:00
parent a5f79bf742
commit c7048c9324
9 changed files with 212 additions and 233 deletions

View File

@@ -99,10 +99,10 @@
<div style="line-height: 150%;" id="details-div"> <div style="line-height: 150%;" id="details-div">
<label for="difficulty-select" title="effects: number of mobs, damage done by mobs, damage done to mobs, mob speed, heal effects">combat difficulty:</label> <label for="difficulty-select" title="effects: number of mobs, damage done by mobs, damage done to mobs, mob speed, heal effects">combat difficulty:</label>
<select name="difficulty-select" id="difficulty-select"> <select name="difficulty-select" id="difficulty-select">
<option value="0">easy</option> <option value="1">easy</option>
<option value="1" selected>normal</option> <option value="2" selected>normal</option>
<option value="2">hard</option> <option value="4">hard</option>
<option value="4">why...</option> <option value="6">why?</option>
</select> </select>
<br> <br>
<label for="community-maps" title="adds in maps written by n-gon player: Francois">include community maps:</label> <label for="community-maps" title="adds in maps written by n-gon player: Francois">include community maps:</label>

View File

@@ -3227,153 +3227,148 @@ const b = {
} }
}, },
firePulse() { firePulse() {
//calculate laser collision mech.fireCDcycle = mech.cycle + Math.floor((mod.isPulseAim ? 25 : 50) * b.fireCD); // cool down
let best, energy, explosionRange; let energy = 0.27 * Math.min(mech.energy, 1.5)
let range = 3000 mech.energy -= energy * mod.isLaserDiode
const path = [{
x: mech.pos.x + 20 * Math.cos(mech.angle),
y: mech.pos.y + 20 * Math.sin(mech.angle)
},
{
x: mech.pos.x + range * Math.cos(mech.angle),
y: mech.pos.y + range * Math.sin(mech.angle)
}
];
const vertexCollision = function (v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices;
const len = vertices.length - 1;
for (let j = 0; j < len; j++) {
results = game.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
if (results.onLine1 && results.onLine2) {
const dx = v1.x - results.x;
const dy = v1.y - results.y;
const dist2 = dx * dx + dy * dy;
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
best = {
x: results.x,
y: results.y,
dist2: dist2,
who: domain[i],
v1: vertices[j],
v2: vertices[j + 1]
};
}
}
}
results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
if (results.onLine1 && results.onLine2) {
const dx = v1.x - results.x;
const dy = v1.y - results.y;
const dist2 = dx * dx + dy * dy;
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
best = {
x: results.x,
y: results.y,
dist2: dist2,
who: domain[i],
v1: vertices[0],
v2: vertices[len]
};
}
}
}
};
//check for collisions
best = {
x: null,
y: null,
dist2: Infinity,
who: null,
v1: null,
v2: null
};
if (mod.isPulseAim) { //find mobs in line of sight
let dist = 2200
energy = 0.23 * Math.min(mech.energy, 1.5)
explosionRange = 1680 * energy
for (let i = 0, len = mob.length; i < len; i++) {
const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position))
if (explosionRange < newDist &&
newDist < dist &&
Matter.Query.ray(map, path[0], mob[i].position).length === 0 &&
Matter.Query.ray(body, path[0], mob[i].position).length === 0) {
dist = newDist
best.who = mob[i]
path[path.length - 1] = mob[i].position
}
}
}
if (!best.who) {
vertexCollision(path[0], path[1], mob);
vertexCollision(path[0], path[1], map);
vertexCollision(path[0], path[1], body);
if (best.dist2 != Infinity) { //if hitting something
path[path.length - 1] = {
x: best.x,
y: best.y
};
}
}
if (mod.isPulseAim) {
mech.energy -= energy * mod.isLaserDiode
if (best.who) b.explosion(path[1], explosionRange, true)
mech.fireCDcycle = mech.cycle + Math.floor(25 * b.fireCD); // cool down
} else {
energy = 0.27 * Math.min(mech.energy, 1.5)
mech.energy -= energy * mod.isLaserDiode
explosionRange = 1560 * energy
if (best.who) b.explosion(path[1], explosionRange, true)
mech.fireCDcycle = mech.cycle + Math.floor(50 * b.fireCD); // cool down
}
if (mod.isPulseStun) {
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);
ctx.lineTo(path[1].x, path[1].y);
ctx.strokeStyle = "rgba(255,0,0,0.13)"
ctx.lineWidth = 60 * energy / 0.2
ctx.stroke();
ctx.strokeStyle = "rgba(255,0,0,0.2)"
ctx.lineWidth = 18
ctx.stroke();
ctx.strokeStyle = "#f00";
ctx.lineWidth = 4
ctx.stroke();
//draw little dots along the laser path if (mod.beamSplitter) {
const sub = Vector.sub(path[1], path[0]) energy *= 0.7
const mag = Vector.magnitude(sub) b.pulse(energy, mech.angle)
for (let i = 0, len = Math.floor(mag * 0.03 * energy / 0.2); i < len; i++) { for (let i = 1; i < 1 + mod.beamSplitter; i++) {
const dist = Math.random() energy *= 0.9
game.drawList.push({ b.pulse(energy, mech.angle - i * 0.35)
x: path[0].x + sub.x * dist + 13 * (Math.random() - 0.5), b.pulse(energy, mech.angle + i * 0.35)
y: path[0].y + sub.y * dist + 13 * (Math.random() - 0.5), }
radius: 1 + 4 * Math.random(), } else {
color: "rgba(255,0,0,0.5)", b.pulse(energy, mech.angle)
time: Math.floor(2 + 33 * Math.random() * Math.random())
});
} }
}, },
}, },
],
pulse(energy, angle = mech.angle) {
let best;
let explosionRange = 1560 * energy
let range = 3000
const path = [{
x: mech.pos.x + 20 * Math.cos(angle),
y: mech.pos.y + 20 * Math.sin(angle)
},
{
x: mech.pos.x + range * Math.cos(angle),
y: mech.pos.y + range * Math.sin(angle)
}
];
const vertexCollision = function (v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices;
const len = vertices.length - 1;
for (let j = 0; j < len; j++) {
results = game.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
if (results.onLine1 && results.onLine2) {
const dx = v1.x - results.x;
const dy = v1.y - results.y;
const dist2 = dx * dx + dy * dy;
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
best = {
x: results.x,
y: results.y,
dist2: dist2,
who: domain[i],
v1: vertices[j],
v2: vertices[j + 1]
};
}
}
}
results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
if (results.onLine1 && results.onLine2) {
const dx = v1.x - results.x;
const dy = v1.y - results.y;
const dist2 = dx * dx + dy * dy;
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
best = {
x: results.x,
y: results.y,
dist2: dist2,
who: domain[i],
v1: vertices[0],
v2: vertices[len]
};
}
}
}
};
//check for collisions
best = {
x: null,
y: null,
dist2: Infinity,
who: null,
v1: null,
v2: null
};
if (mod.isPulseAim) { //find mobs in line of sight
let dist = 2200
for (let i = 0, len = mob.length; i < len; i++) {
const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position))
if (explosionRange < newDist &&
newDist < dist &&
Matter.Query.ray(map, path[0], mob[i].position).length === 0 &&
Matter.Query.ray(body, path[0], mob[i].position).length === 0) {
dist = newDist
best.who = mob[i]
path[path.length - 1] = mob[i].position
}
}
}
if (!best.who) {
vertexCollision(path[0], path[1], mob);
vertexCollision(path[0], path[1], map);
vertexCollision(path[0], path[1], body);
if (best.dist2 != Infinity) { //if hitting something
path[path.length - 1] = {
x: best.x,
y: best.y
};
}
}
if (best.who) b.explosion(path[1], explosionRange, true)
// { if (mod.isPulseStun) {
// name: "pulse", const range = 100 + 2000 * energy
// description: "convert <strong>25%</strong> of your <strong class='color-f'>energy</strong> into a pulsed laser<br>instantly initiates a fusion <strong class='color-e'>explosion</strong>", for (let i = 0, len = mob.length; i < len; ++i) {
// ammo: 0, if (mob[i].alive && !mob[i].isShielded) {
// ammoPack: Infinity, dist = Vector.magnitude(Vector.sub(path[1], mob[i].position)) - mob[i].radius;
// have: false, if (dist < range) mobs.statusStun(mob[i], 30 + Math.floor(energy * 60))
// fire() { }
}
}
//draw laser beam
ctx.beginPath();
ctx.moveTo(path[0].x, path[0].y);
ctx.lineTo(path[1].x, path[1].y);
ctx.strokeStyle = "rgba(255,0,0,0.13)"
ctx.lineWidth = 60 * energy / 0.2
ctx.stroke();
ctx.strokeStyle = "rgba(255,0,0,0.2)"
ctx.lineWidth = 18
ctx.stroke();
ctx.strokeStyle = "#f00";
ctx.lineWidth = 4
ctx.stroke();
// } //draw little dots along the laser path
// }, const sub = Vector.sub(path[1], path[0])
] const mag = Vector.magnitude(sub)
for (let i = 0, len = Math.floor(mag * 0.03 * energy / 0.2); i < len; i++) {
const dist = Math.random()
game.drawList.push({
x: path[0].x + sub.x * dist + 13 * (Math.random() - 0.5),
y: path[0].y + sub.y * dist + 13 * (Math.random() - 0.5),
radius: 1 + 4 * Math.random(),
color: "rgba(255,0,0,0.5)",
time: Math.floor(2 + 33 * Math.random() * Math.random())
});
}
}
}; };

View File

@@ -127,8 +127,7 @@ const game = {
delta: 1000 / 60, //speed of game engine //looks like it has to be 16 to match player input delta: 1000 / 60, //speed of game engine //looks like it has to be 16 to match player input
buttonCD: 0, buttonCD: 0,
levelsCleared: 0, levelsCleared: 0,
difficultyMode: 1, difficultyMode: 2, //normal difficulty is 2
isEasyMode: false,
difficulty: 0, difficulty: 0,
dmgScale: null, //set in levels.setDifficulty dmgScale: null, //set in levels.setDifficulty
healScale: 1, healScale: 1,
@@ -485,20 +484,18 @@ const game = {
level.levelsCleared = 0; level.levelsCleared = 0;
//resetting difficulty //resetting difficulty
game.dmgScale = 1; game.dmgScale = 0; //increases in level.difficultyIncrease
b.dmgScale = 0.7; b.dmgScale = 1; //decreases in level.difficultyIncrease
game.accelScale = 1; game.accelScale = 1;
game.lookFreqScale = 1; game.lookFreqScale = 1;
game.CDScale = 1; game.CDScale = 1;
game.difficulty = 0; game.difficulty = 0;
game.difficultyMode = Number(document.getElementById("difficulty-select").value) game.difficultyMode = Number(document.getElementById("difficulty-select").value)
build.isCustomSelection = false; build.isCustomSelection = false;
if (game.difficultyMode === 0) { // if (game.difficultyMode > 2) {
game.isEasyMode = true; // level.difficultyIncrease(game.difficultyMode)
game.difficultyMode = 1 // level.difficultyIncrease(game.difficultyMode)
level.difficultyDecrease(6); //if this stops being -6 change in build.calculateCustomDifficulty() // }
}
if (game.difficultyMode > 1) level.difficultyIncrease(3)
game.clearNow = true; game.clearNow = true;
document.getElementById("text-log").style.opacity = 0; document.getElementById("text-log").style.opacity = 0;
@@ -687,7 +684,7 @@ const game = {
if (mech.energy > mech.maxEnergy) mech.energy = mech.maxEnergy + (mech.energy - mech.maxEnergy) * 0.75 if (mech.energy > mech.maxEnergy) mech.energy = mech.maxEnergy + (mech.energy - mech.maxEnergy) * 0.75
if (mech.pos.y > game.fallHeight) { // if 4000px deep if (mech.pos.y > game.fallHeight) { // if 4000px deep
if (game.difficultyMode > 2) { if (game.difficultyMode > 4) {
mech.death(); mech.death();
} else { } else {
@@ -726,8 +723,7 @@ const game = {
}); });
} }
} }
if (game.difficultyMode === 2) mech.damage(0.25); mech.damage(0.1 * game.difficultyMode);
if (game.difficultyMode === 1) mech.damage(0.1);
mech.energy = 0.01; mech.energy = 0.01;
} }
} }
@@ -753,7 +749,7 @@ const game = {
let i = who.length; let i = who.length;
while (i--) { while (i--) {
if (who[i].position.y > game.fallHeight) { if (who[i].position.y > game.fallHeight) {
if (save && game.difficultyMode < 3) { if (save && game.difficultyMode < 5) {
Matter.Body.setVelocity(who[i], { Matter.Body.setVelocity(who[i], {
x: 0, x: 0,
y: 0 y: 0

View File

@@ -188,7 +188,7 @@ const build = {
<br>position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)}) &nbsp; velocity: (${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)}) <br>position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)}) &nbsp; velocity: (${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)})
<br>mouse: (${game.mouseInGame.x.toFixed(1)}, ${game.mouseInGame.y.toFixed(1)}) &nbsp; mass: ${player.mass.toFixed(1)} <br>mouse: (${game.mouseInGame.x.toFixed(1)}, ${game.mouseInGame.y.toFixed(1)}) &nbsp; mass: ${player.mass.toFixed(1)}
<br> <br>
<br>level: ${level.levelsCleared} - ${level.levels[level.onLevel]} (${level.difficultyText()}) &nbsp; ${mech.cycle} cycles <br>level: ${level.levelsCleared} - ${level.levelsCleared===0?"intro":level.levels[level.onLevel]} (${level.difficultyText()}) &nbsp; ${mech.cycle} cycles
<br>${mob.length} mobs, &nbsp; ${body.length} blocks, &nbsp; ${bullet.length} bullets, &nbsp; ${powerUp.length} power ups <br>${mob.length} mobs, &nbsp; ${body.length} blocks, &nbsp; ${bullet.length} bullets, &nbsp; ${powerUp.length} power ups
<br>damage difficulty scale: ${(b.dmgScale*100).toFixed(2) }% <br>damage difficulty scale: ${(b.dmgScale*100).toFixed(2) }%
<br>harm difficulty scale: ${(game.dmgScale*100).toFixed(0)}% <br>harm difficulty scale: ${(game.dmgScale*100).toFixed(0)}%
@@ -318,10 +318,10 @@ const build = {
<div>starting level: <input id='starting-level' type="number" step="1" value="0" min="0" max="99"></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="1">easy</option>
<option value="1" selected>normal</option> <option value="2" selected>normal</option>
<option value="2">hard</option> <option value="4">hard</option>
<option value="4">why...</option> <option value="6">why?</option>
</select> </select>
</div>` </div>`
for (let i = 0, len = mech.fieldUpgrades.length; i < len; i++) { for (let i = 0, len = mech.fieldUpgrades.length; i < len; i++) {
@@ -891,7 +891,7 @@ if (localSettings) {
} else { } else {
localSettings = { localSettings = {
isCommunityMaps: false, isCommunityMaps: false,
difficultyMode: '1', difficultyMode: '2',
fpsCapDefault: 'max', fpsCapDefault: 'max',
runCount: 0, runCount: 0,
levelsClearedLastGame: 0, levelsClearedLastGame: 0,

View File

@@ -831,13 +831,13 @@ const level = {
"Last time was a simulation. Is this one a simulation too?", "Last time was a simulation. Is this one a simulation too?",
) )
} }
if (game.difficultyMode < 2 && localSettings.levelsClearedLastGame > 10) { //too easy if (game.difficultyMode < 4 && localSettings.levelsClearedLastGame > 10) { //too easy
say.push( say.push(
"That felt too easy.<br>Maybe I should increase the difficulty of the simulation.", "That felt too easy.<br>Maybe I should increase the difficulty of the simulation.",
"That was fun, but maybe I should increase the difficulty of the simulation.", "That was fun, but maybe I should increase the difficulty of the simulation.",
"I should increase the difficulty of the simulation, that didn't feel realistic.", "I should increase the difficulty of the simulation, that didn't feel realistic.",
) )
} else if (game.difficultyMode > 1 && localSettings.levelsClearedLastGame > 10) { //great run on a hard or why } else if (game.difficultyMode > 3 && localSettings.levelsClearedLastGame > 10) { //great run on a hard or why
say.push( say.push(
"What do I do after I escape?", "What do I do after I escape?",
"I'm almost ready to stop these simulations and actually escape.", "I'm almost ready to stop these simulations and actually escape.",
@@ -3836,35 +3836,35 @@ const level = {
difficultyIncrease(num = 1) { difficultyIncrease(num = 1) {
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
game.difficulty++ game.difficulty++
game.dmgScale += 0.38; //damage done by mobs increases each level
b.dmgScale *= 0.93; //damage done by player decreases each level b.dmgScale *= 0.93; //damage done by player decreases each level
if (game.accelScale < 5) game.accelScale *= 1.02 //mob acceleration increases each level if (game.accelScale < 5) game.accelScale *= 1.02 //mob acceleration increases each level
if (game.lookFreqScale > 0.2) game.lookFreqScale *= 0.98 //mob cycles between looks decreases each level if (game.lookFreqScale > 0.2) game.lookFreqScale *= 0.98 //mob cycles between looks decreases each level
if (game.CDScale > 0.2) game.CDScale *= 0.97 //mob CD time decreases each level if (game.CDScale > 0.2) game.CDScale *= 0.97 //mob CD time decreases each level
} }
game.dmgScale = 0.38 * game.difficulty //damage done by mobs increases each level
game.healScale = 1 / (1 + game.difficulty * 0.06) //a higher denominator makes for lower heals // mech.health += heal * game.healScale; game.healScale = 1 / (1 + game.difficulty * 0.06) //a higher denominator makes for lower heals // mech.health += heal * game.healScale;
}, },
difficultyDecrease(num = 1) { //used in easy mode for game.reset() difficultyDecrease(num = 1) { //used in easy mode for game.reset()
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
game.difficulty-- game.difficulty--
game.dmgScale -= 0.38; //damage done by mobs increases each level
if (game.dmgScale < 0.1) game.dmgScale = 0.1;
b.dmgScale /= 0.93; //damage done by player decreases each level b.dmgScale /= 0.93; //damage done by player decreases each level
if (game.accelScale > 0.2) game.accelScale /= 1.02 //mob acceleration increases each level if (game.accelScale > 0.2) game.accelScale /= 1.02 //mob acceleration increases each level
if (game.lookFreqScale < 5) game.lookFreqScale /= 0.98 //mob cycles between looks decreases each level if (game.lookFreqScale < 5) game.lookFreqScale /= 0.98 //mob cycles between looks decreases each level
if (game.CDScale < 5) game.CDScale /= 0.97 //mob CD time decreases each level if (game.CDScale < 5) game.CDScale /= 0.97 //mob CD time decreases each level
} }
if (game.difficulty < 1) game.difficulty = 0; if (game.difficulty < 1) game.difficulty = 0;
game.dmgScale = 0.38 * game.difficulty //damage done by mobs increases each level
if (game.dmgScale < 0.1) game.dmgScale = 0.1;
game.healScale = 1 / (1 + game.difficulty * 0.06) game.healScale = 1 / (1 + game.difficulty * 0.06)
}, },
difficultyText(mode = document.getElementById("difficulty-select").value) { difficultyText() {
if (mode === "0") { if (game.difficultyMode === 1) {
return "easy" return "easy"
} else if (mode === "1") { } else if (game.difficultyMode === 2) {
return "normal" return "normal"
} else if (mode === "2") { } else if (game.difficultyMode === 4) {
return "hard" return "hard"
} else if (mode === "4") { } else if (game.difficultyMode === 6) {
return "why" return "why"
} }
}, },
@@ -3887,7 +3887,6 @@ const level = {
if (level.levelsCleared > level.levels.length * 1.25) level.difficultyIncrease(game.difficultyMode) if (level.levelsCleared > level.levels.length * 1.25) level.difficultyIncrease(game.difficultyMode)
if (level.levelsCleared > level.levels.length * 1.5) level.difficultyIncrease(game.difficultyMode) if (level.levelsCleared > level.levels.length * 1.5) level.difficultyIncrease(game.difficultyMode)
if (level.levelsCleared > level.levels.length * 2) level.difficultyIncrease(game.difficultyMode) if (level.levelsCleared > level.levels.length * 2) level.difficultyIncrease(game.difficultyMode)
if (game.isEasyMode && level.levelsCleared % 2) level.difficultyDecrease(1);
level.bossKilled = false; level.bossKilled = false;
//reset lost mod display //reset lost mod display
for (let i = 0; i < mod.mods.length; i++) { for (let i = 0; i < mod.mods.length; i++) {

View File

@@ -2428,7 +2428,7 @@ const mod = {
maxCount: 9, maxCount: 9,
count: 0, count: 0,
allowed() { allowed() {
return mod.haveGunCheck("laser") && !mod.isWideLaser && !mod.isPulseLaser return mod.haveGunCheck("laser") && !mod.isWideLaser && !mod.isPulseAim
}, },
requires: "laser, not specular reflection", requires: "laser, not specular reflection",
effect() { effect() {
@@ -2482,7 +2482,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return mod.haveGunCheck("laser") && mod.laserReflections < 3 && !mod.beamSplitter && !mod.isWideLaser return mod.haveGunCheck("laser") && mod.laserReflections < 3 && !mod.isWideLaser
}, },
requires: "laser, not specular reflection<br>not beam splitter, not diffuse", requires: "laser, not specular reflection<br>not beam splitter, not diffuse",
effect() { effect() {
@@ -2520,7 +2520,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return mod.isPulseLaser return mod.isPulseLaser && !mod.beamSplitter
}, },
requires: "pulse", requires: "pulse",
effect() { effect() {

View File

@@ -434,7 +434,7 @@ const powerUps = {
} }
}, },
spawnRandomPowerUp(x, y) { //mostly used after mob dies, doesn't always return a power up spawnRandomPowerUp(x, y) { //mostly used after mob dies, doesn't always return a power up
if ((Math.random() * Math.random() - 0.3 > Math.sqrt(mech.health) && !mod.isEnergyHealth) || Math.random() < 0.035) { //spawn heal chance is higher at low health if ((Math.random() * Math.random() - 0.3 > Math.sqrt(mech.health) && !mod.isEnergyHealth) || Math.random() < 0.04) { //spawn heal chance is higher at low health
powerUps.spawn(x, y, "heal"); powerUps.spawn(x, y, "heal");
return; return;
} }
@@ -446,7 +446,7 @@ const powerUps = {
powerUps.spawn(x, y, "gun"); powerUps.spawn(x, y, "gun");
return; return;
} }
if (Math.random() < 0.0027 * (26 - mod.totalCount)) { //a new mod has a low chance for each not acquired mod up to 15 if (Math.random() < 0.0027 * (25 - mod.totalCount)) { //a new mod has a low chance for each not acquired mod up to 15
powerUps.spawn(x, y, "mod"); powerUps.spawn(x, y, "mod");
return; return;
} }
@@ -462,43 +462,30 @@ const powerUps = {
randomPowerUpCounter: 0, randomPowerUpCounter: 0,
spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades
level.bossKilled = true; level.bossKilled = true;
// if (game.difficultyMode === 4) powerUps.spawn(x, y, "mod") //why mode gets a free mod
powerUps.randomPowerUpCounter++; powerUps.randomPowerUpCounter++;
const chanceToFail = Math.max(level.levelsCleared, 10) * 0.1 //1 until level 10, then 1.1, 1.2, 1.3, ... powerUpChance(Math.max(level.levelsCleared, 10) * 0.1)
if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) { powerUps.randomPowerUpCounter += 0.6;
powerUps.randomPowerUpCounter = 0; powerUpChance(Math.max(level.levelsCleared, 6) * 0.1)
spawnPowerUps()
} else { function powerUpChance(chanceToFail) {
spawnHealthAmmo()
}
if (game.difficultyMode === 4) {
powerUps.randomPowerUpCounter + 0.6;
const chanceToFail = Math.max(level.levelsCleared, 6) * 0.1 //1 until level 8
if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) { if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) {
powerUps.randomPowerUpCounter = 0; powerUps.randomPowerUpCounter = 0;
spawnPowerUps() if (mech.fieldMode === 0) {
powerUps.spawn(x, y, "field")
} else if (Math.random() < 0.95) {
powerUps.spawn(x, y, "mod")
} else {
powerUps.spawn(x, y, "gun")
}
} else { } else {
spawnHealthAmmo() if (mech.health < 0.65 && !mod.isEnergyHealth) {
} powerUps.spawn(x, y, "heal");
} powerUps.spawn(x, y, "heal");
} else {
function spawnHealthAmmo() { powerUps.spawn(x, y, "ammo");
if (mech.health < 0.65 && !mod.isEnergyHealth) { powerUps.spawn(x, y, "ammo");
powerUps.spawn(x, y, "heal"); }
powerUps.spawn(x, y, "heal");
} else {
powerUps.spawn(x, y, "ammo");
powerUps.spawn(x, y, "ammo");
}
}
function spawnPowerUps() {
if (mech.fieldMode === 0) {
powerUps.spawn(x, y, "field")
} else if (Math.random() < 0.95) {
powerUps.spawn(x, y, "mod")
} else {
powerUps.spawn(x, y, "gun")
} }
} }
}, },
@@ -517,7 +504,7 @@ const powerUps = {
}, },
spawnStartingPowerUps(x, y) { //used for map specific power ups, mostly to give player a starting gun spawnStartingPowerUps(x, y) { //used for map specific power ups, mostly to give player a starting gun
if (level.levelsCleared < 4) { //runs 4 times on all difficulty levels if (level.levelsCleared < 4) { //runs 4 times on all difficulty levels
if (game.difficultyMode > 1 && level.levelsCleared > 1) powerUps.spawn(x, y, "mod") if (level.levelsCleared > 1) powerUps.spawn(x, y, "mod")
//bonus power ups for clearing runs in the last game //bonus power ups for clearing runs in the last game
if (level.levelsCleared === 0 && !game.isCheating) { if (level.levelsCleared === 0 && !game.isCheating) {

View File

@@ -233,11 +233,11 @@ const spawn = {
me.isBoss = true; me.isBoss = true;
me.frictionAir = 0.01 me.frictionAir = 0.01
me.seeAtDistance2 = 9000000; me.seeAtDistance2 = 9000000;
me.accelMag = 0.00062 * game.accelScale; me.accelMag = 0.00065 * game.accelScale;
Matter.Body.setDensity(me, 0.0006); //normal is 0.001 Matter.Body.setDensity(me, 0.0006); //normal is 0.001
me.collisionFilter.mask = cat.bullet | cat.player me.collisionFilter.mask = cat.bullet | cat.player
me.memory = Infinity; me.memory = Infinity;
me.seePlayerFreq = 60 me.seePlayerFreq = 30
me.lockedOn = null; me.lockedOn = null;
if (vertices === 9) { if (vertices === 9) {

View File

@@ -1,17 +1,23 @@
gun: pulse is now a mod for laser gun: pulse is now a mod for laser
mod: beam splitter applies to pulse
difficulty balancing
(this needs to be done as more mods are added to the game to prevent power creep)
all modes are a bit harder
if you used to play why, try the new hard
if you used to play hard try the new normal
power ups drop more often from bosses on all modes
************** TODO - n-gon ************** ************** TODO - n-gon **************
optional setting for people with desktops that want double mobs mod - explosions apply radiation damage over time
or spawn a neutron bomb with a timer
hard mode should match the pace of why, but with less difficulty mod self destruct - drones explode when they die
2x power up chances, same as why for all difficulties drones lose extra time on collisions
adjust difficulty levels
easy: 1 optional setting for people with desktops that want double mobs
normal: 2
hard: 3
why: 4
combine more stuff? combine more stuff?
____ mod for ____ ____ mod for ____
@@ -20,11 +26,6 @@ combine more stuff?
iceIX -> foam iceIX -> foam
flechettes -> nail gun flechettes -> nail gun
let beam splitter work with pulse
neutron bomb as a mod for mines
mod: stealth field - mark a mob, it you next kill is that mob get a bonus power up mod: stealth field - mark a mob, it you next kill is that mob get a bonus power up
run only at the start of a new level run only at the start of a new level
@@ -35,6 +36,8 @@ add an ending to the game
around level 15 around level 15
game never ends if you have used cheats game never ends if you have used cheats
new status effect - push mob away from player for a time
new status effect - apply status effect to mobs that makes blocks attracted to them new status effect - apply status effect to mobs that makes blocks attracted to them
only lasts a few cycles only lasts a few cycles
@@ -56,7 +59,6 @@ look for mods that could update description text with count and mod.is informat
can only use variables that change in effect() and remove() can only use variables that change in effect() and remove()
this.description = `<strong>8%</strong> chance to <strong>duplicate</strong> spawned <strong>power ups</strong><br><em>chance to duplicate = ${mod.duplicateChance}</em>` this.description = `<strong>8%</strong> chance to <strong>duplicate</strong> spawned <strong>power ups</strong><br><em>chance to duplicate = ${mod.duplicateChance}</em>`
mod self destruct - drones explode when they die, but they last 1/2 as long
mouse event e.which is deprecated mouse event e.which is deprecated