diff --git a/js/bullet.js b/js/bullet.js
index 6e85e41..2dbe576 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -740,6 +740,7 @@ const b = {
const DIST = Vector.magnitude(TARGET_VECTOR);
if (DIST < closeDist) {
if (DIST < 60) { //eat the power up if close enough
+ powerUps.onPickUp();
powerUp[i].effect();
Matter.World.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1);
@@ -988,6 +989,7 @@ const b = {
const dir = mech.angle;
const RADIUS = (12 + 4 * Math.random())
bullet[me] = Bodies.polygon(position.x, position.y, 4, RADIUS, {
+ isBot: true,
angle: dir,
friction: 0,
frictionStatic: 0,
@@ -1043,6 +1045,7 @@ const b = {
const dir = mech.angle;
const RADIUS = (10 + 5 * Math.random())
bullet[me] = Bodies.polygon(position.x, position.y, 6, RADIUS, {
+ isBot: true,
angle: dir,
friction: 0,
frictionStatic: 0,
@@ -1098,6 +1101,7 @@ const b = {
const dir = mech.angle;
const RADIUS = 21
bullet[me] = Bodies.polygon(position.x, position.y, 5, RADIUS, {
+ isBot: true,
angle: dir,
friction: 0,
frictionStatic: 0,
@@ -1288,6 +1292,7 @@ const b = {
const dir = mech.angle;
const RADIUS = (7 + 2 * Math.random())
bullet[me] = Bodies.polygon(position.x, position.y, 4, RADIUS, {
+ isBot: true,
angle: dir,
friction: 0,
frictionStatic: 0,
@@ -1364,6 +1369,7 @@ const b = {
const dir = mech.angle;
const RADIUS = (14 + 6 * Math.random())
bullet[me] = Bodies.polygon(position.x, position.y, 3, RADIUS, {
+ isBot: true,
angle: dir,
friction: 0,
frictionStatic: 0,
@@ -1391,11 +1397,6 @@ const b = {
},
onEnd() {},
do() {
- //move in a circle
- // const radius = 1.5
- // this.offPlayer.x -= radius * Math.cos(game.cycle * 0.02)
- // this.offPlayer.y -= radius * Math.sin(game.cycle * 0.02)
-
const playerPos = Vector.add(Vector.add(this.offPlayer, mech.pos), Vector.mult(player.velocity, 20)) //also include an offset unique to this bot to keep many bots spread out
const farAway = Math.max(0, (Vector.magnitude(Vector.sub(this.position, playerPos))) / this.followRange) //linear bounding well
const mag = Math.min(farAway, 4) * this.mass * this.acceleration
@@ -1405,7 +1406,6 @@ const b = {
x: this.velocity.x * 0.95,
y: this.velocity.y * 0.95
});
-
//find targets
if (!(game.cycle % this.lookFrequency) && !mech.isStealth) {
this.lockedOn = null;
@@ -1420,7 +1420,6 @@ const b = {
this.lockedOn = mob[i]
}
}
-
//randomize position relative to player
if (Math.random() < 0.15) {
this.offPlayer = {
@@ -1429,7 +1428,6 @@ const b = {
}
}
}
-
//hit target with laser
if (this.lockedOn && this.lockedOn.alive && mech.energy > 0.15) {
mech.energy -= 0.0014 * mod.isLaserDiode
@@ -1526,12 +1524,11 @@ const b = {
fire() {
const me = bullet.length;
const dir = mech.angle + (Math.random() - 0.5) * ((mech.crouch) ? 0.01 : 0.1);
- bullet[me] = Bodies.rectangle(mech.pos.x + 23 * Math.cos(mech.angle), mech.pos.y + 23 * Math.sin(mech.angle), 20 * mod.bulletSize, 6 * mod.bulletSize, b.fireAttributes(dir));
-
+ bullet[me] = Bodies.rectangle(mech.pos.x + 23 * Math.cos(mech.angle), mech.pos.y + 23 * Math.sin(mech.angle), 20 * mod.bulletSize * mod.highCaliber, 6 * mod.bulletSize, b.fireAttributes(dir));
//fire delay decreases as you hold fire, down to 3 from 15
if (this.nextFireCycle + 1 < mech.cycle) this.startingHoldCycle = mech.cycle //reset if not constantly firing
- const CD = Math.max(11 - 0.06 * (mech.cycle - this.startingHoldCycle), 2) //CD scales with cycles fire is held down
+ const CD = Math.max(11 - 0.06 * (mech.cycle - this.startingHoldCycle), 2) * mod.highCaliber //CD scales with cycles fire is held down
this.nextFireCycle = mech.cycle + CD * b.fireCD //predict next fire cycle if the fire button is held down
b.fireProps(CD, mech.crouch ? 38 : 34, dir, me); //cd , speed
// b.fireProps(mech.crouch ? 7 : 4, mech.crouch ? 40 : 34, dir, me); //cd , speed
@@ -1583,8 +1580,6 @@ const b = {
player.force.y -= knock * Math.sin(mech.angle) * 0.3 //reduce knock back in vertical direction to stop super jumps
}
-
-
b.muzzleFlash(35);
if (mod.isNailShot) {
for (let i = 0; i < 14; i++) {
@@ -1635,8 +1630,8 @@ const b = {
num: 5,
isEasyToAim: true,
fire() {
- const SPEED = mech.crouch ? 40 : 30
- mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 28 : 20) * b.fireCD); // cool down
+ const SPEED = mech.crouch ? 43 : 32
+ mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 25 : 18) * b.fireCD); // cool down
if (mod.oneSuperBall) {
let dir = mech.angle
const me = bullet.length;
@@ -1649,7 +1644,7 @@ const b = {
// Matter.Body.setDensity(bullet[me], 0.0001);
bullet[me].endCycle = game.cycle + Math.floor((300 + 60 * Math.random()) * mod.isBulletsLastLonger);
bullet[me].minDmgSpeed = 0;
- bullet[me].restitution = 0.999;
+ bullet[me].restitution = 1;
bullet[me].friction = 0;
bullet[me].do = function () {
this.force.y += this.mass * 0.001;
@@ -1663,7 +1658,7 @@ const b = {
let dir = mech.angle - SPREAD * (mod.superBallNumber - 1) / 2;
for (let i = 0; i < mod.superBallNumber; i++) {
const me = bullet.length;
- bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 12, 7 * mod.bulletSize, b.fireAttributes(dir, false));
+ bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 12, 7.5 * mod.bulletSize, b.fireAttributes(dir, false));
World.add(engine.world, bullet[me]); //add bullet to world
Matter.Body.setVelocity(bullet[me], {
x: SPEED * Math.cos(dir),
@@ -1927,7 +1922,7 @@ const b = {
name: "missiles",
description: "launch missiles that accelerate towards mobs
explodes when near target",
ammo: 0,
- ammoPack: 4,
+ ammoPack: 5,
have: false,
isEasyToAim: true,
fireCycle: 0,
@@ -2094,7 +2089,7 @@ const b = {
bullet[me].restitution = 0.2;
bullet[me].friction = 0.3;
bullet[me].endCycle = Infinity
- bullet[me].explodeRad = 440 + Math.floor(Math.random() * 30);
+ bullet[me].explodeRad = 450 + Math.floor(Math.random() * 30);
bullet[me].onEnd = function () {
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
@@ -2218,7 +2213,7 @@ const b = {
bullet[me].restitution = 0;
bullet[me].minDmgSpeed = 0;
bullet[me].damageRadius = 100;
- bullet[me].maxDamageRadius = (425 + 125 * Math.random()) * (mod.isNeutronImmune ? 1.2 : 1)
+ bullet[me].maxDamageRadius = (435 + 150 * Math.random()) * (mod.isNeutronImmune ? 1.2 : 1)
bullet[me].stuckTo = null;
bullet[me].stuckToRelativePosition = null;
bullet[me].onDmg = function () {};
@@ -2283,8 +2278,6 @@ const b = {
} else {
const bodyCollisions = Matter.Query.collides(this, body)
if (bodyCollisions.length) {
-
-
if (!bodyCollisions[0].bodyA.isNotSticky) {
onCollide(this)
this.stuckTo = bodyCollisions[0].bodyA
@@ -2329,7 +2322,6 @@ const b = {
this.endCycle = 0;
} else {
//aoe damage to player
-
if (!mod.isNeutronImmune && Vector.magnitude(Vector.sub(player.position, this.position)) < this.damageRadius) {
const DRAIN = 0.0015
if (mech.energy > DRAIN) {
@@ -2380,7 +2372,7 @@ const b = {
x: speed * Math.cos(mech.angle),
y: speed * Math.sin(mech.angle)
}, 0, mod.isMineAmmoBack)
- mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 60 : 20) * b.fireCD); // cool down
+ mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 50 : 25) * b.fireCD); // cool down
}
},
{
@@ -2508,7 +2500,7 @@ const b = {
name: "drones",
description: "deploy drones that crash into mobs
crashes reduce their lifespan by 1 second",
ammo: 0,
- ammoPack: 14,
+ ammoPack: 15,
have: false,
isEasyToAim: true,
fire() {
@@ -2621,7 +2613,10 @@ const b = {
this.force.y += this.mass * 0.0003 / this.charge; // low gravity that scales with charge
}
}
-
+ if (mod.isRailTimeSlow) {
+ game.fpsCap = game.fpsCapDefault
+ game.fpsInterval = 1000 / game.fpsCap;
+ }
Matter.Body.scale(this, 8000, 8000) // show the bullet by scaling it up (don't judge me... I know this is a bad way to do it)
this.endCycle = game.cycle + 140
@@ -2672,7 +2667,12 @@ const b = {
let chargeRate = (mech.crouch) ? 0.975 : 0.987
chargeRate *= Math.pow(b.fireCD, 0.03)
this.charge = this.charge * chargeRate + (1 - chargeRate) // this.charge converges to 1
- mech.energy -= (this.charge - lastCharge) * 0.28 //energy drain is proportional to charge gained, but doesn't stop normal mech.fieldRegen
+ if (mod.isRailTimeSlow) {
+ game.fpsCap = 30 //new fps
+ game.fpsInterval = 1000 / game.fpsCap;
+ } else {
+ mech.energy -= (this.charge - lastCharge) * 0.28 //energy drain is proportional to charge gained, but doesn't stop normal mech.fieldRegen
+ }
//draw targeting
let best;
diff --git a/js/engine.js b/js/engine.js
index 12ddd35..2109204 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -205,6 +205,7 @@ function collisionChecks(event) {
if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) {
// const dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)));
let dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)))
+ console.log(dmg)
if (mod.isCrit && !mob[k].seePlayer.recall && !mob[k].shield) dmg *= 5
mob[k].foundPlayer();
mob[k].damage(dmg);
diff --git a/js/game.js b/js/game.js
index c2725da..dd9047c 100644
--- a/js/game.js
+++ b/js/game.js
@@ -39,6 +39,7 @@ const game = {
b.bulletDraw();
b.bulletDo();
game.drawCircle();
+ level.customTopLayer();
// game.clip();
ctx.restore();
game.drawCursor();
@@ -67,6 +68,7 @@ const game = {
game.draw.testing();
game.drawCircle();
game.constructCycle()
+ level.customTopLayer();
ctx.restore();
game.testingOutput();
game.drawCursor();
@@ -691,6 +693,9 @@ const game = {
mech.holdingTarget.collisionFilter.category = 0;
mech.holdingTarget.collisionFilter.mask = 0;
}
+ //set fps back to default
+ game.fpsCap = game.fpsCapDefault
+ game.fpsInterval = 1000 / game.fpsCap;
},
getCoords: {
//used when building maps, outputs a draw rect command to console, only works in testing mode
@@ -735,12 +740,16 @@ const game = {
x: level.enter.x + 50,
y: level.enter.y - 20
});
- // Matter.Body.setPosition(player, {
- // x: player.position.x,
- // y: -7000
- // });
- // game.noCameraScroll()
-
+ // move bots
+ for (let i = 0; i < bullet.length; i++) {
+ if (bullet[i].isBot) {
+ Matter.Body.setPosition(bullet[i], player.position);
+ Matter.Body.setVelocity(bullet[i], {
+ x: 0,
+ y: 0
+ });
+ }
+ }
if (game.difficultyMode === 2) mech.damage(0.3);
if (game.difficultyMode === 1) mech.damage(0.1);
mech.energy = 0;
diff --git a/js/level.js b/js/level.js
index 0ffa367..a58b4fe 100644
--- a/js/level.js
+++ b/js/level.js
@@ -12,18 +12,18 @@ const level = {
if (build.isURLBuild && level.levelsCleared === 0) build.onLoadPowerUps();
if (level.levelsCleared === 0) { //this code only runs on the first level
// level.difficultyIncrease(4)
- // game.enableConstructMode() //used to build maps in testing mode
+ game.enableConstructMode() //used to build maps in testing mode
+ // game.zoomScale = 1000;
+ // game.setZoom();
// mech.isStealth = true;
- // mod.giveMod("bot fabrication");
+ // mod.giveMod("nail-bot");
// b.giveGuns("ice IX")
// mech.setField("plasma torch")
- level.intro(); //starting level
- // level.sewers();
// level.testing();
- // level.template()
- // level.bosses();
- // level.stronghold()
+ // level.intro(); //starting level
+ level.testChamber()
+ // level.sewers();
// level.satellite();
// level.skyscrapers();
// level.aerie();
@@ -31,7 +31,9 @@ const level = {
// level.warehouse();
// level.highrise();
// level.office();
-
+ // level.bosses();
+ // level.template()
+ // level.stronghold() //fan level
} else {
spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
// spawn.pickList = ["focuser", "focuser"]
@@ -43,24 +45,12 @@ const level = {
game.setZoom();
level.addToWorld(); //add bodies to game engine
game.draw.setPaths();
- for (let i = 0; i < mod.laserBotCount; i++) {
- b.laserBot()
- }
- for (let i = 0; i < mod.nailBotCount; i++) {
- b.nailBot()
- }
- for (let i = 0; i < mod.foamBotCount; i++) {
- b.foamBot()
- }
- for (let i = 0; i < mod.boomBotCount; i++) {
- b.boomBot()
- }
- for (let i = 0; i < mod.plasmaBotCount; i++) {
- b.plasmaBot()
- }
-
+ for (let i = 0; i < mod.laserBotCount; i++) b.laserBot()
+ for (let i = 0; i < mod.nailBotCount; i++) b.nailBot()
+ for (let i = 0; i < mod.foamBotCount; i++) b.foamBot()
+ for (let i = 0; i < mod.boomBotCount; i++) b.boomBot()
+ for (let i = 0; i < mod.plasmaBotCount; i++) b.plasmaBot()
if (mod.isArmorFromPowerUps) {
- // for (let i = 0; i < powerUps.totalPowerUps; i++) {}
mech.maxHealth += 0.05 * powerUps.totalPowerUps
if (powerUps.totalPowerUps) game.makeTextLog(" max health increased by " + (0.05 * powerUps.totalPowerUps * 100).toFixed(0) + "%", 300)
}
@@ -69,140 +59,249 @@ const level = {
mech.displayHealth();
}
},
+ custom() {},
+ customTopLayer() {},
//******************************************************************************************************************
//******************************************************************************************************************
//******************************************************************************************************************
//******************************************************************************************************************
- rotor(x, y, rotate = 0, radius = 900, width = 50, density = 0.0005) {
- const rotor1 = Matter.Bodies.rectangle(x, y, width, radius, {
- density: density,
- isNotSticky: true,
- isNotHoldable: true
- });
- const rotor2 = Matter.Bodies.rectangle(x, y, width, radius, {
- angle: Math.PI / 2,
- density: density,
- isNotSticky: true,
- isNotHoldable: true
- });
- rotor = Body.create({ //combine rotor1 and rotor2
- parts: [rotor1, rotor2],
- restitution: 0,
- collisionFilter: {
- category: cat.body,
- mask: cat.body | cat.mob | cat.mobBullet | cat.mobShield | cat.powerUp | cat.player | cat.bullet
- },
- });
- Matter.Body.setPosition(rotor, {
- x: x,
- y: y
- });
- World.add(engine.world, [rotor]);
- body[body.length] = rotor1
- body[body.length] = rotor2
+ portal(centerA, angleA, centerB, angleB) {
+ const width = 30
+ const height = 150
+ const mapWidth = 200
+ const unitA = Matter.Vector.rotate({
+ x: 1,
+ y: 0
+ }, angleA)
+ const unitB = Matter.Vector.rotate({
+ x: 1,
+ y: 0
+ }, angleB)
- setTimeout(function () {
- rotor.collisionFilter.category = cat.body;
- rotor.collisionFilter.mask = cat.body | cat.player | cat.bullet | cat.mob | cat.mobBullet //| cat.map
- }, 1000);
-
- const constraint = Constraint.create({ //fix rotor in place, but allow rotation
- pointA: {
- x: x,
- y: y
- },
- bodyB: rotor
- });
- World.add(engine.world, constraint);
-
- if (rotate) {
- rotor.rotate = function () {
- if (!mech.isBodiesAsleep) {
- Matter.Body.applyForce(rotor, {
- x: rotor.position.x + 100,
- y: rotor.position.y + 100
- }, {
- x: rotate * rotor.mass,
- y: 0
- })
- } else {
- Matter.Body.setAngularVelocity(rotor, 0);
- }
+ draw = function () {
+ ctx.beginPath(); //portal
+ sensor = this.vertices;
+ ctx.moveTo(sensor[0].x, sensor[0].y);
+ for (let i = 1; i < sensor.length; ++i) {
+ ctx.lineTo(sensor[i].x, sensor[i].y);
}
+ ctx.fillStyle = this.color
+ ctx.fill();
}
- composite[composite.length] = rotor
- return rotor
- },
- button(x, y, width = 70) {
- spawn.mapVertex(x + 35, y + 2, "70 10 -70 10 -40 -10 40 -10");
- return {
- isUp: false,
- min: {
- x: x,
- y: y - 15
- },
- max: {
- x: x + width,
- y: y - 5
- },
- width: width,
- height: 20,
- query() {
- if (Matter.Query.region(body, this).length === 0 && Matter.Query.region([player], this).length === 0) {
- this.isUp = true;
+ query = function () {
+ if (Matter.Query.collides(this, [player]).length === 0) { //not touching player
+ if (player.isInPortal === this) player.isInPortal = null
+ } else if (player.isInPortal !== this) { //touching player
+ //teleport
+ player.isInPortal = this.portalPair
+ Matter.Body.setPosition(player, this.portalPair.position);
+ //rotate velocity
+ // const unit = Vector.normalise(Vector.rotate(player.velocity, this.angle - this.portalPair.angle + Math.PI)) //rotate and flip velocity
+ // const mag = Math.max(20, Math.min(50, Vector.magnitude(player.velocity))) //20 is lowest speed, 50 is highest speed
+ // const v = Vector.mult(unit, mag)
+
+ let mag
+ if (this.angle === -Math.PI / 2) {
+ //portal that fires the player up
+ mag = Math.max(10, Math.min(50, player.velocity.y * 0.8)) + 11
} else {
- this.isUp = false;
+ mag = Math.max(3, Math.min(50, Vector.magnitude(player.velocity)))
}
- },
- draw() {
- ctx.fillStyle = "hsl(0, 100%, 70%)"
- if (this.isUp) {
- ctx.fillRect(this.min.x, this.min.y - 10, this.width, 20)
- } else {
- ctx.fillRect(this.min.x, this.min.y, this.width, 25)
- }
- }
- }
- },
- hazard(x, y, width, height, damage = 0.0005, color = "hsl(160, 100%, 35%)") {
- return {
- min: {
- x: x,
- y: y
- },
- max: {
- x: x + width,
- y: y + height
- },
- width: width,
- height: height,
- maxHeight: height,
- query() {
- if (this.height > 0 && Matter.Query.region([player], this).length && !mech.isStealth) {
- mech.damage(damage)
- const drain = 0.005
- if (mech.energy > drain) mech.energy -= drain
- }
- },
- draw() {
- ctx.fillStyle = color
- ctx.fillRect(this.min.x, this.min.y, this.width, this.height)
- },
- level(isFill) {
- const growSpeed = 1
- if (isFill) {
- if (this.height < this.maxHeight) {
- this.height += growSpeed
- this.min.y -= growSpeed
- this.max.y = this.min.y + this.height
+ console.log(mag)
+ const v = Vector.mult(this.portalPair.unit, mag)
+ Matter.Body.setVelocity(player, v);
+ mech.buttonCD_jump = 0 //disable short jumps when letting go of jump key
+ // move bots to follow player
+ for (let i = 0; i < bullet.length; i++) {
+ if (bullet[i].isBot) {
+ Matter.Body.setPosition(bullet[i], this.portalPair.portal.position);
+ Matter.Body.setVelocity(bullet[i], {
+ x: 0,
+ y: 0
+ });
}
- } else if (this.height > 0) {
- this.height -= growSpeed
- this.min.y += growSpeed
- this.max.y = this.min.y + this.height
}
}
}
+
+ const portalA = Bodies.rectangle(centerA.x, centerA.y, width, height, {
+ isSensor: true,
+ angle: angleA,
+ color: "hsla(197, 100%, 50%,0.7)",
+ draw: draw,
+ });
+ const portalB = Bodies.rectangle(centerB.x, centerB.y, width, height, {
+ isSensor: true,
+ angle: angleB,
+ color: "hsla(29, 100%, 50%, 0.7)",
+ draw: draw
+ });
+ const mapA = Bodies.rectangle(centerA.x - 0.5 * unitA.x * mapWidth, centerA.y - 0.5 * unitA.y * mapWidth, mapWidth, height + 100, {
+ collisionFilter: {
+ category: cat.map,
+ mask: cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
+ },
+ unit: unitA,
+ angle: angleA,
+ color: game.draw.mapFill,
+ draw: draw,
+ query: query,
+ lastPortalCycle: 0
+ });
+ Matter.Body.setStatic(mapA, true); //make static
+ World.add(engine.world, mapA); //add to world
+
+ const mapB = Bodies.rectangle(centerB.x - 0.5 * unitB.x * mapWidth, centerB.y - 0.5 * unitB.y * mapWidth, mapWidth, height + 100, {
+ collisionFilter: {
+ category: cat.map,
+ mask: cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
+ },
+ unit: unitB,
+ angle: angleB,
+ color: game.draw.mapFill,
+ draw: draw,
+ query: query,
+ lastPortalCycle: 0
+ });
+ Matter.Body.setStatic(mapB, true); //make static
+ World.add(engine.world, mapB); //add to world
+ mapA.portal = portalA
+ mapB.portal = portalB
+ mapA.portalPair = mapB
+ mapB.portalPair = mapA
+ return [portalA, portalB, mapA, mapB]
+ },
+ testChamber() {
+ const portal = level.portal({
+ x: 2500,
+ y: -100
+ }, Math.PI, { //left
+ x: 2500,
+ y: -3100
+ }, Math.PI) //left
+ const portal2 = level.portal({
+ x: 100,
+ y: -2150
+ }, -Math.PI / 2, { //up
+ x: 1300,
+ y: -2150
+ }, -Math.PI / 2) //up
+ level.custom = () => {
+ level.playerExitCheck();
+ portal[2].query()
+ portal[3].query()
+ portal2[2].query()
+ portal2[3].query()
+ };
+ level.customTopLayer = () => {
+ portal[0].draw();
+ portal[1].draw();
+ portal[2].draw();
+ portal[3].draw();
+ portal2[0].draw();
+ portal2[1].draw();
+ portal2[2].draw();
+ portal2[3].draw();
+ };
+
+ if (false) {
+ level.setPosToSpawn(0, -50); //lower spawn
+ level.exit.y = level.enter.y - 550;
+ level.fillBG.push({
+ x: -300,
+ y: -1000,
+ width: 650,
+ height: 500,
+ color: "#d4f4f4"
+ });
+ } else {
+ level.setPosToSpawn(0, -600); //upper spawn
+ level.exit.y = level.enter.y + 550;
+ level.fillBG.push({
+ x: -300,
+ y: -500,
+ width: 650,
+ height: 500,
+ color: "#d4f4f4"
+ });
+ }
+ spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
+ level.exit.x = level.enter.x;
+ spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20);
+
+ 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
+
+ //outer wall
+ spawn.mapRect(-500, -3800, 200, 4000); //left map wall
+ spawn.mapRect(2500, -2975, 200, 2375); //right map middle wall
+ spawn.mapRect(-400, -3800, 3100, 200); //map ceiling
+ spawn.mapRect(-400, 0, 3100, 200); //floor
+
+ //entrance
+ spawn.mapRect(300, -550, 50, 350); //right entrance wall
+ spawn.mapRect(-400, -550, 3000, 50); //ceiling
+ //entrance clutter
+ const xPos = shuffle([550, 1100, 1850]);
+ spawn.mapRect(xPos[0], -350, 400, 100);
+ spawn.mapRect(xPos[1], -350, 300, 400);
+ spawn.mapRect(xPos[2], -150, 300, 200);
+
+ //exit
+ spawn.mapRect(-400, -1050, 750, 50);
+ spawn.mapRect(300, -1050, 50, 300);
+
+
+ //portal bottom
+ spawn.mapRect(2500, -700, 200, 540); //right portal wall
+ spawn.mapRect(2525, -200, 175, 250); //right portal back wall
+
+ //portal top
+ spawn.mapRect(1400, -3000, 1300, 50); //floor
+ spawn.mapRect(2500, -3700, 200, 540); //right portal wall
+ spawn.mapRect(2525, -3200, 175, 250); //right portal back wall
+ // spawn.mapRect(700, -3250, 775, 350);
+
+ spawn.mapRect(0, -3250, 1450, 50);
+ spawn.mapRect(1400, -3250, 50, 300);
+
+ // spawn.mapRect(-350, -2875, 175, 325);
+ spawn.mapRect(-150, -3000, 150, 50);
+ spawn.mapRect(-350, -2750, 175, 200);
+
+
+ //portal 2
+ spawn.mapRect(-300, -2600, 300, 700);
+ spawn.mapRect(-25, -1975, 250, 75);
+
+ spawn.mapRect(1400, -2600, 300, 700);
+ spawn.mapRect(1175, -1975, 250, 75);
+
+ // spawn.mapRect(200, -2150, 25, 250);
+ // spawn.mapRect(475, -2150, 25, 250);
+ //portal walls
+ // spawn.mapRect(575, -8, 100, 50);
+ // spawn.mapRect(925, -8, 100, 50);
+ // spawn.mapRect(675,t -625, 250, 675);
+
+ // spawn.mapRect(1700, 75, 150, 25);
+ // spawn.mapRect(1700, -700, 150, 25);
+ // spawn.mapRect(1850, 0, 525, 100);
+ // spawn.mapRect(1850, -700, 525, 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);
+ powerUps.addRerollToLevel() //needs to run after mobs are spawned
},
sewers() {
const rotor = level.rotor(5100, 2425, -0.001)
@@ -2356,4 +2455,161 @@ const level = {
World.add(engine.world, consBB[i]);
}
},
+ rotor(x, y, rotate = 0, radius = 900, width = 50, density = 0.0005) {
+ const rotor1 = Matter.Bodies.rectangle(x, y, width, radius, {
+ density: density,
+ isNotSticky: true,
+ isNotHoldable: true
+ });
+ const rotor2 = Matter.Bodies.rectangle(x, y, width, radius, {
+ angle: Math.PI / 2,
+ density: density,
+ isNotSticky: true,
+ isNotHoldable: true
+ });
+ rotor = Body.create({ //combine rotor1 and rotor2
+ parts: [rotor1, rotor2],
+ restitution: 0,
+ collisionFilter: {
+ category: cat.body,
+ mask: cat.body | cat.mob | cat.mobBullet | cat.mobShield | cat.powerUp | cat.player | cat.bullet
+ },
+ });
+ Matter.Body.setPosition(rotor, {
+ x: x,
+ y: y
+ });
+ World.add(engine.world, [rotor]);
+ body[body.length] = rotor1
+ body[body.length] = rotor2
+
+ setTimeout(function () {
+ rotor.collisionFilter.category = cat.body;
+ rotor.collisionFilter.mask = cat.body | cat.player | cat.bullet | cat.mob | cat.mobBullet //| cat.map
+ }, 1000);
+
+ const constraint = Constraint.create({ //fix rotor in place, but allow rotation
+ pointA: {
+ x: x,
+ y: y
+ },
+ bodyB: rotor
+ });
+ World.add(engine.world, constraint);
+
+ if (rotate) {
+ rotor.rotate = function () {
+ if (!mech.isBodiesAsleep) {
+ Matter.Body.applyForce(rotor, {
+ x: rotor.position.x + 100,
+ y: rotor.position.y + 100
+ }, {
+ x: rotate * rotor.mass,
+ y: 0
+ })
+ } else {
+ Matter.Body.setAngularVelocity(rotor, 0);
+ }
+ }
+ }
+ composite[composite.length] = rotor
+ return rotor
+ },
+ button(x, y, width = 66) {
+ spawn.mapVertex(x + 35, y + 2, "70 10 -70 10 -40 -10 40 -10");
+ map[map.length - 1].restitution = 0;
+ map[map.length - 1].friction = 1;
+ map[map.length - 1].frictionStatic = 1;
+
+ // const buttonSensor = Bodies.rectangle(x + 35, y - 1, 70, 20, {
+ // isSensor: true
+ // });
+
+ return {
+ isUp: false,
+ min: {
+ x: x + 2,
+ y: y - 11
+ },
+ max: {
+ x: x + width,
+ y: y - 10
+ },
+ width: width,
+ height: 20,
+ query() {
+ // if (Matter.Query.collides(buttonSensor, body).length === 0 && Matter.Query.collides(buttonSensor, [player]).length === 0) {
+ if (Matter.Query.region(body, this).length === 0 && Matter.Query.region([player], this).length === 0) {
+ this.isUp = true;
+ } else {
+ this.isUp = false;
+ // const list = Matter.Query.collides(buttonSensor, body)
+ // if (list.length > 0) {
+ // Matter.Body.setVelocity(list[0].bodyB, {
+ // x: 0,
+ // y: 0
+ // });
+ // }
+ }
+ },
+ draw() {
+ ctx.fillStyle = "hsl(0, 100%, 70%)"
+ if (this.isUp) {
+ ctx.fillRect(this.min.x, this.min.y - 10, this.width, 20)
+ } else {
+ ctx.fillRect(this.min.x, this.min.y, this.width, 25)
+ }
+ //draw sensor zone
+ // ctx.beginPath();
+ // sensor = buttonSensor.vertices;
+ // ctx.moveTo(sensor[0].x, sensor[0].y);
+ // for (let i = 1; i < sensor.length; ++i) {
+ // ctx.lineTo(sensor[i].x, sensor[i].y);
+ // }
+ // ctx.lineTo(sensor[0].x, sensor[0].y);
+ // ctx.fillStyle = "rgba(255, 255, 0, 0.3)";
+ // ctx.fill();
+ }
+ }
+ },
+ hazard(x, y, width, height, damage = 0.0005, color = "hsl(160, 100%, 35%)") {
+ return {
+ min: {
+ x: x,
+ y: y
+ },
+ max: {
+ x: x + width,
+ y: y + height
+ },
+ width: width,
+ height: height,
+ maxHeight: height,
+ query() {
+ if (this.height > 0 && Matter.Query.region([player], this).length && !mech.isStealth) {
+ mech.damage(damage)
+ const drain = 0.005
+ if (mech.energy > drain) mech.energy -= drain
+ }
+ },
+ draw() {
+ ctx.fillStyle = color
+ ctx.fillRect(this.min.x, this.min.y, this.width, this.height)
+ },
+ level(isFill) {
+ const growSpeed = 1
+ if (isFill) {
+ if (this.height < this.maxHeight) {
+ this.height += growSpeed
+ this.min.y -= growSpeed
+ this.max.y = this.min.y + this.height
+ }
+ } else if (this.height > 0) {
+ this.height -= growSpeed
+ this.min.y += growSpeed
+ this.max.y = this.min.y + this.height
+ }
+ }
+ }
+ },
};
\ No newline at end of file
diff --git a/js/mods.js b/js/mods.js
index ddb6a03..3e3f339 100644
--- a/js/mods.js
+++ b/js/mods.js
@@ -643,7 +643,7 @@ const mod = {
maxCount: 1,
count: 0,
allowed() {
- return game.fpsCapDefault > 45
+ return game.fpsCapDefault > 45 && !mod.isRailTimeSlow
},
requires: "FPS above 45",
effect() {
@@ -852,22 +852,6 @@ const mod = {
mech.displayHealth();
}
},
- {
- name: "negentropy",
- description: "at the start of each level
heal up to 66% of maximum health",
- maxCount: 1,
- count: 0,
- allowed() {
- return mech.maxHealth > 1 || mod.isArmorFromPowerUps
- },
- requires: "increased max health",
- effect() {
- mod.isHealLowHealth = true;
- },
- remove() {
- mod.isHealLowHealth = false;
- }
- },
{
name: "crystallized armor",
description: "increase maximum health by 5% for each
unused power up at the end of a level",
@@ -884,6 +868,38 @@ const mod = {
mod.isArmorFromPowerUps = false;
}
},
+ {
+ name: "negentropy",
+ description: "at the start of each level
heal up to 66% of maximum health",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return mech.maxHealth > 1 || mod.isArmorFromPowerUps
+ },
+ requires: "increased max health",
+ effect() {
+ mod.isHealLowHealth = true;
+ },
+ remove() {
+ mod.isHealLowHealth = false;
+ }
+ },
+ // {
+ // name: "prismatic cleavage",
+ // description: "harm that would be fatal no longer kills you
instead it is removed from your maximum health",
+ // maxCount: 1,
+ // count: 0,
+ // allowed() {
+ // return mech.maxHealth > 1 || mod.isArmorFromPowerUps
+ // },
+ // requires: "increased max health",
+ // effect() {
+ // mod.isMaxHealthRemove = true;
+ // },
+ // remove() {
+ // mod.isMaxHealthRemove = false;
+ // }
+ // },
{
name: "recursive healing",
description: "healing power ups trigger 1 more time",
@@ -1245,6 +1261,22 @@ const mod = {
mod.bulletSize = 1;
}
},
+ {
+ name: "high caliber",
+ description: "100% increased minigun bullet size
100% increased delay after firing",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return mod.haveGunCheck("minigun")
+ },
+ requires: "minigun",
+ effect() {
+ mod.highCaliber = 2
+ },
+ remove() {
+ mod.highCaliber = 1
+ }
+ },
{
name: "ice crystal nucleation",
description: "your minigun uses energy to condense
unlimited freezing bullets from water vapor",
@@ -1813,7 +1845,22 @@ const mod = {
mod.isFoamGrowOnDeath = false;
}
},
-
+ {
+ name: "frame-dragging",
+ description: "slow time while charging the rail gun
charging no longer drains energy",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return game.fpsCapDefault > 45 && mod.haveGunCheck("rail gun") && !mod.isSlowFPS
+ },
+ requires: "rail gun && FPS above 45",
+ effect() {
+ mod.isRailTimeSlow = true;
+ },
+ remove() {
+ mod.isRailTimeSlow = false;
+ }
+ },
{
name: "fragmenting projectiles",
description: "rail gun fragments into nails
after hitting mobs at high speeds",
@@ -2384,5 +2431,7 @@ const mod = {
isRerollHaste: null,
rerollHaste: null,
isMineDrop: null,
- isRerollBots: null
+ isRerollBots: null,
+ isRailTimeSlow: null
+ // isMaxHealthRemove: null
}
\ No newline at end of file
diff --git a/js/player.js b/js/player.js
index 9791101..c91127b 100644
--- a/js/player.js
+++ b/js/player.js
@@ -945,14 +945,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 * 3;
- if (mod.isMineDrop) b.mine({
- x: mech.pos.x,
- y: mech.pos.y
- }, {
- x: 0,
- y: 0
- }, 0, mod.isMineAmmoBack)
+ powerUps.onPickUp();
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
@@ -1663,7 +1656,7 @@ const mech = {
mech.grabPowerUp();
mech.lookForPickUp(180);
- const DRAIN = 0.0017
+ const DRAIN = 0.0014
if (mech.energy > DRAIN) {
mech.energy -= DRAIN;
if (mech.energy < DRAIN) {
diff --git a/js/powerup.js b/js/powerup.js
index 63a9b6d..d1db07a 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -195,7 +195,9 @@ const powerUps = {
let choice2 = -1
let choice3 = -1
if (choice1 > -1) {
- let text = `