superfluidity
This commit is contained in:
@@ -1079,7 +1079,7 @@ const b = {
|
||||
plasmaBot(position = mech.pos) {
|
||||
const me = bullet.length;
|
||||
const dir = mech.angle;
|
||||
const RADIUS = 20
|
||||
const RADIUS = 21
|
||||
bullet[me] = Bodies.polygon(position.x, position.y, 5, RADIUS, {
|
||||
angle: dir,
|
||||
friction: 0,
|
||||
@@ -1115,7 +1115,7 @@ const b = {
|
||||
let closeDist = mod.isPlasmaRange * 1000;
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
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(body, this.position, mob[i].position).length === 0) {
|
||||
closeDist = DIST;
|
||||
|
||||
17
js/game.js
17
js/game.js
@@ -233,7 +233,10 @@ const game = {
|
||||
if (mod.mods[i].count > 0) {
|
||||
if (text) text += "<br>" //add a new line, but not on the first line
|
||||
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)`
|
||||
}
|
||||
}
|
||||
@@ -243,7 +246,7 @@ const game = {
|
||||
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="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>',
|
||||
makeTextLog(text, time = 180) {
|
||||
if (game.replaceTextLog) {
|
||||
@@ -400,6 +403,8 @@ const game = {
|
||||
// game.noCameraScroll()
|
||||
} else if (keys[85]) { // next level with U
|
||||
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.isHealLowHealth) {
|
||||
if (mech.health < mech.maxHealth * 0.25) {
|
||||
mech.addHealth(0.01 * mech.maxHealth)
|
||||
}
|
||||
}
|
||||
|
||||
if (!(game.cycle % 420)) { //once every 7 seconds
|
||||
fallCheck = function (who, save = false) {
|
||||
let i = who.length;
|
||||
@@ -1086,6 +1085,8 @@ const game = {
|
||||
enableConstructMode() {
|
||||
game.isConstructionMode = true;
|
||||
game.isAutoZoom = false;
|
||||
game.zoomScale = 2200;
|
||||
game.setZoom();
|
||||
|
||||
document.body.addEventListener("mouseup", (e) => {
|
||||
if (game.testing && game.constructMouseDownPosition) {
|
||||
|
||||
@@ -248,7 +248,6 @@ const build = {
|
||||
document.getElementById("difficulty-select").value = document.getElementById("difficulty-select-custom").value
|
||||
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
|
||||
});
|
||||
mod.resetModText();
|
||||
},
|
||||
reset() {
|
||||
build.isCustomSelection = true;
|
||||
|
||||
561
js/level.js
561
js/level.js
@@ -13,18 +13,16 @@ const level = {
|
||||
// game.enableConstructMode() //used to build maps in testing mode
|
||||
// level.difficultyIncrease(9)
|
||||
// mech.isStealth = true;
|
||||
// mod.giveMod("plasma-bot");
|
||||
// mod.giveMod("nail-bot");
|
||||
// mod.giveMod("laser-bot");
|
||||
// mod.giveMod("boom-bot");
|
||||
// mod.giveMod("supply chain");
|
||||
// b.giveGuns("pulse")
|
||||
b.giveGuns("ice IX")
|
||||
// mech.setField("plasma torch")
|
||||
|
||||
level.intro(); //starting level
|
||||
// level.bossRoom1()
|
||||
// level.testing();
|
||||
// level.stronghold()
|
||||
// level.template()
|
||||
// level.bosses();
|
||||
// level.stronghold()
|
||||
// level.satellite();
|
||||
// level.skyscrapers();
|
||||
// level.aerie();
|
||||
@@ -32,6 +30,7 @@ const level = {
|
||||
// level.warehouse();
|
||||
// level.highrise();
|
||||
// level.office();
|
||||
|
||||
} else {
|
||||
spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
|
||||
// spawn.pickList = ["focuser", "focuser"]
|
||||
@@ -61,245 +60,86 @@ const level = {
|
||||
|
||||
if (mod.isArmorFromPowerUps) {
|
||||
// for (let i = 0; i < powerUps.totalPowerUps; i++) {}
|
||||
mech.maxHealth += 0.04 * 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)
|
||||
mech.maxHealth += 0.05 * powerUps.totalPowerUps
|
||||
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++
|
||||
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
|
||||
},
|
||||
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
|
||||
//******************************************************************************************************************
|
||||
//******************************************************************************************************************
|
||||
//******************************************************************************************************************
|
||||
//******************************************************************************************************************
|
||||
bossRoom1() {
|
||||
level.custom = () => {
|
||||
level.playerExitCheck();
|
||||
};
|
||||
},
|
||||
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) {
|
||||
// if (target.velocity.y < 0) {
|
||||
// mech.undoCrouch();
|
||||
// mech.enterAir();
|
||||
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
|
||||
});
|
||||
}
|
||||
level.setPosToSpawn(0, -50); //normal spawn
|
||||
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
|
||||
level.exit.x = 1500;
|
||||
level.exit.y = -1875;
|
||||
level.defaultZoom = 1800
|
||||
game.zoomTransition(level.defaultZoom)
|
||||
document.body.style.backgroundColor = "#dcdcde";
|
||||
// powerUps.spawnStartingPowerUps(1475, -1175);
|
||||
// spawn.debris(750, -2200, 3700, 16); //16 debris per level
|
||||
// level.fill.push({ //foreground
|
||||
// x: 2500,
|
||||
// y: -1100,
|
||||
// width: 450,
|
||||
// height: 250,
|
||||
// color: "rgba(0,0,0,0.1)"
|
||||
// });
|
||||
// level.fillBG.push({ //background
|
||||
// x: 1300,
|
||||
// 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);
|
||||
},
|
||||
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
|
||||
}
|
||||
template() {
|
||||
level.custom = () => {
|
||||
level.playerExitCheck();
|
||||
};
|
||||
level.setPosToSpawn(0, -50); //normal spawn
|
||||
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
|
||||
level.exit.x = 1500;
|
||||
level.exit.y = -1875;
|
||||
level.defaultZoom = 1800
|
||||
game.zoomTransition(level.defaultZoom)
|
||||
document.body.style.backgroundColor = "#dcdcde";
|
||||
// powerUps.spawnStartingPowerUps(1475, -1175);
|
||||
// spawn.debris(750, -2200, 3700, 16); //16 debris per level
|
||||
// level.fill.push({ //foreground
|
||||
// x: 2500,
|
||||
// y: -1100,
|
||||
// width: 450,
|
||||
// height: 250,
|
||||
// color: "rgba(0,0,0,0.1)"
|
||||
// });
|
||||
// level.fillBG.push({ //background
|
||||
// x: 1300,
|
||||
// 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);
|
||||
},
|
||||
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]);
|
||||
}
|
||||
},
|
||||
//******************************************************************************************************************
|
||||
//******************************************************************************************************************
|
||||
//******************************************************************************************************************
|
||||
//******************************************************************************************************************
|
||||
testing() {
|
||||
level.custom = () => {
|
||||
level.playerExitCheck();
|
||||
@@ -358,14 +198,14 @@ const level = {
|
||||
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
|
||||
spawn.boost(1500, 0, 900);
|
||||
|
||||
// spawn.bomberBoss(2900, -500)
|
||||
spawn.bomberBoss(2900, -500)
|
||||
// spawn.launcherBoss(1200, -500)
|
||||
// spawn.laserTargetingBoss(1600, -400)
|
||||
// spawn.spawner(1600, -500)
|
||||
// spawn.sniper(1700, -120, 50)
|
||||
spawn.sniper(1400, -120)
|
||||
spawn.sniper(1800, -120)
|
||||
spawn.sniper(2200, -120)
|
||||
// spawn.sniper(1400, -120)
|
||||
// spawn.sniper(1800, -120)
|
||||
// spawn.sniper(2200, -120)
|
||||
// spawn.cellBossCulture(1600, -500)
|
||||
// spawn.shooter(1600, -500)
|
||||
// spawn.striker(1600, -500)
|
||||
@@ -2056,4 +1896,239 @@ const level = {
|
||||
|
||||
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]);
|
||||
}
|
||||
},
|
||||
};
|
||||
57
js/mob.js
57
js/mob.js
@@ -44,46 +44,63 @@ const mobs = {
|
||||
}
|
||||
},
|
||||
statusSlow(who, cycles = 60) {
|
||||
if (!who.shield && !who.isShielded && !mech.isBodiesAsleep) {
|
||||
if (who.isBoss) {
|
||||
cycles = Math.floor(cycles * 0.25)
|
||||
applySlow(who)
|
||||
//look for mobs near the target
|
||||
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
|
||||
let i = who.status.length
|
||||
game.drawList.push({
|
||||
x: who.position.x,
|
||||
y: who.position.y,
|
||||
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 (who.status[i].type === "slow") who.status.splice(i, 1);
|
||||
if (target.status[i].type === "slow") target.status.splice(i, 1); //remove other "slow" effects on this mob
|
||||
}
|
||||
who.status.push({
|
||||
target.status.push({
|
||||
effect() {
|
||||
Matter.Body.setVelocity(who, {
|
||||
Matter.Body.setVelocity(target, {
|
||||
x: 0,
|
||||
y: 0
|
||||
});
|
||||
Matter.Body.setAngularVelocity(who, 0);
|
||||
Matter.Body.setAngularVelocity(target, 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.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(who.vertices[0].x, who.vertices[0].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 = who.fill
|
||||
ctx.fillStyle = target.fill
|
||||
ctx.fill();
|
||||
},
|
||||
type: "slow",
|
||||
endCycle: game.cycle + cycles,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
statusStun(who, cycles = 180) {
|
||||
if (!who.shield && !who.isShielded && !mech.isBodiesAsleep) {
|
||||
Matter.Body.setVelocity(who, {
|
||||
x: who.velocity.x * 0.5,
|
||||
y: who.velocity.y * 0.5
|
||||
x: who.velocity.x * 0.8,
|
||||
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
|
||||
let i = who.status.length
|
||||
while (i--) {
|
||||
@@ -97,7 +114,7 @@ const mobs = {
|
||||
x: who.position.x + 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.moveTo(who.vertices[0].x, who.vertices[0].y);
|
||||
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(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
|
||||
Matter.Body.setAngularVelocity(mob[mob.length - 1], (Math.random() - 0.5) * 0.5);
|
||||
Matter.Body.setVelocity(mob[mob.length - 1], {
|
||||
@@ -1000,7 +1017,7 @@ const mobs = {
|
||||
}
|
||||
}
|
||||
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)
|
||||
} else if (Math.random() < 0.25) {
|
||||
b.nailBot(this.position)
|
||||
|
||||
106
js/mods.js
106
js/mods.js
@@ -80,7 +80,8 @@ const mod = {
|
||||
return dmg * mod.slowFire
|
||||
},
|
||||
onHealthChange() { //used with acid mod
|
||||
if (mod.isAcidDmg && mech.health > 0.8) {
|
||||
if (mod.isAcidDmg) {
|
||||
if (mech.health > 0.8) {
|
||||
mod.acidDmg = 0.5
|
||||
if (!build.isCustomSelection) {
|
||||
setTimeout(function () {
|
||||
@@ -95,21 +96,8 @@ const mod = {
|
||||
}, 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: [{
|
||||
name: "capacitor",
|
||||
// nameInfo: "<span id='mod-capacitor'></span>",
|
||||
@@ -178,7 +166,6 @@ const mod = {
|
||||
},
|
||||
{
|
||||
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>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -587,7 +574,7 @@ const mod = {
|
||||
},
|
||||
{
|
||||
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,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -621,6 +608,11 @@ const mod = {
|
||||
{
|
||||
name: "entanglement",
|
||||
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",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -769,7 +761,7 @@ const mod = {
|
||||
},
|
||||
{
|
||||
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,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -785,7 +777,7 @@ const mod = {
|
||||
},
|
||||
{
|
||||
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,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -815,23 +807,6 @@ const mod = {
|
||||
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",
|
||||
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",
|
||||
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,
|
||||
count: 0,
|
||||
isNonRefundable: true,
|
||||
@@ -936,7 +911,7 @@ const mod = {
|
||||
},
|
||||
{
|
||||
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,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -994,7 +969,7 @@ const mod = {
|
||||
},
|
||||
{
|
||||
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,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -1011,7 +986,12 @@ const mod = {
|
||||
{
|
||||
name: "anthropic principle",
|
||||
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,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -1030,7 +1010,7 @@ const mod = {
|
||||
},
|
||||
{
|
||||
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,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -1039,9 +1019,9 @@ const mod = {
|
||||
requires: "",
|
||||
effect() {
|
||||
mod.isImmortal = true;
|
||||
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() {
|
||||
mod.isImmortal = false;
|
||||
@@ -1143,6 +1123,9 @@ const mod = {
|
||||
{
|
||||
name: "fluoroantimonic acid",
|
||||
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",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -1153,7 +1136,6 @@ const mod = {
|
||||
requires: "health above 80%",
|
||||
effect() {
|
||||
mod.isAcidDmg = true;
|
||||
mod.onHealthChange();
|
||||
},
|
||||
remove() {
|
||||
mod.acidDmg = 0;
|
||||
@@ -1697,6 +1679,22 @@ const mod = {
|
||||
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",
|
||||
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;
|
||||
}
|
||||
},
|
||||
{
|
||||
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",
|
||||
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,
|
||||
isSporeFreeze: null,
|
||||
isShotgunRecoil: null,
|
||||
isHealLowHealth: null
|
||||
isHealLowHealth: null,
|
||||
isAoESlow: null
|
||||
}
|
||||
@@ -476,7 +476,7 @@ const mech = {
|
||||
if (mod.isDeathAvoid && powerUps.reroll.rerolls) { //&& Math.random() < 0.5
|
||||
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
|
||||
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)
|
||||
@@ -505,7 +505,7 @@ const mech = {
|
||||
if (mech.health < 0 || isNaN(mech.health)) {
|
||||
if (mod.isDeathAvoid && powerUps.reroll.rerolls > 0) { //&& Math.random() < 0.5
|
||||
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
|
||||
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)
|
||||
@@ -942,7 +942,7 @@ const mech = {
|
||||
y: powerUp[i].velocity.y * 0.11
|
||||
});
|
||||
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
|
||||
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
|
||||
@@ -1950,7 +1950,7 @@ const mech = {
|
||||
y: powerUp[i].velocity.y * 0.11
|
||||
});
|
||||
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();
|
||||
Matter.World.remove(engine.world, powerUp[i]);
|
||||
powerUp.splice(i, 1);
|
||||
|
||||
@@ -79,7 +79,7 @@ const powerUps = {
|
||||
}
|
||||
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[type].effect();
|
||||
},
|
||||
@@ -218,7 +218,6 @@ const powerUps = {
|
||||
choiceLog: [], //records all previous choice options
|
||||
effect() {
|
||||
|
||||
|
||||
function pick(skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) {
|
||||
let options = [];
|
||||
for (let i = 0; i < mod.mods.length; i++) {
|
||||
|
||||
62
js/spawn.js
62
js/spawn.js
@@ -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
|
||||
mobs.spawn(x, y, 3, radius, "transparent");
|
||||
let me = mob[mob.length - 1];
|
||||
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.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.hoverElevation = 460 + (Math.random() - 0.5) * 200; //squared
|
||||
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.frictionStatic = 0;
|
||||
me.friction = 0;
|
||||
@@ -1578,7 +1578,7 @@ const spawn = {
|
||||
this.explode(this.mass * 10);
|
||||
};
|
||||
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.frictionAir = 0;
|
||||
me.restitution = 0.8;
|
||||
@@ -1592,6 +1592,58 @@ const spawn = {
|
||||
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)) {
|
||||
mobs.spawn(x, y, 3, radius, "transparent"); //"rgb(25,0,50)")
|
||||
|
||||
24
todo.txt
24
todo.txt
@@ -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 **************
|
||||
|
||||
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)
|
||||
|
||||
held blocks aren't moving to the next level
|
||||
only issue is setting held block to not collide
|
||||
|
||||
mod do 50% more damage in close, but 50% less at a distance
|
||||
mod - do 50% more damage in close, but 50% less at a distance
|
||||
code it like mod.isFarAwayDmg
|
||||
have these mods disable each other
|
||||
|
||||
|
||||
Reference in New Issue
Block a user