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">
<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">
<option value="0">easy</option>
<option value="1" selected>normal</option>
<option value="2">hard</option>
<option value="4">why...</option>
<option value="1">easy</option>
<option value="2" selected>normal</option>
<option value="4">hard</option>
<option value="6">why?</option>
</select>
<br>
<label for="community-maps" title="adds in maps written by n-gon player: Francois">include community maps:</label>

View File

@@ -3227,16 +3227,35 @@ const b = {
}
},
firePulse() {
//calculate laser collision
let best, energy, explosionRange;
mech.fireCDcycle = mech.cycle + Math.floor((mod.isPulseAim ? 25 : 50) * b.fireCD); // cool down
let energy = 0.27 * Math.min(mech.energy, 1.5)
mech.energy -= energy * mod.isLaserDiode
if (mod.beamSplitter) {
energy *= 0.7
b.pulse(energy, mech.angle)
for (let i = 1; i < 1 + mod.beamSplitter; i++) {
energy *= 0.9
b.pulse(energy, mech.angle - i * 0.35)
b.pulse(energy, mech.angle + i * 0.35)
}
} else {
b.pulse(energy, mech.angle)
}
},
},
],
pulse(energy, angle = mech.angle) {
let best;
let explosionRange = 1560 * energy
let range = 3000
const path = [{
x: mech.pos.x + 20 * Math.cos(mech.angle),
y: mech.pos.y + 20 * Math.sin(mech.angle)
x: mech.pos.x + 20 * Math.cos(angle),
y: mech.pos.y + 20 * Math.sin(angle)
},
{
x: mech.pos.x + range * Math.cos(mech.angle),
y: mech.pos.y + range * Math.sin(mech.angle)
x: mech.pos.x + range * Math.cos(angle),
y: mech.pos.y + range * Math.sin(angle)
}
];
const vertexCollision = function (v1, v1End, domain) {
@@ -3290,8 +3309,6 @@ const b = {
};
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 &&
@@ -3315,17 +3332,8 @@ const b = {
};
}
}
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) {
@@ -3362,18 +3370,5 @@ const b = {
time: Math.floor(2 + 33 * Math.random() * Math.random())
});
}
},
},
// {
// name: "pulse",
// 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>",
// ammo: 0,
// ammoPack: Infinity,
// have: false,
// fire() {
// }
// },
]
}
};

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
buttonCD: 0,
levelsCleared: 0,
difficultyMode: 1,
isEasyMode: false,
difficultyMode: 2, //normal difficulty is 2
difficulty: 0,
dmgScale: null, //set in levels.setDifficulty
healScale: 1,
@@ -485,20 +484,18 @@ const game = {
level.levelsCleared = 0;
//resetting difficulty
game.dmgScale = 1;
b.dmgScale = 0.7;
game.dmgScale = 0; //increases in level.difficultyIncrease
b.dmgScale = 1; //decreases in level.difficultyIncrease
game.accelScale = 1;
game.lookFreqScale = 1;
game.CDScale = 1;
game.difficulty = 0;
game.difficultyMode = Number(document.getElementById("difficulty-select").value)
build.isCustomSelection = false;
if (game.difficultyMode === 0) {
game.isEasyMode = true;
game.difficultyMode = 1
level.difficultyDecrease(6); //if this stops being -6 change in build.calculateCustomDifficulty()
}
if (game.difficultyMode > 1) level.difficultyIncrease(3)
// if (game.difficultyMode > 2) {
// level.difficultyIncrease(game.difficultyMode)
// level.difficultyIncrease(game.difficultyMode)
// }
game.clearNow = true;
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.pos.y > game.fallHeight) { // if 4000px deep
if (game.difficultyMode > 2) {
if (game.difficultyMode > 4) {
mech.death();
} else {
@@ -726,8 +723,7 @@ const game = {
});
}
}
if (game.difficultyMode === 2) mech.damage(0.25);
if (game.difficultyMode === 1) mech.damage(0.1);
mech.damage(0.1 * game.difficultyMode);
mech.energy = 0.01;
}
}
@@ -753,7 +749,7 @@ const game = {
let i = who.length;
while (i--) {
if (who[i].position.y > game.fallHeight) {
if (save && game.difficultyMode < 3) {
if (save && game.difficultyMode < 5) {
Matter.Body.setVelocity(who[i], {
x: 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>mouse: (${game.mouseInGame.x.toFixed(1)}, ${game.mouseInGame.y.toFixed(1)}) &nbsp; mass: ${player.mass.toFixed(1)}
<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>damage difficulty scale: ${(b.dmgScale*100).toFixed(2) }%
<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>
<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">
<option value="0">easy</option>
<option value="1" selected>normal</option>
<option value="2">hard</option>
<option value="4">why...</option>
<option value="1">easy</option>
<option value="2" selected>normal</option>
<option value="4">hard</option>
<option value="6">why?</option>
</select>
</div>`
for (let i = 0, len = mech.fieldUpgrades.length; i < len; i++) {
@@ -891,7 +891,7 @@ if (localSettings) {
} else {
localSettings = {
isCommunityMaps: false,
difficultyMode: '1',
difficultyMode: '2',
fpsCapDefault: 'max',
runCount: 0,
levelsClearedLastGame: 0,

View File

@@ -831,13 +831,13 @@ const level = {
"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(
"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.",
"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(
"What do I do after I escape?",
"I'm almost ready to stop these simulations and actually escape.",
@@ -3836,35 +3836,35 @@ const level = {
difficultyIncrease(num = 1) {
for (let i = 0; i < num; i++) {
game.difficulty++
game.dmgScale += 0.38; //damage done by mobs increases 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.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
}
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;
},
difficultyDecrease(num = 1) { //used in easy mode for game.reset()
for (let i = 0; i < num; i++) {
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
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.CDScale < 5) game.CDScale /= 0.97 //mob CD time decreases each level
}
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)
},
difficultyText(mode = document.getElementById("difficulty-select").value) {
if (mode === "0") {
difficultyText() {
if (game.difficultyMode === 1) {
return "easy"
} else if (mode === "1") {
} else if (game.difficultyMode === 2) {
return "normal"
} else if (mode === "2") {
} else if (game.difficultyMode === 4) {
return "hard"
} else if (mode === "4") {
} else if (game.difficultyMode === 6) {
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.5) 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;
//reset lost mod display
for (let i = 0; i < mod.mods.length; i++) {

View File

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

View File

@@ -434,7 +434,7 @@ const powerUps = {
}
},
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");
return;
}
@@ -446,7 +446,7 @@ const powerUps = {
powerUps.spawn(x, y, "gun");
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");
return;
}
@@ -462,27 +462,23 @@ const powerUps = {
randomPowerUpCounter: 0,
spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades
level.bossKilled = true;
// if (game.difficultyMode === 4) powerUps.spawn(x, y, "mod") //why mode gets a free mod
powerUps.randomPowerUpCounter++;
const chanceToFail = Math.max(level.levelsCleared, 10) * 0.1 //1 until level 10, then 1.1, 1.2, 1.3, ...
if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) {
powerUps.randomPowerUpCounter = 0;
spawnPowerUps()
} else {
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) {
powerUps.randomPowerUpCounter = 0;
spawnPowerUps()
} else {
spawnHealthAmmo()
}
}
function spawnHealthAmmo() {
powerUps.randomPowerUpCounter++;
powerUpChance(Math.max(level.levelsCleared, 10) * 0.1)
powerUps.randomPowerUpCounter += 0.6;
powerUpChance(Math.max(level.levelsCleared, 6) * 0.1)
function powerUpChance(chanceToFail) {
if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) {
powerUps.randomPowerUpCounter = 0;
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 {
if (mech.health < 0.65 && !mod.isEnergyHealth) {
powerUps.spawn(x, y, "heal");
powerUps.spawn(x, y, "heal");
@@ -491,15 +487,6 @@ const powerUps = {
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")
}
}
},
chooseRandomPowerUp(x, y) { //100% chance to drop a random power up //used in spawn.debris
@@ -517,7 +504,7 @@ const powerUps = {
},
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 (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
if (level.levelsCleared === 0 && !game.isCheating) {

View File

@@ -233,11 +233,11 @@ const spawn = {
me.isBoss = true;
me.frictionAir = 0.01
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
me.collisionFilter.mask = cat.bullet | cat.player
me.memory = Infinity;
me.seePlayerFreq = 60
me.seePlayerFreq = 30
me.lockedOn = null;
if (vertices === 9) {

View File

@@ -1,17 +1,23 @@
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 **************
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
2x power up chances, same as why for all difficulties
adjust difficulty levels
easy: 1
normal: 2
hard: 3
why: 4
mod self destruct - drones explode when they die
drones lose extra time on collisions
optional setting for people with desktops that want double mobs
combine more stuff?
____ mod for ____
@@ -20,11 +26,6 @@ combine more stuff?
iceIX -> foam
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
run only at the start of a new level
@@ -35,6 +36,8 @@ add an ending to the game
around level 15
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
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()
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