superfluidity

This commit is contained in:
landgreen
2020-07-02 19:36:06 -07:00
parent 00b01bb820
commit 00933c9f7e
10 changed files with 537 additions and 362 deletions

View File

@@ -1079,7 +1079,7 @@ const b = {
plasmaBot(position = mech.pos) { plasmaBot(position = mech.pos) {
const me = bullet.length; const me = bullet.length;
const dir = mech.angle; const dir = mech.angle;
const RADIUS = 20 const RADIUS = 21
bullet[me] = Bodies.polygon(position.x, position.y, 5, RADIUS, { bullet[me] = Bodies.polygon(position.x, position.y, 5, RADIUS, {
angle: dir, angle: dir,
friction: 0, friction: 0,
@@ -1115,7 +1115,7 @@ const b = {
let closeDist = mod.isPlasmaRange * 1000; let closeDist = mod.isPlasmaRange * 1000;
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
const DIST = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius; const DIST = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius;
if (DIST < closeDist && mob[i].dropPowerUp && if (DIST < closeDist &&
Matter.Query.ray(map, this.position, mob[i].position).length === 0 && Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0) { Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
closeDist = DIST; closeDist = DIST;

View File

@@ -233,7 +233,10 @@ const game = {
if (mod.mods[i].count > 0) { if (mod.mods[i].count > 0) {
if (text) text += "<br>" //add a new line, but not on the first line if (text) text += "<br>" //add a new line, but not on the first line
text += mod.mods[i].name text += mod.mods[i].name
if (mod.mods[i].nameInfo) text += mod.mods[i].nameInfo if (mod.mods[i].nameInfo) {
text += mod.mods[i].nameInfo
mod.mods[i].addNameInfo();
}
if (mod.mods[i].count > 1) text += ` (${mod.mods[i].count}x)` if (mod.mods[i].count > 1) text += ` (${mod.mods[i].count}x)`
} }
} }
@@ -243,7 +246,7 @@ const game = {
replaceTextLog: true, replaceTextLog: true,
// <!-- <path d="M832.41,106.64 V323.55 H651.57 V256.64 c0-82.5,67.5-150,150-150 Z" fill="#789" stroke="none" /> // <!-- <path d="M832.41,106.64 V323.55 H651.57 V256.64 c0-82.5,67.5-150,150-150 Z" fill="#789" stroke="none" />
// <path d="M827,112 h30 a140,140,0,0,1,140,140 v68 h-167 z" fill="#7ce" stroke="none" /> --> // <path d="M827,112 h30 a140,140,0,0,1,140,140 v68 h-167 z" fill="#7ce" stroke="none" /> -->
SVGleftMouse: '<svg viewBox="750 0 200 765" class="mouse-icon" width="40px" height = "60px" stroke-linecap="round" stroke-linejoin="round" stroke-width="25px" stroke="#000" fill="none"> <path fill="#fff" stroke="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M832.41,106.64 V323.55 H651.57 V256.64 c0-82.5,67.5-150,150-150 Z" fill="#149" stroke="none" /> <path fill="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M657 317 h 340 h-170 v-207" /> <ellipse fill="#fff" cx="827.57" cy="218.64" rx="29" ry="68" /> </svg>', // SVGleftMouse: '<svg viewBox="750 0 200 765" class="mouse-icon" width="40px" height = "60px" stroke-linecap="round" stroke-linejoin="round" stroke-width="25px" stroke="#000" fill="none"> <path fill="#fff" stroke="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M832.41,106.64 V323.55 H651.57 V256.64 c0-82.5,67.5-150,150-150 Z" fill="#149" stroke="none" /> <path fill="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M657 317 h 340 h-170 v-207" /> <ellipse fill="#fff" cx="827.57" cy="218.64" rx="29" ry="68" /> </svg>',
SVGrightMouse: '<svg viewBox="750 0 200 765" class="mouse-icon" width="40px" height = "60px" stroke-linecap="round" stroke-linejoin="round" stroke-width="25px" stroke="#000" fill="none"> <path fill="#fff" stroke="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M827,112 h30 a140,140,0,0,1,140,140 v68 h-167 z" fill="#0cf" stroke="none" /> <path fill="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M657 317 h 340 h-170 v-207" /> <ellipse fill="#fff" cx="827.57" cy="218.64" rx="29" ry="68" /> </svg>', SVGrightMouse: '<svg viewBox="750 0 200 765" class="mouse-icon" width="40px" height = "60px" stroke-linecap="round" stroke-linejoin="round" stroke-width="25px" stroke="#000" fill="none"> <path fill="#fff" stroke="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M827,112 h30 a140,140,0,0,1,140,140 v68 h-167 z" fill="#0cf" stroke="none" /> <path fill="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M657 317 h 340 h-170 v-207" /> <ellipse fill="#fff" cx="827.57" cy="218.64" rx="29" ry="68" /> </svg>',
makeTextLog(text, time = 180) { makeTextLog(text, time = 180) {
if (game.replaceTextLog) { if (game.replaceTextLog) {
@@ -400,6 +403,8 @@ const game = {
// game.noCameraScroll() // game.noCameraScroll()
} else if (keys[85]) { // next level with U } else if (keys[85]) { // next level with U
level.nextLevel(); level.nextLevel();
} else if (keys[88] && keys[90]) {
mech.death();
} }
} }
}, },
@@ -775,12 +780,6 @@ const game = {
if (mod.isHealthRecovery) mech.addHealth(0.01) if (mod.isHealthRecovery) mech.addHealth(0.01)
} }
if (mod.isHealLowHealth) {
if (mech.health < mech.maxHealth * 0.25) {
mech.addHealth(0.01 * mech.maxHealth)
}
}
if (!(game.cycle % 420)) { //once every 7 seconds if (!(game.cycle % 420)) { //once every 7 seconds
fallCheck = function (who, save = false) { fallCheck = function (who, save = false) {
let i = who.length; let i = who.length;
@@ -1086,6 +1085,8 @@ const game = {
enableConstructMode() { enableConstructMode() {
game.isConstructionMode = true; game.isConstructionMode = true;
game.isAutoZoom = false; game.isAutoZoom = false;
game.zoomScale = 2200;
game.setZoom();
document.body.addEventListener("mouseup", (e) => { document.body.addEventListener("mouseup", (e) => {
if (game.testing && game.constructMouseDownPosition) { if (game.testing && game.constructMouseDownPosition) {

View File

@@ -248,7 +248,6 @@ const build = {
document.getElementById("difficulty-select").value = document.getElementById("difficulty-select-custom").value document.getElementById("difficulty-select").value = document.getElementById("difficulty-select-custom").value
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
}); });
mod.resetModText();
}, },
reset() { reset() {
build.isCustomSelection = true; build.isCustomSelection = true;

View File

@@ -13,18 +13,16 @@ const level = {
// game.enableConstructMode() //used to build maps in testing mode // game.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(9) // level.difficultyIncrease(9)
// mech.isStealth = true; // mech.isStealth = true;
// mod.giveMod("plasma-bot");
// mod.giveMod("nail-bot");
// mod.giveMod("laser-bot");
// mod.giveMod("boom-bot");
// mod.giveMod("supply chain"); // mod.giveMod("supply chain");
// b.giveGuns("pulse") b.giveGuns("ice IX")
// mech.setField("plasma torch") // mech.setField("plasma torch")
level.intro(); //starting level level.intro(); //starting level
// level.bossRoom1()
// level.testing(); // level.testing();
// level.stronghold() // level.template()
// level.bosses(); // level.bosses();
// level.stronghold()
// level.satellite(); // level.satellite();
// level.skyscrapers(); // level.skyscrapers();
// level.aerie(); // level.aerie();
@@ -32,6 +30,7 @@ const level = {
// level.warehouse(); // level.warehouse();
// level.highrise(); // level.highrise();
// level.office(); // level.office();
} else { } else {
spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
// spawn.pickList = ["focuser", "focuser"] // spawn.pickList = ["focuser", "focuser"]
@@ -61,245 +60,86 @@ const level = {
if (mod.isArmorFromPowerUps) { if (mod.isArmorFromPowerUps) {
// for (let i = 0; i < powerUps.totalPowerUps; i++) {} // for (let i = 0; i < powerUps.totalPowerUps; i++) {}
mech.maxHealth += 0.04 * powerUps.totalPowerUps mech.maxHealth += 0.05 * powerUps.totalPowerUps
if (powerUps.totalPowerUps) game.makeTextLog("<span style='font-size:115%;'> max health increased by " + (0.04 * powerUps.totalPowerUps * 100).toFixed(0) + "%</span>", 300) if (powerUps.totalPowerUps) game.makeTextLog("<span style='font-size:115%;'> max health increased by " + (0.05 * powerUps.totalPowerUps * 100).toFixed(0) + "%</span>", 300)
} }
}, },
isBuildRun: false, //******************************************************************************************************************
difficultyIncrease(num = 1) { //******************************************************************************************************************
// if (level.isBuildRun) num++ //******************************************************************************************************************
for (let i = 0; i < num; i++) { //******************************************************************************************************************
game.difficulty++ bossRoom1() {
game.dmgScale += 0.21; //damage done by mobs increases each level level.custom = () => {
b.dmgScale *= 0.91; //damage done by player decreases each level level.playerExitCheck();
game.accelScale *= 1.027 //mob acceleration increases each level
game.lookFreqScale *= 0.974 //mob cycles between looks decreases each level
game.CDScale *= 0.964 //mob CD time decreases each level
}
game.healScale = 1 / (1 + game.difficulty * 0.09) //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.21; //damage done by mobs increases each level
if (game.dmgScale < 0.1) game.dmgScale = 0.1;
b.dmgScale /= 0.91; //damage done by player decreases each level
game.accelScale /= 1.027 //mob acceleration increases each level
game.lookFreqScale /= 0.974 //mob cycles between looks decreases each level
game.CDScale /= 0.964 //mob CD time decreases each level
}
if (game.difficulty < 1) game.difficulty = 0;
game.healScale = 1 / (1 + game.difficulty * 0.09)
},
difficultyText(mode = document.getElementById("difficulty-select").value) {
if (mode === "0") {
return "easy"
} else if (mode === "1") {
return "normal"
} else if (mode === "2") {
return "hard"
} else if (mode === "4") {
return "why"
}
},
levelAnnounce() {
if (level.levelsCleared === 0) {
document.title = "n-gon: intro (" + level.difficultyText() + ")";
} else {
document.title = "n-gon: L" + (level.levelsCleared) + " " + level.levels[level.onLevel] + " (" + level.difficultyText() + ")";
}
},
custom() {}, //each level runs it's own custom code (level exits, ...)
nextLevel() {
level.levelsCleared++;
level.onLevel++; //cycles map to next level
if (level.onLevel > level.levels.length - 1) level.onLevel = 0;
level.difficultyIncrease(game.difficultyMode) //increase difficulty based on modes
if (game.isEasyMode && level.levelsCleared % 2) level.difficultyDecrease(1);
game.clearNow = true; //triggers in game.clearMap to remove all physics bodies and setup for new map
},
playerExitCheck() {
if (
player.position.x > level.exit.x &&
player.position.x < level.exit.x + 100 &&
player.position.y > level.exit.y - 150 &&
player.position.y < level.exit.y - 40 &&
player.velocity.y < 0.1
) {
level.nextLevel()
}
},
setPosToSpawn(xPos, yPos) {
mech.spawnPos.x = mech.pos.x = xPos;
mech.spawnPos.y = mech.pos.y = yPos;
level.enter.x = mech.spawnPos.x - 50;
level.enter.y = mech.spawnPos.y + 20;
mech.transX = mech.transSmoothX = canvas.width2 - mech.pos.x;
mech.transY = mech.transSmoothY = canvas.height2 - mech.pos.y;
mech.Vx = mech.spawnVel.x;
mech.Vy = mech.spawnVel.y;
player.force.x = 0;
player.force.y = 0;
Matter.Body.setPosition(player, mech.spawnPos);
Matter.Body.setVelocity(player, mech.spawnVel);
},
enter: {
x: 0,
y: 0,
draw() {
ctx.beginPath();
ctx.moveTo(level.enter.x, level.enter.y + 30);
ctx.lineTo(level.enter.x, level.enter.y - 80);
ctx.bezierCurveTo(level.enter.x, level.enter.y - 170, level.enter.x + 100, level.enter.y - 170, level.enter.x + 100, level.enter.y - 80);
ctx.lineTo(level.enter.x + 100, level.enter.y + 30);
ctx.lineTo(level.enter.x, level.enter.y + 30);
ctx.fillStyle = "#ccc";
ctx.fill();
}
},
exit: {
x: 0,
y: 0,
draw() {
ctx.beginPath();
ctx.moveTo(level.exit.x, level.exit.y + 30);
ctx.lineTo(level.exit.x, level.exit.y - 80);
ctx.bezierCurveTo(level.exit.x, level.exit.y - 170, level.exit.x + 100, level.exit.y - 170, level.exit.x + 100, level.exit.y - 80);
ctx.lineTo(level.exit.x + 100, level.exit.y + 30);
ctx.lineTo(level.exit.x, level.exit.y + 30);
ctx.fillStyle = "#0ff";
ctx.fill();
}
},
fillBG: [],
drawFillBGs() {
for (let i = 0, len = level.fillBG.length; i < len; ++i) {
const f = level.fillBG[i];
ctx.fillStyle = f.color;
ctx.fillRect(f.x, f.y, f.width, f.height);
}
},
fill: [],
drawFills() {
for (let i = 0, len = level.fill.length; i < len; ++i) {
const f = level.fill[i];
ctx.fillStyle = f.color;
ctx.fillRect(f.x, f.y, f.width, f.height);
}
},
queryList: [], //queries do actions on many objects in regions
checkQuery() {
let bounds, action, info;
function isInZone(targetArray) {
let results = Matter.Query.region(targetArray, bounds);
for (let i = 0, len = results.length; i < len; ++i) {
level.queryActions[action](results[i], info);
}
}
for (let i = 0, len = level.queryList.length; i < len; ++i) {
bounds = level.queryList[i].bounds;
action = level.queryList[i].action;
info = level.queryList[i].info;
for (let j = 0, l = level.queryList[i].groups.length; j < l; ++j) {
isInZone(level.queryList[i].groups[j]);
}
}
},
//oddly query regions can't get smaller than 50 width?
addQueryRegion(x, y, width, height, action, groups = [
[player], body, mob, powerUp, bullet
], info) {
level.queryList[level.queryList.length] = {
bounds: {
min: {
x: x,
y: y
},
max: {
x: x + width,
y: y + height
}
},
action: action,
groups: groups,
info: info
}; };
}, level.setPosToSpawn(0, -50); //normal spawn
queryActions: { spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
bounce(target, info) { level.exit.x = 1500;
//jerky fling upwards level.exit.y = -1875;
Matter.Body.setVelocity(target, { level.defaultZoom = 1800
x: info.Vx + (Math.random() - 0.5) * 6, game.zoomTransition(level.defaultZoom)
y: info.Vy document.body.style.backgroundColor = "#dcdcde";
}); // powerUps.spawnStartingPowerUps(1475, -1175);
target.torque = (Math.random() - 0.5) * 2 * target.mass; // spawn.debris(750, -2200, 3700, 16); //16 debris per level
}, // level.fill.push({ //foreground
boost(target, yVelocity) { // x: 2500,
// if (target.velocity.y < 0) { // y: -1100,
// mech.undoCrouch(); // width: 450,
// mech.enterAir(); // height: 250,
mech.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts // color: "rgba(0,0,0,0.1)"
mech.hardLandCD = 0 // disable hard landing // });
if (target.velocity.y > 30) { // level.fillBG.push({ //background
Matter.Body.setVelocity(target, { // x: 1300,
x: target.velocity.x + (Math.random() - 0.5) * 2, // y: -1800,
y: -23 //gentle bounce if coming down super fast // width: 750,
}); // height: 1800,
} else { // color: "#d4d4d7"
Matter.Body.setVelocity(target, { // });
x: target.velocity.x + (Math.random() - 0.5) * 2,
y: yVelocity
});
}
}, spawn.mapRect(-100, 0, 1000, 100);
force(target, info) { // spawn.bodyRect(1540, -1110, 300, 25, 0.9);
if (target.velocity.y < 0) { // spawn.boost(4150, 0, 1300);
//gently force up if already on the way up // spawn.randomSmallMob(1300, -70);
target.force.x += info.Vx * target.mass; // spawn.randomMob(2650, -975, 0.8);
target.force.y += info.Vy * target.mass; // spawn.randomBoss(1700, -900, 0.4);
} else { // if (game.difficulty > 3) spawn.randomLevelBoss(2200, -1300);
target.force.y -= 0.0007 * target.mass; //gently fall in on the way down
}
},
antiGrav(target) {
target.force.y -= 0.0011 * target.mass;
},
death(target) {
target.death();
}
}, },
addToWorld() { template() {
//needs to be run to put bodies into the world level.custom = () => {
for (let i = 0; i < body.length; i++) { level.playerExitCheck();
//body[i].collisionFilter.group = 0; };
if (body[i] !== mech.holdingTarget) { level.setPosToSpawn(0, -50); //normal spawn
body[i].collisionFilter.category = cat.body; spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
body[i].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet level.exit.x = 1500;
} level.exit.y = -1875;
body[i].classType = "body"; level.defaultZoom = 1800
World.add(engine.world, body[i]); //add to world game.zoomTransition(level.defaultZoom)
} document.body.style.backgroundColor = "#dcdcde";
for (let i = 0; i < map.length; i++) { // powerUps.spawnStartingPowerUps(1475, -1175);
//map[i].collisionFilter.group = 0; // spawn.debris(750, -2200, 3700, 16); //16 debris per level
map[i].collisionFilter.category = cat.map; // level.fill.push({ //foreground
map[i].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet; // x: 2500,
Matter.Body.setStatic(map[i], true); //make static // y: -1100,
World.add(engine.world, map[i]); //add to world // width: 450,
} // height: 250,
for (let i = 0; i < cons.length; i++) { // color: "rgba(0,0,0,0.1)"
World.add(engine.world, cons[i]); // });
} // level.fillBG.push({ //background
for (let i = 0; i < consBB.length; i++) { // x: 1300,
World.add(engine.world, consBB[i]); // y: -1800,
} // width: 750,
// height: 1800,
// color: "#d4d4d7"
// });
spawn.mapRect(-100, 0, 1000, 100);
// spawn.bodyRect(1540, -1110, 300, 25, 0.9);
// spawn.boost(4150, 0, 1300);
// spawn.randomSmallMob(1300, -70);
// spawn.randomMob(2650, -975, 0.8);
// spawn.randomBoss(1700, -900, 0.4);
// if (game.difficulty > 3) spawn.randomLevelBoss(2200, -1300);
}, },
//******************************************************************************************************************
//******************************************************************************************************************
//******************************************************************************************************************
//******************************************************************************************************************
testing() { testing() {
level.custom = () => { level.custom = () => {
level.playerExitCheck(); level.playerExitCheck();
@@ -358,14 +198,14 @@ const level = {
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
spawn.boost(1500, 0, 900); spawn.boost(1500, 0, 900);
// spawn.bomberBoss(2900, -500) spawn.bomberBoss(2900, -500)
// spawn.launcherBoss(1200, -500) // spawn.launcherBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400) // spawn.laserTargetingBoss(1600, -400)
// spawn.spawner(1600, -500) // spawn.spawner(1600, -500)
// spawn.sniper(1700, -120, 50) // spawn.sniper(1700, -120, 50)
spawn.sniper(1400, -120) // spawn.sniper(1400, -120)
spawn.sniper(1800, -120) // spawn.sniper(1800, -120)
spawn.sniper(2200, -120) // spawn.sniper(2200, -120)
// spawn.cellBossCulture(1600, -500) // spawn.cellBossCulture(1600, -500)
// spawn.shooter(1600, -500) // spawn.shooter(1600, -500)
// spawn.striker(1600, -500) // spawn.striker(1600, -500)
@@ -2056,4 +1896,239 @@ const level = {
if (game.difficulty > 3) spawn.randomLevelBoss(1850, -1400, 1); if (game.difficulty > 3) spawn.randomLevelBoss(1850, -1400, 1);
}, },
//******************************************************************************************************************
//******************************************************************************************************************
//******************************************************************************************************************
//******************************************************************************************************************
isBuildRun: false,
difficultyIncrease(num = 1) {
// if (level.isBuildRun) num++
for (let i = 0; i < num; i++) {
game.difficulty++
game.dmgScale += 0.21; //damage done by mobs increases each level
b.dmgScale *= 0.91; //damage done by player decreases each level
game.accelScale *= 1.027 //mob acceleration increases each level
game.lookFreqScale *= 0.974 //mob cycles between looks decreases each level
game.CDScale *= 0.964 //mob CD time decreases each level
}
game.healScale = 1 / (1 + game.difficulty * 0.09) //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.21; //damage done by mobs increases each level
if (game.dmgScale < 0.1) game.dmgScale = 0.1;
b.dmgScale /= 0.91; //damage done by player decreases each level
game.accelScale /= 1.027 //mob acceleration increases each level
game.lookFreqScale /= 0.974 //mob cycles between looks decreases each level
game.CDScale /= 0.964 //mob CD time decreases each level
}
if (game.difficulty < 1) game.difficulty = 0;
game.healScale = 1 / (1 + game.difficulty * 0.09)
},
difficultyText(mode = document.getElementById("difficulty-select").value) {
if (mode === "0") {
return "easy"
} else if (mode === "1") {
return "normal"
} else if (mode === "2") {
return "hard"
} else if (mode === "4") {
return "why"
}
},
levelAnnounce() {
if (level.levelsCleared === 0) {
document.title = "n-gon: intro (" + level.difficultyText() + ")";
} else {
document.title = "n-gon: L" + (level.levelsCleared) + " " + level.levels[level.onLevel] + " (" + level.difficultyText() + ")";
}
},
custom() {}, //each level runs it's own custom code (level exits, ...)
nextLevel() {
level.levelsCleared++;
level.onLevel++; //cycles map to next level
if (level.onLevel > level.levels.length - 1) level.onLevel = 0;
level.difficultyIncrease(game.difficultyMode) //increase difficulty based on modes
if (game.isEasyMode && level.levelsCleared % 2) level.difficultyDecrease(1);
game.clearNow = true; //triggers in game.clearMap to remove all physics bodies and setup for new map
if (mod.isHealLowHealth && mech.health < mech.maxHealth * 0.5) {
mech.health = mech.maxHealth * 0.5
mod.onHealthChange();
mech.displayHealth();
}
},
playerExitCheck() {
if (
player.position.x > level.exit.x &&
player.position.x < level.exit.x + 100 &&
player.position.y > level.exit.y - 150 &&
player.position.y < level.exit.y - 40 &&
player.velocity.y < 0.1
) {
level.nextLevel()
}
},
setPosToSpawn(xPos, yPos) {
mech.spawnPos.x = mech.pos.x = xPos;
mech.spawnPos.y = mech.pos.y = yPos;
level.enter.x = mech.spawnPos.x - 50;
level.enter.y = mech.spawnPos.y + 20;
mech.transX = mech.transSmoothX = canvas.width2 - mech.pos.x;
mech.transY = mech.transSmoothY = canvas.height2 - mech.pos.y;
mech.Vx = mech.spawnVel.x;
mech.Vy = mech.spawnVel.y;
player.force.x = 0;
player.force.y = 0;
Matter.Body.setPosition(player, mech.spawnPos);
Matter.Body.setVelocity(player, mech.spawnVel);
},
enter: {
x: 0,
y: 0,
draw() {
ctx.beginPath();
ctx.moveTo(level.enter.x, level.enter.y + 30);
ctx.lineTo(level.enter.x, level.enter.y - 80);
ctx.bezierCurveTo(level.enter.x, level.enter.y - 170, level.enter.x + 100, level.enter.y - 170, level.enter.x + 100, level.enter.y - 80);
ctx.lineTo(level.enter.x + 100, level.enter.y + 30);
ctx.lineTo(level.enter.x, level.enter.y + 30);
ctx.fillStyle = "#ccc";
ctx.fill();
}
},
exit: {
x: 0,
y: 0,
draw() {
ctx.beginPath();
ctx.moveTo(level.exit.x, level.exit.y + 30);
ctx.lineTo(level.exit.x, level.exit.y - 80);
ctx.bezierCurveTo(level.exit.x, level.exit.y - 170, level.exit.x + 100, level.exit.y - 170, level.exit.x + 100, level.exit.y - 80);
ctx.lineTo(level.exit.x + 100, level.exit.y + 30);
ctx.lineTo(level.exit.x, level.exit.y + 30);
ctx.fillStyle = "#0ff";
ctx.fill();
}
},
fillBG: [],
drawFillBGs() {
for (let i = 0, len = level.fillBG.length; i < len; ++i) {
const f = level.fillBG[i];
ctx.fillStyle = f.color;
ctx.fillRect(f.x, f.y, f.width, f.height);
}
},
fill: [],
drawFills() {
for (let i = 0, len = level.fill.length; i < len; ++i) {
const f = level.fill[i];
ctx.fillStyle = f.color;
ctx.fillRect(f.x, f.y, f.width, f.height);
}
},
queryList: [], //queries do actions on many objects in regions
checkQuery() {
let bounds, action, info;
function isInZone(targetArray) {
let results = Matter.Query.region(targetArray, bounds);
for (let i = 0, len = results.length; i < len; ++i) {
level.queryActions[action](results[i], info);
}
}
for (let i = 0, len = level.queryList.length; i < len; ++i) {
bounds = level.queryList[i].bounds;
action = level.queryList[i].action;
info = level.queryList[i].info;
for (let j = 0, l = level.queryList[i].groups.length; j < l; ++j) {
isInZone(level.queryList[i].groups[j]);
}
}
},
//oddly query regions can't get smaller than 50 width?
addQueryRegion(x, y, width, height, action, groups = [
[player], body, mob, powerUp, bullet
], info) {
level.queryList[level.queryList.length] = {
bounds: {
min: {
x: x,
y: y
},
max: {
x: x + width,
y: y + height
}
},
action: action,
groups: groups,
info: info
};
},
queryActions: {
bounce(target, info) {
//jerky fling upwards
Matter.Body.setVelocity(target, {
x: info.Vx + (Math.random() - 0.5) * 6,
y: info.Vy
});
target.torque = (Math.random() - 0.5) * 2 * target.mass;
},
boost(target, yVelocity) {
mech.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts
mech.hardLandCD = 0 // disable hard landing
if (target.velocity.y > 30) {
Matter.Body.setVelocity(target, {
x: target.velocity.x + (Math.random() - 0.5) * 2,
y: -23 //gentle bounce if coming down super fast
});
} else {
Matter.Body.setVelocity(target, {
x: target.velocity.x + (Math.random() - 0.5) * 2,
y: yVelocity
});
}
},
force(target, info) {
if (target.velocity.y < 0) { //gently force up if already on the way up
target.force.x += info.Vx * target.mass;
target.force.y += info.Vy * target.mass;
} else {
target.force.y -= 0.0007 * target.mass; //gently fall in on the way down
}
},
antiGrav(target) {
target.force.y -= 0.0011 * target.mass;
},
death(target) {
target.death();
}
},
addToWorld() { //needs to be run to put bodies into the world
for (let i = 0; i < body.length; i++) {
//body[i].collisionFilter.group = 0;
if (body[i] !== mech.holdingTarget) {
body[i].collisionFilter.category = cat.body;
body[i].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet
}
body[i].classType = "body";
World.add(engine.world, body[i]); //add to world
}
for (let i = 0; i < map.length; i++) {
//map[i].collisionFilter.group = 0;
map[i].collisionFilter.category = cat.map;
map[i].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet;
Matter.Body.setStatic(map[i], true); //make static
World.add(engine.world, map[i]); //add to world
}
for (let i = 0; i < cons.length; i++) {
World.add(engine.world, cons[i]);
}
for (let i = 0; i < consBB.length; i++) {
World.add(engine.world, consBB[i]);
}
},
}; };

View File

@@ -44,46 +44,63 @@ const mobs = {
} }
}, },
statusSlow(who, cycles = 60) { statusSlow(who, cycles = 60) {
if (!who.shield && !who.isShielded && !mech.isBodiesAsleep) { applySlow(who)
if (who.isBoss) { //look for mobs near the target
cycles = Math.floor(cycles * 0.25) if (mod.isAoESlow) {
const range = (220 + 150 * Math.random()) ** 2
for (let i = 0, len = mob.length; i < len; i++) {
if (Vector.magnitudeSquared(Vector.sub(who.position, mob[i].position)) < range) applySlow(mob[i])
} }
//remove other "slow" effects on this mob game.drawList.push({
let i = who.status.length x: who.position.x,
while (i--) { y: who.position.y,
if (who.status[i].type === "slow") who.status.splice(i, 1); radius: Math.sqrt(range),
color: "rgba(0,100,255,0.05)",
time: 3
});
}
function applySlow(target) {
if (!target.shield && !target.isShielded && !mech.isBodiesAsleep) {
if (target.isBoss) cycles = Math.floor(cycles * 0.25)
let i = target.status.length
while (i--) {
if (target.status[i].type === "slow") target.status.splice(i, 1); //remove other "slow" effects on this mob
}
target.status.push({
effect() {
Matter.Body.setVelocity(target, {
x: 0,
y: 0
});
Matter.Body.setAngularVelocity(target, 0);
ctx.beginPath();
ctx.moveTo(target.vertices[0].x, target.vertices[0].y);
for (let j = 1, len = target.vertices.length; j < len; ++j) {
ctx.lineTo(target.vertices[j].x, target.vertices[j].y);
}
ctx.lineTo(target.vertices[0].x, target.vertices[0].y);
ctx.strokeStyle = "rgba(0,100,255,0.8)";
ctx.lineWidth = 15;
ctx.stroke();
ctx.fillStyle = target.fill
ctx.fill();
},
type: "slow",
endCycle: game.cycle + cycles,
})
} }
who.status.push({
effect() {
Matter.Body.setVelocity(who, {
x: 0,
y: 0
});
Matter.Body.setAngularVelocity(who, 0);
ctx.beginPath();
ctx.moveTo(who.vertices[0].x, who.vertices[0].y);
for (let j = 1, len = who.vertices.length; j < len; ++j) {
ctx.lineTo(who.vertices[j].x, who.vertices[j].y);
}
ctx.lineTo(who.vertices[0].x, who.vertices[0].y);
ctx.strokeStyle = "rgba(0,100,255,0.8)";
ctx.lineWidth = 15;
ctx.stroke();
ctx.fillStyle = who.fill
ctx.fill();
},
type: "slow",
endCycle: game.cycle + cycles,
})
} }
}, },
statusStun(who, cycles = 180) { statusStun(who, cycles = 180) {
if (!who.shield && !who.isShielded && !mech.isBodiesAsleep) { if (!who.shield && !who.isShielded && !mech.isBodiesAsleep) {
Matter.Body.setVelocity(who, { Matter.Body.setVelocity(who, {
x: who.velocity.x * 0.5, x: who.velocity.x * 0.8,
y: who.velocity.y * 0.5 y: who.velocity.y * 0.8
}); });
Matter.Body.setAngularVelocity(who, who.angularVelocity * 0.5); Matter.Body.setAngularVelocity(who, who.angularVelocity * 0.8);
//remove other "stun" effects on this mob //remove other "stun" effects on this mob
let i = who.status.length let i = who.status.length
while (i--) { while (i--) {
@@ -97,7 +114,7 @@ const mobs = {
x: who.position.x + 100 * (Math.random() - 0.5), x: who.position.x + 100 * (Math.random() - 0.5),
y: who.position.y + 100 * (Math.random() - 0.5) y: who.position.y + 100 * (Math.random() - 0.5)
} }
if (who.velocity.y < 2) who.force.y += who.mass * 0.0005 //extra gravity if (who.velocity.y < 2) who.force.y += who.mass * 0.0004 //extra gravity
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(who.vertices[0].x, who.vertices[0].y); ctx.moveTo(who.vertices[0].x, who.vertices[0].y);
for (let j = 1, len = who.vertices.length; j < len; ++j) { for (let j = 1, len = who.vertices.length; j < len; ++j) {
@@ -831,7 +848,7 @@ const mobs = {
Matter.Query.ray(map, this.position, this.mechPosRange()).length === 0 && //see player Matter.Query.ray(map, this.position, this.mechPosRange()).length === 0 && //see player
Matter.Query.ray(body, this.position, this.mechPosRange()).length === 0 Matter.Query.ray(body, this.position, this.mechPosRange()).length === 0
) { ) {
spawn.bullet(this.position.x, this.position.y + this.radius * 0.5, 10 + Math.ceil(this.radius / 15), 5); spawn.bomb(this.position.x, this.position.y + this.radius * 0.5, 10 + Math.ceil(this.radius / 15), 5);
//add spin and speed //add spin and speed
Matter.Body.setAngularVelocity(mob[mob.length - 1], (Math.random() - 0.5) * 0.5); Matter.Body.setAngularVelocity(mob[mob.length - 1], (Math.random() - 0.5) * 0.5);
Matter.Body.setVelocity(mob[mob.length - 1], { Matter.Body.setVelocity(mob[mob.length - 1], {
@@ -1000,7 +1017,7 @@ const mobs = {
} }
} }
if (Math.random() < mod.isBotSpawner) { if (Math.random() < mod.isBotSpawner) {
if (Math.random() < 0.2) { //very low chance of plasma bot if (Math.random() < 0.1) { //very low chance of plasma bot
b.plasmaBot(this.position) b.plasmaBot(this.position)
} else if (Math.random() < 0.25) { } else if (Math.random() < 0.25) {
b.nailBot(this.position) b.nailBot(this.position)

View File

@@ -80,36 +80,24 @@ const mod = {
return dmg * mod.slowFire return dmg * mod.slowFire
}, },
onHealthChange() { //used with acid mod onHealthChange() { //used with acid mod
if (mod.isAcidDmg && mech.health > 0.8) { if (mod.isAcidDmg) {
mod.acidDmg = 0.5 if (mech.health > 0.8) {
if (!build.isCustomSelection) { mod.acidDmg = 0.5
setTimeout(function () { if (!build.isCustomSelection) {
if (document.getElementById("mod-acid")) document.getElementById("mod-acid").innerHTML = " (on)" setTimeout(function () {
}, 10); if (document.getElementById("mod-acid")) document.getElementById("mod-acid").innerHTML = " (on)"
} }, 10);
} else { }
mod.acidDmg = 0 } else {
if (!build.isCustomSelection) { mod.acidDmg = 0
setTimeout(function () { if (!build.isCustomSelection) {
if (document.getElementById("mod-acid")) document.getElementById("mod-acid").innerHTML = " (off)" setTimeout(function () {
}, 10); if (document.getElementById("mod-acid")) document.getElementById("mod-acid").innerHTML = " (off)"
}, 10);
}
} }
} }
// if (mod.isLowHealthDmg) {
// if (!build.isCustomSelection) {
// setTimeout(function () {
// if (document.getElementById("mod-low-health-damage")) document.getElementById("mod-low-health-damage").innerHTML = " +" + (((3 / (2 + Math.min(mech.health, 1))) - 1) * 100).toFixed(0) + "%"
// }, 10);
// }
// }
}, },
resetModText() {
setTimeout(function () {
if (document.getElementById("mod-acid")) document.getElementById("mod-acid").innerHTML = "";
if (document.getElementById("mod-low-health-damage")) document.getElementById("mod-low-health-damage").innerHTML = "";
}, 10);
},
mods: [{ mods: [{
name: "capacitor", name: "capacitor",
// nameInfo: "<span id='mod-capacitor'></span>", // nameInfo: "<span id='mod-capacitor'></span>",
@@ -178,7 +166,6 @@ const mod = {
}, },
{ {
name: "negative feedback", name: "negative feedback",
// nameInfo: "<span id='mod-low-health-damage'></span>",
description: "do extra <strong class='color-d'>damage</strong> at <strong>low health</strong><br><em>up to <strong>50%</strong> increase when near death</em>", description: "do extra <strong class='color-d'>damage</strong> at <strong>low health</strong><br><em>up to <strong>50%</strong> increase when near death</em>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -587,7 +574,7 @@ const mod = {
}, },
{ {
name: "Pauli exclusion", name: "Pauli exclusion",
description: `<strong>immune</strong> to <strong>harm</strong> for <strong>1</strong> second<br>activates after being <strong>harmed</strong> from a collision`, description: `after being <strong>harmed</strong> from a collision<br><strong>immune</strong> to <strong>harm</strong> for <strong>1</strong> second`,
maxCount: 9, maxCount: 9,
count: 0, count: 0,
allowed() { allowed() {
@@ -621,6 +608,11 @@ const mod = {
{ {
name: "entanglement", name: "entanglement",
nameInfo: "<span id = 'mod-entanglement'></span>", nameInfo: "<span id = 'mod-entanglement'></span>",
addNameInfo() {
setTimeout(function () {
game.boldActiveGunHUD();
}, 1000);
},
description: "<strong>16%</strong> less <strong>harm</strong> for each gun in your <strong>inventory</strong><br> while your <strong>first gun</strong> is equipped", description: "<strong>16%</strong> less <strong>harm</strong> for each gun in your <strong>inventory</strong><br> while your <strong>first gun</strong> is equipped",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -769,7 +761,7 @@ const mod = {
}, },
{ {
name: "negentropy", name: "negentropy",
description: "when below <strong>25%</strong> of <strong>maximum health</strong><br> <strong class='color-h'>heal</strong> <strong>1%</strong> of <strong>maximum health</strong> per second", description: "at the start of each <strong>level</strong><br><strong class='color-h'>heal</strong> up to <strong>50%</strong> of <strong>maximum health</strong>",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
allowed() { allowed() {
@@ -785,7 +777,7 @@ const mod = {
}, },
{ {
name: "crystallized armor", name: "crystallized armor",
description: "increase <strong>maximum</strong> <strong class='color-h'>health</strong> by <strong>4%</strong> for each<br>unused <strong>power up</strong> at the end of a <strong>level</strong>", description: "increase <strong>maximum</strong> <strong class='color-h'>health</strong> by <strong>5%</strong> for each<br>unused <strong>power up</strong> at the end of a <strong>level</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
@@ -815,23 +807,6 @@ const mod = {
mod.recursiveHealing = 1; mod.recursiveHealing = 1;
} }
}, },
{
name: "pair production",
description: "<strong>power ups</strong> overfill your <strong class='color-f'>energy</strong><br>temporarily gain <strong>twice</strong> your max <strong class='color-f'>energy</strong>",
maxCount: 1,
count: 0,
allowed() {
return true
},
requires: "",
effect: () => {
mod.isMassEnergy = true // used in mech.grabPowerUp
mech.energy = mech.maxEnergy * 2
},
remove() {
mod.isMassEnergy = false;
}
},
{ {
name: "bubble fusion", name: "bubble fusion",
description: "after destroying a mob's <strong>shield</strong><br>spawn <strong>3</strong> <strong class='color-h'>heals</strong>, <strong>ammo</strong>, or <strong class='color-r'>rerolls</strong>", description: "after destroying a mob's <strong>shield</strong><br>spawn <strong>3</strong> <strong class='color-h'>heals</strong>, <strong>ammo</strong>, or <strong class='color-r'>rerolls</strong>",
@@ -886,7 +861,7 @@ const mod = {
}, },
{ {
name: "supply chain", name: "supply chain",
description: "double your current <strong>ammo</strong> for all <strong>gun</strong>", description: "double your current <strong>ammo</strong> for all <strong>guns</strong>",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
isNonRefundable: true, isNonRefundable: true,
@@ -936,7 +911,7 @@ const mod = {
}, },
{ {
name: "cardinality", name: "cardinality",
description: "<strong>2</strong> extra <strong>choices</strong> when selecting <strong>power ups</strong>", description: "<strong>2</strong> extra <strong>choices</strong> for <strong class='color-m'>mods</strong>, <strong>guns</strong>, and <strong>fields</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
@@ -994,7 +969,7 @@ const mod = {
}, },
{ {
name: "many-worlds", name: "many-worlds",
description: "after choosing a <strong>gun</strong>, <strong>field</strong>, or <strong class='color-m'>mod</strong><br>spawn a <strong class='color-r'>reroll</strong>, if you have none", description: "after choosing a <strong class='color-m'>mod</strong>, <strong>gun</strong>, or <strong>field</strong><br>spawn a <strong class='color-r'>reroll</strong>, if you have none",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
@@ -1011,7 +986,12 @@ const mod = {
{ {
name: "anthropic principle", name: "anthropic principle",
nameInfo: "<span id = 'mod-anthropic'></span>", nameInfo: "<span id = 'mod-anthropic'></span>",
description: "<strong class='color-h'>heal</strong> to <strong>50%</strong> health instead of <strong>dying</strong><br>consumes <strong>1</strong> <strong class='color-r'>reroll</strong>", addNameInfo() {
setTimeout(function () {
powerUps.reroll.changeRerolls(0)
}, 1000);
},
description: "<strong class='color-h'>heal</strong> to <strong>60%</strong> health instead of <strong>dying</strong><br>consumes <strong>1</strong> <strong class='color-r'>reroll</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
@@ -1030,7 +1010,7 @@ const mod = {
}, },
{ {
name: "quantum immortality", name: "quantum immortality",
description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br>spawn <strong>3</strong> <strong class='color-r'>rerolls</strong>", description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br>spawn <strong>5</strong> <strong class='color-r'>rerolls</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
@@ -1039,9 +1019,9 @@ const mod = {
requires: "", requires: "",
effect() { effect() {
mod.isImmortal = true; mod.isImmortal = true;
powerUps.spawn(mech.pos.x, mech.pos.y, "reroll", false); for (let i = 0; i < 5; i++) {
powerUps.spawn(mech.pos.x, mech.pos.y, "reroll", false); powerUps.spawn(mech.pos.x, mech.pos.y, "reroll", false);
powerUps.spawn(mech.pos.x, mech.pos.y, "reroll", false); }
}, },
remove() { remove() {
mod.isImmortal = false; mod.isImmortal = false;
@@ -1143,6 +1123,9 @@ const mod = {
{ {
name: "fluoroantimonic acid", name: "fluoroantimonic acid",
nameInfo: "<span id='mod-acid'></span>", nameInfo: "<span id='mod-acid'></span>",
addNameInfo() {
mod.onHealthChange();
},
description: "each <strong>bullet</strong> does instant <strong class='color-p'>acid</strong> <strong class='color-d'>damage</strong><br><strong>active</strong> when you are above <strong>80%</strong> base health", description: "each <strong>bullet</strong> does instant <strong class='color-p'>acid</strong> <strong class='color-d'>damage</strong><br><strong>active</strong> when you are above <strong>80%</strong> base health",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -1153,7 +1136,6 @@ const mod = {
requires: "health above 80%", requires: "health above 80%",
effect() { effect() {
mod.isAcidDmg = true; mod.isAcidDmg = true;
mod.onHealthChange();
}, },
remove() { remove() {
mod.acidDmg = 0; mod.acidDmg = 0;
@@ -1697,6 +1679,22 @@ const mod = {
mod.isFastDrones = false mod.isFastDrones = false
} }
}, },
{
name: "superfluidity",
description: "<strong class='color-s'>freeze</strong> effects apply to mobs near it's target",
maxCount: 1,
count: 0,
allowed() {
return mod.haveGunCheck("ice IX") || mod.isIceCrystals || mod.isSporeFreeze || (mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && mod.isIceField)
},
requires: "a freeze effect",
effect() {
mod.isAoESlow = true
},
remove() {
mod.isAoESlow = false
}
},
{ {
name: "heavy water", name: "heavy water",
description: "<strong>ice IX</strong> is synthesized with an extra neutron<br>does <strong class='color-p'>radioactive</strong> <strong class='color-d'>damage</strong> over 3 seconds", description: "<strong>ice IX</strong> is synthesized with an extra neutron<br>does <strong class='color-p'>radioactive</strong> <strong class='color-d'>damage</strong> over 3 seconds",
@@ -1991,6 +1989,23 @@ const mod = {
mech.fieldShieldingScale = 1; mech.fieldShieldingScale = 1;
} }
}, },
{
name: "pair production",
description: "<strong>power ups</strong> overfill your <strong class='color-f'>energy</strong><br>temporarily gain <strong>3x</strong> your maximum <strong class='color-f'>energy</strong>",
maxCount: 1,
count: 0,
allowed() {
return mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing"
},
requires: "nano-scale manufacturing",
effect: () => {
mod.isMassEnergy = true // used in mech.grabPowerUp
mech.energy = mech.maxEnergy * 3
},
remove() {
mod.isMassEnergy = false;
}
},
{ {
name: "mycelium manufacturing", name: "mycelium manufacturing",
description: "<strong>nano-scale manufacturing</strong> is repurposed<br>excess <strong class='color-f'>energy</strong> used to grow <strong class='color-p' style='letter-spacing: 2px;'>spores</strong>", description: "<strong>nano-scale manufacturing</strong> is repurposed<br>excess <strong class='color-f'>energy</strong> used to grow <strong class='color-p' style='letter-spacing: 2px;'>spores</strong>",
@@ -2276,5 +2291,6 @@ const mod = {
isPulseAim: null, isPulseAim: null,
isSporeFreeze: null, isSporeFreeze: null,
isShotgunRecoil: null, isShotgunRecoil: null,
isHealLowHealth: null isHealLowHealth: null,
isAoESlow: null
} }

View File

@@ -476,7 +476,7 @@ const mech = {
if (mod.isDeathAvoid && powerUps.reroll.rerolls) { //&& Math.random() < 0.5 if (mod.isDeathAvoid && powerUps.reroll.rerolls) { //&& Math.random() < 0.5
powerUps.reroll.changeRerolls(-1) powerUps.reroll.changeRerolls(-1)
mech.energy = mech.maxEnergy * 0.5 mech.energy = mech.maxEnergy * 0.6
// if (mech.energy < 0.05) mech.energy = 0.05 // if (mech.energy < 0.05) mech.energy = 0.05
mech.immuneCycle = mech.cycle + 120 //disable this.immuneCycle bonus seconds mech.immuneCycle = mech.cycle + 120 //disable this.immuneCycle bonus seconds
game.makeTextLog("<span style='font-size:115%;'> <strong>death</strong> avoided<br><strong>1</strong> <strong class='color-r'>reroll</strong> consumed</span>", 420) game.makeTextLog("<span style='font-size:115%;'> <strong>death</strong> avoided<br><strong>1</strong> <strong class='color-r'>reroll</strong> consumed</span>", 420)
@@ -505,7 +505,7 @@ const mech = {
if (mech.health < 0 || isNaN(mech.health)) { if (mech.health < 0 || isNaN(mech.health)) {
if (mod.isDeathAvoid && powerUps.reroll.rerolls > 0) { //&& Math.random() < 0.5 if (mod.isDeathAvoid && powerUps.reroll.rerolls > 0) { //&& Math.random() < 0.5
powerUps.reroll.changeRerolls(-1) powerUps.reroll.changeRerolls(-1)
mech.health = mech.maxHealth * 0.5 mech.health = mech.maxHealth * 0.6
// if (mech.health < 0.05) mech.health = 0.05 // if (mech.health < 0.05) mech.health = 0.05
mech.immuneCycle = mech.cycle + 120 //disable this.immuneCycle bonus seconds mech.immuneCycle = mech.cycle + 120 //disable this.immuneCycle bonus seconds
game.makeTextLog("<span style='font-size:115%;'> <strong>death</strong> avoided<br><strong>1</strong> <strong class='color-r'>reroll</strong> consumed</span>", 420) game.makeTextLog("<span style='font-size:115%;'> <strong>death</strong> avoided<br><strong>1</strong> <strong class='color-r'>reroll</strong> consumed</span>", 420)
@@ -942,7 +942,7 @@ const mech = {
y: powerUp[i].velocity.y * 0.11 y: powerUp[i].velocity.y * 0.11
}); });
if (dist2 < 5000 && !game.isChoosing) { //use power up if it is close enough if (dist2 < 5000 && !game.isChoosing) { //use power up if it is close enough
if (mod.isMassEnergy) mech.energy = mech.maxEnergy * 2; if (mod.isMassEnergy) mech.energy = mech.maxEnergy * 3;
Matter.Body.setVelocity(player, { //player knock back, after grabbing power up Matter.Body.setVelocity(player, { //player knock back, after grabbing power up
x: player.velocity.x + ((powerUp[i].velocity.x * powerUp[i].mass) / player.mass) * 0.3, x: player.velocity.x + ((powerUp[i].velocity.x * powerUp[i].mass) / player.mass) * 0.3,
y: player.velocity.y + ((powerUp[i].velocity.y * powerUp[i].mass) / player.mass) * 0.3 y: player.velocity.y + ((powerUp[i].velocity.y * powerUp[i].mass) / player.mass) * 0.3
@@ -1950,7 +1950,7 @@ const mech = {
y: powerUp[i].velocity.y * 0.11 y: powerUp[i].velocity.y * 0.11
}); });
if (dist2 < 5000 && !game.isChoosing) { //use power up if it is close enough if (dist2 < 5000 && !game.isChoosing) { //use power up if it is close enough
if (mod.isMassEnergy) mech.energy = mech.maxEnergy * 2; if (mod.isMassEnergy) mech.energy = mech.maxEnergy * 3;
powerUp[i].effect(); powerUp[i].effect();
Matter.World.remove(engine.world, powerUp[i]); Matter.World.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1); powerUp.splice(i, 1);

View File

@@ -79,7 +79,7 @@ const powerUps = {
} }
return out return out
}, },
use(type) { use(type) { //runs when you actually reroll a list of selections, type can be field, gun, or mod
powerUps.reroll.changeRerolls(-1) powerUps.reroll.changeRerolls(-1)
powerUps[type].effect(); powerUps[type].effect();
}, },
@@ -218,7 +218,6 @@ const powerUps = {
choiceLog: [], //records all previous choice options choiceLog: [], //records all previous choice options
effect() { effect() {
function pick(skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { function pick(skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) {
let options = []; let options = [];
for (let i = 0; i < mod.mods.length; i++) { for (let i = 0; i < mod.mods.length; i++) {

View File

@@ -1466,20 +1466,20 @@ const spawn = {
// } // }
// }; // };
// }, // },
bomberBoss(x, y, radius = 85 + Math.ceil(Math.random() * 20)) { bomberBoss(x, y, radius = 80 + Math.floor(Math.random() * 15)) {
//boss that drops bombs from above and holds a set distance from player //boss that drops bombs from above and holds a set distance from player
mobs.spawn(x, y, 3, radius, "transparent"); mobs.spawn(x, y, 3, radius, "transparent");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
Matter.Body.setDensity(me, 0.0015 + 0.0004 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.0014 + 0.0003 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.stroke = "rgba(255,0,200)"; //used for drawGhost me.stroke = "rgba(255,0,200)"; //used for drawGhost
me.seeAtDistance2 = 1500000; me.seeAtDistance2 = 1500000;
me.fireFreq = Math.ceil(30 + 2000 / radius); me.fireFreq = Math.ceil(60 + 3000 / radius);
me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search
me.hoverElevation = 460 + (Math.random() - 0.5) * 200; //squared me.hoverElevation = 460 + (Math.random() - 0.5) * 200; //squared
me.hoverXOff = (Math.random() - 0.5) * 100; me.hoverXOff = (Math.random() - 0.5) * 100;
me.accelMag = Math.floor(10 * (Math.random() + 5)) * 0.00001 * game.accelScale; me.accelMag = Math.floor(10 * (Math.random() + 4.5)) * 0.00001 * game.accelScale;
me.g = 0.0002; //required if using 'gravity' // gravity called in hoverOverPlayer me.g = 0.0002; //required if using 'gravity' // gravity called in hoverOverPlayer
me.frictionStatic = 0; me.frictionStatic = 0;
me.friction = 0; me.friction = 0;
@@ -1578,7 +1578,7 @@ const spawn = {
this.explode(this.mass * 10); this.explode(this.mass * 10);
}; };
Matter.Body.setDensity(me, 0.0001); //normal is 0.001 Matter.Body.setDensity(me, 0.0001); //normal is 0.001
me.timeLeft = 240; me.timeLeft = 200;
me.g = 0.001; //required if using 'gravity' me.g = 0.001; //required if using 'gravity'
me.frictionAir = 0; me.frictionAir = 0;
me.restitution = 0.8; me.restitution = 0.8;
@@ -1592,6 +1592,58 @@ const spawn = {
this.timeLimit(); this.timeLimit();
}; };
}, },
bomb(x, y, radius = 6, sides = 5) {
mobs.spawn(x, y, sides, radius, "rgb(255,0,0)");
let me = mob[mob.length - 1];
me.stroke = "transparent";
me.onHit = function () {
this.explode(this.mass * 10);
};
me.onDeath = function () {
if (game.difficulty > 10) {
spawn.bullet(this.position.x, this.position.y, this.radius / 3, 5);
spawn.bullet(this.position.x, this.position.y, this.radius / 3, 5);
spawn.bullet(this.position.x, this.position.y, this.radius / 3, 5);
const mag = 8
const v1 = Vector.rotate({
x: 1,
y: 1
}, 2 * Math.PI * Math.random())
const v2 = Vector.rotate({
x: 1,
y: 1
}, 2 * Math.PI * Math.random())
const v3 = Vector.normalise(Vector.add(v1, v2)) //last vector is opposite the sum of the other two to look a bit like momentum is conserved
Matter.Body.setVelocity(mob[mob.length - 1], {
x: mag * v1.x,
y: mag * v1.y
});
Matter.Body.setVelocity(mob[mob.length - 2], {
x: mag * v2.x,
y: mag * v2.y
});
Matter.Body.setVelocity(mob[mob.length - 3], {
x: -mag * v3.x,
y: -mag * v3.y
});
}
}
Matter.Body.setDensity(me, 0.0001); //normal is 0.001
me.timeLeft = 95 + Math.floor(Math.random() * 15);
me.g = 0.001; //required if using 'gravity'
me.frictionAir = 0;
me.restitution = 1;
me.leaveBody = false;
me.dropPowerUp = false;
me.showHealthBar = false;
me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
me.do = function () {
this.gravity();
this.timeLimit();
};
},
sniper(x, y, radius = 35 + Math.ceil(Math.random() * 30)) { sniper(x, y, radius = 35 + Math.ceil(Math.random() * 30)) {
mobs.spawn(x, y, 3, radius, "transparent"); //"rgb(25,0,50)") mobs.spawn(x, y, 3, radius, "transparent"); //"rgb(25,0,50)")

View File

@@ -1,13 +1,29 @@
negentropy - heals player to 50% max health at the end of a level
crystallized armor - give 5% (was 4%) max health for a power up
mod - superfluidity: AoE freeze effect
bomberBoss's bombs split into 3 bombs on later levels
mod - pair production only works for nano-scale manufacturing, but gives 3x (up from 2x) max energy
press Z+X in testing mode to trigger player death
************** TODO - n-gon ************** ************** TODO - n-gon **************
plasma field gets longer as you hold it longer
mod - AoE radiation might work when the effect ends
or maybe just anytime another mob is near
wave beam: mod - longitudinal waves (bullets oscillate fast /slow not up/down)
trigger on crouch?
medium caliber gun in between minigun and rail gun
mod: electricity damages mobs that get near the bullet
get ammo back if it hits mobs
ammo returns to you if it misses
mob that flashes the player (makes the graphics not update for a couple seconds) mob that flashes the player (makes the graphics not update for a couple seconds)
held blocks aren't moving to the next level mod - do 50% more damage in close, but 50% less at a distance
only issue is setting held block to not collide
mod do 50% more damage in close, but 50% less at a distance
code it like mod.isFarAwayDmg code it like mod.isFarAwayDmg
have these mods disable each other have these mods disable each other