training mode choice for new players

electronegativity: +26->23% damage

gun cancel button doesn't show up on the initial level if you haven't done the training yet and you didn't choose a gun
after exiting initial level players are prompted to start the training levels
  only if they haven't done the training and they didn't pick up a gun, and a few other conditions
community training levels only are added when community maps setting is on and player clicks on training

if you die after clearing fewer than 4 levels the difficulty settings automatically opens
improved text formatting on updates
This commit is contained in:
landgreen
2024-01-29 21:29:39 -08:00
parent 4e6acdd5d0
commit 778a2c93b6
8 changed files with 123 additions and 88 deletions

View File

@@ -4028,7 +4028,7 @@ const b = {
bullet[me] = Bodies.polygon(where.x, where.y, 12, radius, b.fireAttributes(dir, false));
Composite.add(engine.world, bullet[me]); //add bullet to world
Matter.Body.setVelocity(bullet[me], velocity);
bullet[me].calcDensity = () => 0.0007 + 0.00055 * tech.isSuperHarm + 0.0004 * tech.isBulletTeleport
bullet[me].calcDensity = function () { 0.0007 + 0.00055 * tech.isSuperHarm + 0.0004 * tech.isBulletTeleport }
Matter.Body.setDensity(bullet[me], bullet[me].calcDensity());
bullet[me].endCycle = simulation.cycle + Math.floor(270 + 90 * Math.random());
bullet[me].minDmgSpeed = 0;

View File

@@ -1752,18 +1752,19 @@ document.getElementById("updates").addEventListener("toggle", function () {
xhr.open("GET", path, true);
xhr.send();
}
let text = `<strong>n-gon</strong>: <a href="https://github.com/landgreen/n-gon/blob/master/todo.txt">todo list</a> and complete <a href="https://github.com/landgreen/n-gon/commits/master">change-log</a><hr>`
let text = `<pre><strong>n-gon</strong>: <a href="https://github.com/landgreen/n-gon/blob/master/todo.txt">todo list</a> and complete <a href="https://github.com/landgreen/n-gon/commits/master">change-log</a><hr>`
document.getElementById("updates-div").innerHTML = text
/// https://api.github.com/repos/landgreen/n-gon/stats/commit_activity
loadJSON('https://api.github.com/repos/landgreen/n-gon/commits',
function (data) {
// console.log(data)
// console.log(data[0].sha) //unique code for most recent commit
for (let i = 0, len = 20; i < len; i++) {
text += "<strong>" + data[i].commit.author.date.substr(0, 10) + "</strong> - "; //+ "<br>"
text += data[i].commit.message
if (i < len - 1) text += "<hr>"
}
text += "</pre>"
document.getElementById("updates-div").innerHTML = text.replace(/\n/g, "<br />")
},
function (xhr) {

View File

@@ -12,7 +12,7 @@ const level = {
//see level.populateLevels: (initial, ... , reservoir or factory, reactor, ... , subway, final) added later
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock"],
communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass", "cantilever", "tlinat", "ruins", "ace", "crimsonTowers", "LaunchSite", "shipwreck", "unchartedCave", "dojo"],
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon", "diamagnetism"],
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"],
levels: [],
start() {
if (level.levelsCleared === 0) { //this code only runs on the first level
@@ -63,7 +63,6 @@ const level = {
// tech.tech[322].frequency = 100
// spawn.tetherBoss(1900, -500, { x: 1900, y: -500 })
// for (let i = 0; i < 40; ++i) tech.giveTech()
level[simulation.isTraining ? "walk" : "initial"]() //normal starting level **************************************************
// spawn.bodyRect(2425, -120, 200, 200);
@@ -76,6 +75,7 @@ const level = {
// for (let i = 0; i < 20; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "ammo");
// for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "field", false);
//lore testing
// localSettings.isTrainingNotAttempted = true
// simulation.isCheating = false //true;
// for (let i = 0; i < 5; i++) tech.giveTech("undefined")
// lore.techCount = 2
@@ -252,8 +252,9 @@ const level = {
if (!level.disableExit) {
level.levelsCleared++;
level.onLevel++; //cycles map to next level
if (simulation.isTraining) {
if (level.onLevel > level.levels.length - 1) {
if (level.onLevel > level.levels.length - 1) { //if all training levels are completed
level.disableExit = true
document.getElementById("health").style.display = "none"
document.getElementById("health-bg").style.display = "none"
@@ -286,16 +287,12 @@ const level = {
tech.isDeathAvoidedThisLevel = false;
simulation.updateTechHUD();
simulation.clearNow = true; //triggers in simulation.clearMap to remove all physics bodies and setup for new map
//pop up new level info screen for a few seconds
if (!simulation.isChoosing && m.alive && (level.levels[level.onLevel] === "final" || level.levels[level.onLevel] === "reactor")) { //level.levels[level.onLevel] === "subway" ||
//pause
if (!simulation.paused) {
simulation.paused = true;
simulation.isChoosing = true; //stops p from un pausing on key down
// build.pauseGrid()
// document.body.style.cursor = "auto";
}
//build level info
document.getElementById("choose-grid").style.gridTemplateColumns = "250px"
@@ -370,68 +367,20 @@ const level = {
}
requestAnimationFrame(newLevelDraw);
// // clear
// requestAnimationFrame(() => {
// simulation.wipe();
// });
// //wireframe
// setTimeout(() => {
// requestAnimationFrame(() => {
// simulation.wipe();
// simulation.camera();
// simulation.draw.wireFrame();
// ctx.restore();
// });
// }, 500);
// //almost normal draw
// setTimeout(() => {
// requestAnimationFrame(() => {
// simulation.wipe();
// simulation.camera();
// // ctx.fillStyle = "rgba(0,0,0,0.66)"
// // ctx.fill(simulation.draw.mapPath);
// simulation.draw.drawMapPath();
// ctx.restore();
// });
// }, 1000);
// //normal draw
// setTimeout(() => {
// requestAnimationFrame(() => {
// simulation.wipe();
// simulation.camera();
// // level.custom();
// simulation.draw.cons();
// simulation.draw.body();
// // m.draw();
// // m.hold();
// level.customTopLayer();
// simulation.draw.drawMapPath();
// ctx.restore();
// });
// }, 1500);
// //unpause
// setTimeout(() => {
// document.body.style.cursor = "none";
// if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 15; //player is immune to damage for 30 cycles
// if (simulation.paused) requestAnimationFrame(cycle);
// if (m.alive) simulation.paused = false;
// simulation.isChoosing = false; //stops p from un pausing on key down
// build.unPauseGrid()
// document.getElementById("choose-grid").style.opacity = "0"
// // document.getElementById("choose-grid").style.visibility = "hidden"
// setTimeout(() => {
// document.getElementById("choose-grid").style.visibility = "hidden"
// }, 1000);
// }, 2000);
}
}
},
unPause() {
if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 30; //player is immune to damage for 30 cycles
if (simulation.paused) requestAnimationFrame(cycle);
if (m.alive) simulation.paused = false;
simulation.isChoosing = false; //stops p from un pausing on key down
build.unPauseGrid()
document.getElementById("choose-grid").style.opacity = "0"
setTimeout(() => {
document.getElementById("choose-grid").style.visibility = "hidden"
}, 1000);
},
populateLevels() { //run a second time if URL is loaded
if (document.getElementById("banned").value) { //remove levels from ban list in settings
const banList = document.getElementById("banned").value.replace(/,/g, ' ').replace(/\s\s+/g, ' ').replace(/[^\w\s]/g, '') //replace commas with spaces, replace double spaces with single, remove strange symbols
@@ -468,6 +417,7 @@ const level = {
if (simulation.isTraining) {
simulation.isHorizontalFlipped = false
level.levels = level.trainingLevels.slice(0) //copy array, not by just by assignment
if (simulation.isCommunityMaps) level.trainingLevels.push("diamagnetism")
} else { //add remove and shuffle levels for the normal game (not training levels)
level.levels = level.playableLevels.slice(0) //copy array, not by just by assignment
if (simulation.isCommunityMaps) {
@@ -608,7 +558,73 @@ const level = {
if (level.exitCount > 100) {
level.exitCount = 0
level.nextLevel()
//prompt an option to do the training levels or continue to the normal game
if (!simulation.isChoosing && m.alive && !simulation.isTraining && !simulation.isCheating && b.inventory.length === 0 && level.levelsCleared === 0 && localSettings.isTrainingNotAttempted) {
//pause
if (!simulation.paused) {
simulation.paused = true;
simulation.isChoosing = true; //stops p from un pausing on key down
document.body.style.cursor = "auto";
document.getElementById("choose-grid").style.pointerEvents = "auto";
document.getElementById("choose-grid").style.transitionDuration = "0s";
}
//build level info
document.getElementById("choose-grid").classList.add('choose-grid-no-images');
document.getElementById("choose-grid").classList.remove('choose-grid');
document.getElementById("choose-grid").style.gridTemplateColumns = "350px"
let text = `
<div class="choose-grid-module" id = "choose-training" style = "font-size: 1em; padding:10px;color:#333;">
<h2 style="text-align: center;letter-spacing: 5px;">training</h2>
Begin the <strong>guided tutorial</strong> that shows you how to use your <strong class='color-f'>field</strong> and <strong class='color-g'>gun</strong>.
</div>
<div class="choose-grid-module" id = "choose-unPause" style = "font-size: 1em; padding:10px;color:#333;">
<h2 style="text-align: center; letter-spacing: 7px;">play</h2>
Begin the <strong>standard game</strong> where you progress through <strong>13</strong> random levels and beat the final boss.
</div>`
//use you use your <strong class='color-g'>gun</strong>, <strong class='color-f'>field</strong>, and <strong class='color-m'>tech</strong>
document.getElementById("choose-grid").innerHTML = text
//show level info
document.getElementById("choose-grid").style.opacity = "1"
document.getElementById("choose-grid").style.transitionDuration = "0.25s"; //how long is the fade in on
document.getElementById("choose-grid").style.visibility = "visible"
document.getElementById("choose-training").addEventListener("click", () => {
level.unPause()
simulation.isTraining = true
level.levelsCleared--;
level.onLevel--
simulation.isHorizontalFlipped = false
level.levels = level.trainingLevels.slice(0) //copy array, not by just by assignment
level.nextLevel()
//reset hide image style
if (localSettings.isHideImages) {
document.getElementById("choose-grid").classList.add('choose-grid-no-images');
document.getElementById("choose-grid").classList.remove('choose-grid');
} else {
document.getElementById("choose-grid").classList.add('choose-grid');
document.getElementById("choose-grid").classList.remove('choose-grid-no-images');
}
});
document.getElementById("choose-unPause").addEventListener("click", () => {
level.unPause()
level.nextLevel()
//reset hide image style
if (localSettings.isHideImages) {
document.getElementById("choose-grid").classList.add('choose-grid-no-images');
document.getElementById("choose-grid").classList.remove('choose-grid');
} else {
document.getElementById("choose-grid").classList.add('choose-grid');
document.getElementById("choose-grid").classList.remove('choose-grid-no-images');
}
});
requestAnimationFrame(() => {
ctx.fillStyle = `rgba(150,150,150,0.9)`; //`rgba(221,221,221,0.6)`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
});
} else { //advance to next level
level.nextLevel()
}
}
}
},

View File

@@ -477,6 +477,8 @@ const m = {
Composite.clear(engine.world);
Engine.clear(engine);
simulation.splashReturn();
//if you die after clearing fewer than 4 levels the difficulty settings automatically opens
if (level.levelsCleared < 4 && !simulation.isTraining && !simulation.isCheating) document.getElementById("settings-details").open = true;
}, 5000);
}
},
@@ -5042,7 +5044,7 @@ const m = {
{
name: "grappling hook",
// description: `use <strong class='color-f'>energy</strong> to pull yourself towards the <strong>map</strong><br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second`,
description: `use <strong class='color-f'>energy</strong> to fire a hook that <strong>pulls</strong> player<br><strong class='color-d'>damages</strong> mobs and destroys <strong class='color-block'>blocks</strong><br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second`,
description: `use <strong class='color-f'>energy</strong> to fire a hook that <strong>pulls</strong> player<br><strong class='color-d'>damages</strong> mobs and grabs <strong class='color-block'>blocks</strong><br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second`,
effect: () => {
m.fieldFire = true;
// m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping

View File

@@ -683,6 +683,8 @@ const powerUps = {
return `<div></div>`
} else if (tech.isCancelTech) {
return `<div class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 115px;">randomize</div>`
} else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted) { //don't show cancel if on initial level and haven't done tutorial
return `<div class='cancel-card' style="visibility: hidden;"></div>`
} else {
return `<div class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 85px;">cancel</div>`
}
@@ -739,10 +741,11 @@ const powerUps = {
text += `<span class='cancel-card' style="width: 95px;float: right;background-color: #aaa;color:#888;">cancel</span>`
} else if (tech.isCancelTech) {
text += `<span class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 115px;float: right;font-size:0.9em;padding-top:5px">randomize</span>`
} else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted) {
text += `<span class='cancel-card' style="visibility: hidden;">cancel</span>` //don't show cancel if on initial level and haven't done tutorial
} else {
text += `<span class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 95px;float: right;">cancel</span>`
}
return text + "</div>"
},
buildColumns(totalChoices, type) {

View File

@@ -250,7 +250,7 @@ const tech = {
if (tech.isBotDamage) dmg *= 1 + 0.06 * b.totalBots()
if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage
if (tech.isLowEnergyDamage) dmg *= 1 + 0.7 * Math.max(0, 1 - m.energy)
if (tech.energyDamage) dmg *= 1 + m.energy * 0.26 * tech.energyDamage;
if (tech.energyDamage) dmg *= 1 + m.energy * 0.23 * tech.energyDamage;
if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.007
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2.11
if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.88, player.speed * 0.0193)
@@ -2517,7 +2517,7 @@ const tech = {
},
{
name: "MACHO",
description: "a massive but compact object slowly follows you<br>if you are inside the <strong>MACHO</strong> <strong>+60%</strong> <strong class='color-defense'>defense</strong>",
description: "a massive compact halo object follows you<br><strong>+60%</strong> <strong class='color-defense'>defense</strong> while you are inside the <strong>MACHO</strong>",
maxCount: 1,
count: 0,
frequency: 1,
@@ -7675,7 +7675,7 @@ const tech = {
{
name: "electronegativity",
descriptionFunction() {
return `<strong>+0.26%</strong> <strong class='color-d'>damage</strong> per current stored <strong class='color-f'>energy</strong><br><em>(+${(27 * m.maxEnergy).toFixed(0)}% damage at max energy)</em>`
return `<strong>+0.23%</strong> <strong class='color-d'>damage</strong> per current stored <strong class='color-f'>energy</strong><br><em>(+${(27 * m.maxEnergy).toFixed(0)}% damage at max energy)</em>`
},
// description: "<strong>+1%</strong> <strong class='color-d'>damage</strong> per <strong>8</strong> stored <strong class='color-f'>energy</strong>",
isFieldTech: true,