diff --git a/.gitignore b/.gitignore
index e9de866..ef23d46 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
.DS_Store
.DS_Store
.DS_Store
+js/workspace.code-workspace
diff --git a/js/engine.js b/js/engine.js
index 4591db2..2a0033f 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -186,6 +186,7 @@ function collisionChecks(event) {
color: simulation.playerDmgColor,
time: simulation.drawTime
});
+ if (tech.isLessDamageReduction && !mob[k].shield) mob[k].damageReduction *= mob[k].isBoss ? 1.005 : 1.05
return;
}
//mob + body collisions
@@ -231,15 +232,15 @@ function collisionChecks(event) {
}
//determine if player is on the ground
-Events.on(engine, "collisionStart", function(event) {
+Events.on(engine, "collisionStart", function (event) {
playerOnGroundCheck(event);
// playerHeadCheck(event);
if (m.alive) collisionChecks(event);
});
-Events.on(engine, "collisionActive", function(event) {
+Events.on(engine, "collisionActive", function (event) {
playerOnGroundCheck(event);
// playerHeadCheck(event);
});
-Events.on(engine, "collisionEnd", function(event) {
+Events.on(engine, "collisionEnd", function (event) {
playerOffGroundCheck(event);
});
\ No newline at end of file
diff --git a/js/level.js b/js/level.js
index e2485e0..a2b1f69 100644
--- a/js/level.js
+++ b/js/level.js
@@ -16,18 +16,17 @@ const level = {
// localSettings.levelsClearedLastGame = 10
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true
- // m.setField("molecular assembler")
+ // m.setField("wormhole")
// b.giveGuns("laser")
// b.giveGuns("nail gun")
// b.giveGuns("harpoon")
- // tech.giveTech("darts")
- // tech.giveTech("incendiary ammunition")
+ // tech.giveTech("affine connection")
+ // tech.giveTech("regression")
// tech.giveTech("relativistic momentum")
// for (let i = 0; i < 2; i++) tech.giveTech("refractory metal")
// tech.giveTech("antiscience")
// for (let i = 0; i < 1; i++) tech.giveTech("reticulum")
// for (let i = 0; i < 2; i++) tech.giveTech("laser-bot")
- // tech.isCancelDuplication = true
level.intro(); //starting level
// level.testing(); //not in rotation, used for testing
@@ -132,8 +131,8 @@ const level = {
// for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + 90 * (Math.random() - 0.5), player.position.y + 90 * (Math.random() - 0.5), "tech", false); //start
}
},
- custom() {},
- customTopLayer() {},
+ custom() { },
+ customTopLayer() { },
setDifficulty() {
simulation.difficulty = 0
b.dmgScale = 1; //damage done by player decreases each level
@@ -575,7 +574,7 @@ const level = {
body[body.length] = rotor1
body[body.length] = rotor2
- setTimeout(function() {
+ setTimeout(function () {
rotor.collisionFilter.category = cat.body;
rotor.collisionFilter.mask = cat.body | cat.player | cat.bullet | cat.mob | cat.mobBullet //| cat.map
}, 1000);
@@ -590,7 +589,7 @@ const level = {
Composite.add(engine.world, constraint);
if (rotate) {
- rotor.rotate = function() {
+ rotor.rotate = function () {
if (!m.isBodiesAsleep) {
Matter.Body.applyForce(rotor, {
x: rotor.position.x + 100,
@@ -793,7 +792,7 @@ const level = {
y: 0
}, angleB)
- draw = function() {
+ draw = function () {
ctx.beginPath(); //portal
let v = this.vertices;
ctx.moveTo(v[0].x, v[0].y);
@@ -803,7 +802,7 @@ const level = {
ctx.fillStyle = this.color
ctx.fill();
}
- query = function(isRemoveBlocks = false) {
+ query = function (isRemoveBlocks = false) {
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
@@ -998,7 +997,7 @@ const level = {
opticalQuery() {
if (this.isOn) {
//draw
- ctx.fillStyle = `hsla(0, 100%, 50%,${0.6+0.4*Math.random()})`
+ ctx.fillStyle = `hsla(0, 100%, 50%,${0.6 + 0.4 * Math.random()})`
ctx.fillRect(this.min.x, this.min.y, this.width, this.height)
//collision with player
if (this.height > 0 && Matter.Query.region([player], this).length && !(m.isCloak)) {
@@ -1418,7 +1417,7 @@ const level = {
button.isReadyToFire = true
} else if (button.isReadyToFire && !button.isUp) {
button.isReadyToFire = false
- fireBlock = function(xPos, yPos) {
+ fireBlock = function (xPos, yPos) {
const index = body.length
spawn.bodyRect(xPos, yPos, 35 + 50 * Math.random(), 35 + 50 * Math.random());
const bodyBullet = body[body.length - 1]
@@ -1474,7 +1473,7 @@ const level = {
button.isReadyToFire = true
} else if (button.isReadyToFire && !button.isUp) {
button.isReadyToFire = false
- fireBlock = function(xPos, yPos) {
+ fireBlock = function (xPos, yPos) {
const index = body.length
spawn.bodyRect(xPos, yPos, 35 + 50 * Math.random(), 35 + 50 * Math.random());
const bodyBullet = body[body.length - 1]
@@ -1569,7 +1568,7 @@ const level = {
y: -5
});
}
- ctx.fillStyle = `rgba(255,0,255,${0.2+0.7*Math.random()})`
+ ctx.fillStyle = `rgba(255,0,255,${0.2 + 0.7 * Math.random()})`
ctx.fillRect(bounds.min.x, y - 185, 38, 70);
}
}
@@ -1636,7 +1635,7 @@ const level = {
y: -5
});
}
- ctx.fillStyle = `rgba(255,0,255,${0.2+0.7*Math.random()})`
+ ctx.fillStyle = `rgba(255,0,255,${0.2 + 0.7 * Math.random()})`
ctx.fillRect(bounds.min.x, y - 185, 38, 70);
}
}
@@ -1888,7 +1887,7 @@ const level = {
Composite.add(engine.world, who); //add to world
}
let r = 150
- let hexagon = `${r} 0 ${r*Math.cos(5.236)} ${r*Math.sin(5.236)} ${r*Math.cos(4.189)} ${r*Math.sin(4.189)} ${-r} 0 ${r*Math.cos(2.0944)} ${r*Math.sin(2.0944)} ${r*Math.cos(1.0472)} ${r*Math.sin(1.0472)} `
+ let hexagon = `${r} 0 ${r * Math.cos(5.236)} ${r * Math.sin(5.236)} ${r * Math.cos(4.189)} ${r * Math.sin(4.189)} ${-r} 0 ${r * Math.cos(2.0944)} ${r * Math.sin(2.0944)} ${r * Math.cos(1.0472)} ${r * Math.sin(1.0472)} `
//450 horizontal spread // -130-130-130 = 390 vertical
if (Math.random() < 0.5) {
spawn.mapVertex(x + 775, y + -260, hexagon);
@@ -1977,13 +1976,13 @@ const level = {
}
//right side hexagons
let r = 300
- let hexagon = `${r} 0 ${r*Math.cos(5.236)} ${r*Math.sin(5.236)} ${r*Math.cos(4.189)} ${r*Math.sin(4.189)} ${-r} 0 ${r*Math.cos(2.0944)} ${r*Math.sin(2.0944)} ${r*Math.cos(1.0472)} ${r*Math.sin(1.0472)} `
+ let hexagon = `${r} 0 ${r * Math.cos(5.236)} ${r * Math.sin(5.236)} ${r * Math.cos(4.189)} ${r * Math.sin(4.189)} ${-r} 0 ${r * Math.cos(2.0944)} ${r * Math.sin(2.0944)} ${r * Math.cos(1.0472)} ${r * Math.sin(1.0472)} `
spawn.mapVertex(x + 1640, y + -365, hexagon);
// r = 275
// let hexagonHalf = `${r} 0 ${r*Math.cos(5.236)} ${r*Math.sin(5.236)} ${r*Math.cos(4.189)} ${r*Math.sin(4.189)} ${-r} 0 `
// spawn.mapVertex(x + 2300, y + -75, hexagonHalf);
r = 150
- const hexagon150 = `${r} 0 ${r*Math.cos(5.236)} ${r*Math.sin(5.236)} ${r*Math.cos(4.189)} ${r*Math.sin(4.189)} ${-r} 0 ${r*Math.cos(2.0944)} ${r*Math.sin(2.0944)} ${r*Math.cos(1.0472)} ${r*Math.sin(1.0472)} `
+ const hexagon150 = `${r} 0 ${r * Math.cos(5.236)} ${r * Math.sin(5.236)} ${r * Math.cos(4.189)} ${r * Math.sin(4.189)} ${-r} 0 ${r * Math.cos(2.0944)} ${r * Math.sin(2.0944)} ${r * Math.cos(1.0472)} ${r * Math.sin(1.0472)} `
// spawn.mapVertex(x + 1750, y + -550, hexagon150);
spawn.mapVertex(x + 1750, y + -1100, hexagon150);
spawn.mapVertex(x + 1750, y + -1650, hexagon150);
@@ -1991,7 +1990,7 @@ const level = {
//left side
r = 350
- let hexagonHalf = `${r} 0 ${r*Math.cos(5.236)} ${r*Math.sin(5.236)} ${r*Math.cos(4.189)} ${r*Math.sin(4.189)} ${-r} 0 `
+ let hexagonHalf = `${r} 0 ${r * Math.cos(5.236)} ${r * Math.sin(5.236)} ${r * Math.cos(4.189)} ${r * Math.sin(4.189)} ${-r} 0 `
spawn.mapVertex(x + 425, y + -90, hexagonHalf);
spawn.mapVertex(x + 850, y + -500, hexagon150);
@@ -2338,10 +2337,10 @@ const level = {
spawn.mapRect(4850, -275, 50, 175);
//???
- level.difficultyIncrease(40) //30 is near max on hard //60 is near max on why
- // spawn.starter(1900, -500, 200) //big boy
+ level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
+ spawn.starter(1900, -500, 200) //big boy
- // spawn.spiderBoss(1700, -500)
+ // spawn.launcherOne(1700, -500)
// spawn.launcherBoss(3200, -500)
// spawn.laserTargetingBoss(1700, -500)
// spawn.powerUpBoss(3200, -500)
@@ -2371,7 +2370,7 @@ const level = {
// spawn.blinkBoss(1600, -500)
// spawn.laserTargetingBoss(1700, -120)
// spawn.bomberBoss(1400, -500)
- spawn.laser(1800, -320)
+ // spawn.laser(1800, -320)
// spawn.laserBombingBoss(1600, -500)
// spawn.laserTargetingBoss(1600, -500)
// spawn.laserBoss(1600, -500)
@@ -2389,7 +2388,7 @@ const level = {
level.exit.draw();
level.enter.draw();
};
- level.customTopLayer = () => {};
+ level.customTopLayer = () => { };
level.setPosToSpawn(0, -50); //normal spawn
level.exit.x = 1500;
level.exit.y = -1875;
@@ -5519,7 +5518,7 @@ const level = {
if (mob[i].isBoss) me = mob[i]
}
if (me) {
- me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs
+ me.onDeath = function () { //please don't edit the onDeath function this causes serious bugs
spawnCouloirEnHaut()
doorSortieSalle.isOpen = false;
};
@@ -5535,7 +5534,7 @@ const level = {
if (mob[i].isBoss) me = mob[i]
}
if (me) {
- me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs
+ me.onDeath = function () { //please don't edit the onDeath function this causes serious bugs
spawnCouloirEnHaut()
doorSortieSalle.isOpen = false;
};
@@ -5760,11 +5759,11 @@ const level = {
body[body.length] = part4;
body[body.length] = part5;
body[body.length] = part6;
- setTimeout(function() {
+ setTimeout(function () {
chair.collisionFilter.category = cat.body;
chair.collisionFilter.mask = cat.body | cat.player | cat.bullet | cat.mob | cat.mobBullet | cat.map
}, 1000);
- setTimeout(function() {
+ setTimeout(function () {
chair2.collisionFilter.category = cat.body;
chair2.collisionFilter.mask = cat.body | cat.player | cat.bullet | cat.mob | cat.mobBullet | cat.map
}, 1000);
@@ -5819,7 +5818,7 @@ const level = {
body[body.length] = rightUpperLeg
body[body.length] = rightLowerArm
body[body.length] = rightUpperArm
- setTimeout(function() {
+ setTimeout(function () {
person.collisionFilter.category = cat.body;
person.collisionFilter.mask = cat.body | cat.player | cat.bullet | cat.mob | cat.mobBullet | cat.map
}, 1000);
@@ -6211,7 +6210,7 @@ const level = {
level.exit.draw();
level.enter.draw();
};
- level.customTopLayer = () => {};
+ level.customTopLayer = () => { };
level.defaultZoom = 1800
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#dcdcde";
@@ -7270,7 +7269,7 @@ const level = {
body[body.length] = part1;
body[body.length] = part2;
body[body.length] = part3;
- setTimeout(function() {
+ setTimeout(function () {
compoundParts.collisionFilter.category = cat.body;
compoundParts.collisionFilter.mask = cat.body | cat.player | cat.bullet | cat.mob | cat.mobBullet | cat.map
}, 1000);
@@ -7389,8 +7388,8 @@ const level = {
// prevent the user from getting into the secreter room without defeating all mobs
if (m.pos.x > 1500 && m.pos.x < 2500 && m.pos.y > -4000 && m.pos.y < -3500 && mob.reduce((a, i) => {
- return a || ((Math.sqrt((i.position.x - 3600) * (i.position.x - 3600) + (i.position.y + 3600) * (i.position.y + 3600)) < 20000) && i.isDropPowerUp);
- }, false) && !emergencyActivated) {
+ return a || ((Math.sqrt((i.position.x - 3600) * (i.position.x - 3600) + (i.position.y + 3600) * (i.position.y + 3600)) < 20000) && i.isDropPowerUp);
+ }, false) && !emergencyActivated) {
Matter.Body.setPosition(player, {
x: 2800,
y: m.pos.y
diff --git a/js/lore.js b/js/lore.js
index 6c0eca0..4d3e28d 100644
--- a/js/lore.js
+++ b/js/lore.js
@@ -11,7 +11,6 @@ const lore = {
} else if (simulation.difficultyMode === 6) {
this.techGoal = 1
}
-
},
talkingColor: "#dff", //set color of graphic on level.null
isSpeech: false,
@@ -42,6 +41,17 @@ const lore = {
lore.conversation[lore.chapter][lore.sentence]() //go to next sentence in the chapter and play it
}
},
+ unlockTesting() {
+ if (localSettings.loreCount < 1) localSettings.loreCount = 1
+ localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
+ document.getElementById("control-testing").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
+ document.getElementById("experiment-button").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
+ simulation.makeTextLog(`lore.unlockTesting()`, Infinity);
+
+ sound.portamento(50)
+ sound.portamento(83.333)
+ sound.portamento(166.666)
+ },
anand: {
color: "#e0c",
voice: undefined,
@@ -490,19 +500,6 @@ const lore = {
// () => { lore.miriam.text("And that is why you keep running these fighting simulations.") },
// () => { lore.miriam.text("You haven't been researching new technology.") },
// () => { lore.miriam.text("You've are planning how to escape.") },
-
-
- unlockTesting() {
- if (localSettings.loreCount < 1) localSettings.loreCount = 1
- localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
- document.getElementById("control-testing").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
- document.getElementById("experiment-button").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
- simulation.makeTextLog(`lore.unlockTesting()`, Infinity);
-
- sound.portamento(50)
- sound.portamento(83.333)
- sound.portamento(166.666)
- },
}
diff --git a/js/mob.js b/js/mob.js
index 1b1c331..bcf8dd6 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -128,7 +128,7 @@ const mobs = {
const y = who.position.y - w * 0.7;
ctx.fillStyle = "rgba(100, 100, 100, 0.3)";
ctx.fillRect(x, y, w, h);
- ctx.fillStyle = `rgba(${Math.floor(255*Math.random())},${Math.floor(255*Math.random())},${Math.floor(255*Math.random())},0.5)`
+ ctx.fillStyle = `rgba(${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},0.5)`
ctx.fillRect(x, y, w * who.health, h);
//draw fill inside mob
@@ -165,7 +165,7 @@ const mobs = {
});
}
},
- endEffect() {},
+ endEffect() { },
dmg: tickDamage,
type: "dot",
endCycle: simulation.cycle + cycles,
@@ -472,7 +472,7 @@ const mobs = {
}
},
laser() {
- const vertexCollision = function(v1, v1End, domain) {
+ const vertexCollision = function (v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices;
const len = vertices.length - 1;
@@ -609,7 +609,7 @@ const mobs = {
ctx.fillStyle = "rgba(0,0,0,0.07)";
ctx.fill();
//spring to random place on map
- const vertexCollision = function(v1, v1End, domain) {
+ const vertexCollision = function (v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices;
const len = vertices.length - 1;
@@ -676,7 +676,7 @@ const mobs = {
},
curl(range = 1000, mag = -10) {
//cause all mobs, and bodies to rotate in a circle
- applyCurl = function(center, array, isAntiGravity = true) {
+ applyCurl = function (center, array, isAntiGravity = true) {
for (let i = 0; i < array.length; ++i) {
if (!array[i].isNotHoldable) {
const sub = Vector.sub(center, array[i].position)
@@ -686,10 +686,17 @@ const mobs = {
if (radius2 < range * range && radius2 > 10000) {
const curlVector = Vector.mult(Vector.perp(Vector.normalise(sub)), mag)
//apply curl force
- Matter.Body.setVelocity(array[i], {
- x: array[i].velocity.x * 0.94 + curlVector.x * 0.06,
- y: array[i].velocity.y * 0.94 + curlVector.y * 0.06
- })
+ if (array[i].isMobBullet) {
+ Matter.Body.setVelocity(array[i], {
+ x: array[i].velocity.x * 0.97 + curlVector.x * 0.06,
+ y: array[i].velocity.y * 0.97 + curlVector.y * 0.06
+ })
+ } else {
+ Matter.Body.setVelocity(array[i], {
+ x: array[i].velocity.x * 0.94 + curlVector.x * 0.06,
+ y: array[i].velocity.y * 0.94 + curlVector.y * 0.06
+ })
+ }
if (isAntiGravity) array[i].force.y -= 0.8 * simulation.g * array[i].mass
// //draw curl, for debugging
// ctx.beginPath();
@@ -818,7 +825,7 @@ const mobs = {
//be sure to declare searchTarget in mob spawn
//accelerate towards the searchTarget
if (!this.seePlayer.recall) {
- const newTarget = function(that) {
+ const newTarget = function (that) {
if (Math.random() < 0.0005) {
that.searchTarget = player.position; //chance to target player
} else {
@@ -1221,7 +1228,7 @@ const mobs = {
for (let i = 0, len = consBB.length; i < len; ++i) {
if (consBB[i].bodyA === this) {
if (consBB[i].bodyB.shield) {
- consBB[i].bodyB.do = function() {
+ consBB[i].bodyB.do = function () {
this.death();
};
}
@@ -1231,7 +1238,7 @@ const mobs = {
break;
} else if (consBB[i].bodyB === this) {
if (consBB[i].bodyA.shield) {
- consBB[i].bodyA.do = function() {
+ consBB[i].bodyA.do = function () {
this.death();
};
}
@@ -1290,7 +1297,7 @@ const mobs = {
//large mobs shrink so they don't block paths
if (body[len].mass + body[len2].mass > 16) {
const massLimit = 8 + 6 * Math.random()
- const shrink = function(that1, that2) {
+ const shrink = function (that1, that2) {
if (that1.mass + that2.mass > massLimit) {
const scale = 0.95;
Matter.Body.scale(that1, scale, scale);
@@ -1313,7 +1320,7 @@ const mobs = {
//large mobs shrink so they don't block paths
if (body[len].mass > 9) {
const massLimit = 7 + 4 * Math.random()
- const shrink = function(that) {
+ const shrink = function (that) {
if (that.mass > massLimit) {
const scale = 0.95;
Matter.Body.scale(that, scale, scale);
diff --git a/js/player.js b/js/player.js
index 160dc52..3dc5255 100644
--- a/js/player.js
+++ b/js/player.js
@@ -57,7 +57,7 @@ const m = {
},
setFillColors() {
this.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)`
- this.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light-25}%)`
+ this.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 25}%)`
let grd = ctx.createLinearGradient(-30, 0, 30, 0);
grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor);
@@ -183,7 +183,7 @@ const m = {
lastGroundedPositionY: 0,
// mouseZoom: 0,
lookSmoothing: 0.07, //1 is instant jerky, 0.001 is slow smooth zoom, 0.07 is standard
- look() {}, //set to lookDefault()
+ look() { }, //set to lookDefault()
lookDefault() {
//always on mouse look
m.angle = Math.atan2(
@@ -405,7 +405,7 @@ const m = {
m.health = 1;
// m.addHealth(1)
- simulation.wipe = function() { //set wipe to have trails
+ simulation.wipe = function () { //set wipe to have trails
ctx.fillStyle = "rgba(255,255,255,0)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
@@ -415,8 +415,8 @@ const m = {
m.switchWorlds()
const swapPeriod = 1000
for (let i = 0, len = 5; i < len; i++) {
- setTimeout(function() {
- simulation.wipe = function() { //set wipe to have trails
+ setTimeout(function () {
+ simulation.wipe = function () { //set wipe to have trails
ctx.fillStyle = "rgba(255,255,255,0)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
@@ -424,16 +424,16 @@ const m = {
simulation.clearNow = true; //triggers a map reset
m.switchWorlds()
simulation.isTextLogOpen = true;
- simulation.makeTextLog(`simulation.amplitude = 0.${len-i-1}`, swapPeriod);
+ simulation.makeTextLog(`simulation.amplitude = 0.${len - i - 1}`, swapPeriod);
simulation.isTextLogOpen = false;
- simulation.wipe = function() { //set wipe to have trails
- ctx.fillStyle = `rgba(255,255,255,${(i+1)*(i+1)*0.006})`;
+ simulation.wipe = function () { //set wipe to have trails
+ ctx.fillStyle = `rgba(255,255,255,${(i + 1) * (i + 1) * 0.006})`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
}, (i + 1) * swapPeriod);
}
- setTimeout(function() {
- simulation.wipe = function() { //set wipe to normal
+ setTimeout(function () {
+ simulation.wipe = function () { //set wipe to normal
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
simulation.isTextLogOpen = true;
@@ -448,7 +448,7 @@ const m = {
document.getElementById("text-log").style.opacity = 0; //fade out any active text logs
document.getElementById("fade-out").style.opacity = 0.9; //slowly fade to 90% white on top of canvas
// build.shareURL(false)
- setTimeout(function() {
+ setTimeout(function () {
Composite.clear(engine.world);
Engine.clear(engine);
simulation.splashReturn();
@@ -491,7 +491,7 @@ const m = {
baseHealth: 1,
setMaxHealth() {
m.maxHealth = m.baseHealth + tech.extraMaxHealth + tech.isFallingDamage //+ tech.bonusHealth
- document.getElementById("health-bg").style.width = `${Math.floor(300*m.maxHealth)}px`
+ document.getElementById("health-bg").style.width = `${Math.floor(300 * m.maxHealth)}px`
simulation.makeTextLog(`m.maxHealth = ${m.maxHealth.toFixed(2)}`)
if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth();
@@ -588,7 +588,7 @@ const m = {
if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles
let isDrawPlayer = true
- const shortPause = function() {
+ const shortPause = function () {
if (m.defaultFPSCycle < m.cycle) { //back to default values
simulation.fpsCap = simulation.fpsCapDefault
simulation.fpsInterval = 1000 / simulation.fpsCap;
@@ -657,13 +657,13 @@ const m = {
for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "heal", false);
m.energy = m.maxEnergy
if (m.immuneCycle < m.cycle + 300) m.immuneCycle = m.cycle + 300 //disable this.immuneCycle bonus seconds
- simulation.wipe = function() { //set wipe to have trails
+ simulation.wipe = function () { //set wipe to have trails
ctx.fillStyle = "rgba(255,255,255,0.03)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
- setTimeout(function() {
+ setTimeout(function () {
tech.maxDuplicationEvent()
- simulation.wipe = function() { //set wipe to normal
+ simulation.wipe = function () { //set wipe to normal
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
}, 3000);
@@ -686,13 +686,13 @@ const m = {
${powerUps.research.count}`)
for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "heal", false);
if (m.immuneCycle < m.cycle + 300) m.immuneCycle = m.cycle + 300 //disable this.immuneCycle bonus seconds
- simulation.wipe = function() { //set wipe to have trails
+ simulation.wipe = function () { //set wipe to have trails
ctx.fillStyle = "rgba(255,255,255,0.03)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
- setTimeout(function() {
+ setTimeout(function () {
tech.maxDuplicationEvent()
- simulation.wipe = function() { //set wipe to normal
+ simulation.wipe = function () { //set wipe to normal
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
}, 3000);
@@ -709,7 +709,7 @@ const m = {
}
if (dmg > 0.06 / m.holdingMassScale) m.drop(); //drop block if holding
- const normalFPS = function() {
+ const normalFPS = function () {
if (m.defaultFPSCycle < m.cycle) { //back to default values
simulation.fpsCap = simulation.fpsCapDefault
simulation.fpsInterval = 1000 / simulation.fpsCap;
@@ -808,38 +808,7 @@ const m = {
m.knee.x = (l / d) * (m.foot.x - m.hip.x) - (h / d) * (m.foot.y - m.hip.y) + m.hip.x + offset;
m.knee.y = (l / d) * (m.foot.y - m.hip.y) + (h / d) * (m.foot.x - m.hip.x) + m.hip.y;
},
- draw() {
- ctx.fillStyle = m.fillColor;
- m.walk_cycle += m.flipLegs * m.Vx;
-
- //draw body
- ctx.save();
- ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5
- ctx.translate(m.pos.x, m.pos.y);
-
- m.calcLeg(Math.PI, -3);
- m.drawLeg("#4a4a4a");
- m.calcLeg(0, 0);
- m.drawLeg("#333");
-
- ctx.rotate(m.angle);
- ctx.beginPath();
- ctx.arc(0, 0, 30, 0, 2 * Math.PI);
- ctx.fillStyle = this.bodyGradient;
- ctx.fill();
- ctx.arc(15, 0, 4, 0, 2 * Math.PI);
- ctx.strokeStyle = "#333";
- ctx.lineWidth = 2;
- ctx.stroke();
- // draw eye; used in flip-flop
- // ctx.beginPath();
- // ctx.arc(15, 0, 3.5, 0, 2 * Math.PI);
- // ctx.fillStyle = m.eyeFillColor;
- // ctx.fill()
-
- ctx.restore();
- m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
- },
+ draw() { },
drawFlipFlop() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
@@ -875,17 +844,13 @@ const m = {
drawDefault() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
-
- //draw body
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5
ctx.translate(m.pos.x, m.pos.y);
-
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a");
m.calcLeg(0, 0);
m.drawLeg("#333");
-
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
@@ -895,12 +860,6 @@ const m = {
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
- // draw eye; used in flip-flop
- // ctx.beginPath();
- // ctx.arc(15, 0, 3.5, 0, 2 * Math.PI);
- // ctx.fillStyle = m.eyeFillColor;
- // ctx.fill()
-
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
},
@@ -1022,7 +981,7 @@ const m = {
ctx.fillRect(xOff, yOff, range * m.energy, 10);
}
},
- drawFieldMeterCloaking: function() {
+ drawFieldMeterCloaking: function () {
if (m.energy < m.maxEnergy) { // replaces m.drawFieldMeter() with custom code
m.regenEnergy();
const xOff = m.pos.x - m.radius * m.maxEnergy
@@ -1038,11 +997,11 @@ const m = {
ctx.stroke();
}
},
- regenEnergy: function() { //used in drawFieldMeter // rewritten by some tech
+ regenEnergy: function () { //used in drawFieldMeter // rewritten by some tech
if (m.immuneCycle < m.cycle) m.energy += m.fieldRegen;
if (m.energy < 0) m.energy = 0
},
- regenEnergyDefault: function() {
+ regenEnergyDefault: function () {
if (m.immuneCycle < m.cycle) m.energy += m.fieldRegen;
if (m.energy < 0) m.energy = 0
},
@@ -1230,7 +1189,7 @@ const m = {
m.holdingTarget.friction = m.holdingTarget.frictionStatic = m.holdingTarget.frictionAir = 0.001
}
//check every second to see if player is away from thrown body, and make solid
- const solid = function(that) {
+ const solid = function (that) {
const dx = that.position.x - player.position.x;
const dy = that.position.y - player.position.y;
if (that.speed < 3 && dx * dx + dy * dy > 10000 && that !== m.holdingTarget) {
@@ -1262,7 +1221,7 @@ const m = {
m.definePlayerMass() //return to normal player mass
if (tech.isAddBlockMass) {
- const expand = function(that, massLimit) {
+ const expand = function (that, massLimit) {
if (that.mass < massLimit) {
const scale = 1.05;
Matter.Body.scale(that, scale, scale);
@@ -1507,7 +1466,7 @@ const m = {
// wake(powerUp);
}
},
- hold() {},
+ hold() { },
setField(index) {
if (isNaN(index)) { //find index by name
let found = false
@@ -1527,1534 +1486,1501 @@ const m = {
simulation.makeTextLog(`m.setField("${m.fieldUpgrades[m.fieldMode].name}")`);
},
fieldUpgrades: [{
- name: "field emitter",
- description: "regen 6 energy per second
use it to deflect mobs and throw blocks
energy regen disabled if immune to harm",
- // description: "use energy to deflect mobs,
grab power ups, and throw blocks
regen 6 energy/s, when not immune to harm",
- effect: () => {
- m.hold = function() {
- if (m.isHolding) {
- m.drawHold(m.holdingTarget);
- m.holding();
- m.throwBlock();
- } else if ((input.field && m.fieldCDcycle < m.cycle)) { //not hold but field button is pressed
- m.grabPowerUp();
- m.lookForPickUp();
- if (m.energy > 0.05) {
- m.drawField();
- m.pushMobsFacing();
- }
- } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
- m.pickUp();
- } else {
- m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ name: "field emitter",
+ description: "regen 6 energy per second
use it to deflect mobs and throw blocks
energy regen disabled if immune to harm",
+ // description: "use energy to deflect mobs,
grab power ups, and throw blocks
regen 6 energy/s, when not immune to harm",
+ effect: () => {
+ m.hold = function () {
+ if (m.isHolding) {
+ m.drawHold(m.holdingTarget);
+ m.holding();
+ m.throwBlock();
+ } else if ((input.field && m.fieldCDcycle < m.cycle)) { //not hold but field button is pressed
+ m.grabPowerUp();
+ m.lookForPickUp();
+ if (m.energy > 0.05) {
+ m.drawField();
+ m.pushMobsFacing();
}
- m.drawFieldMeter()
- }
- }
- },
- {
- name: "standing wave",
- description: "3 oscillating shields are permanently active
deflecting protects you in every direction
deflecting has 50% less recoil", //drains energy
- drainCD: 0,
- effect: () => {
- m.fieldBlockCD = 0;
- m.blockingRecoil = 2 //4 is normal
- m.fieldRange = 175
- m.fieldShieldingScale = 1.3 * Math.pow(0.6, (tech.harmonics - 2))
-
- m.harmonic3Phase = () => { //normal standard 3 different 2-d circles
- const fieldRange1 = (0.7 + 0.3 * Math.sin(m.cycle / 23)) * m.fieldRange * m.harmonicRadius
- const fieldRange2 = (0.63 + 0.37 * Math.sin(m.cycle / 37)) * m.fieldRange * m.harmonicRadius
- const fieldRange3 = (0.65 + 0.35 * Math.sin(m.cycle / 47)) * m.fieldRange * m.harmonicRadius
- const netfieldRange = Math.max(fieldRange1, fieldRange2, fieldRange3)
- ctx.fillStyle = "rgba(110,170,200," + Math.min(0.73, (0.04 + m.energy * (0.11 + 0.13 * Math.random()))) + ")";
- ctx.beginPath();
- ctx.arc(m.pos.x, m.pos.y, fieldRange1, 0, 2 * Math.PI);
- ctx.fill();
- ctx.beginPath();
- ctx.arc(m.pos.x, m.pos.y, fieldRange2, 0, 2 * Math.PI);
- ctx.fill();
- ctx.beginPath();
- ctx.arc(m.pos.x, m.pos.y, fieldRange3, 0, 2 * Math.PI);
- ctx.fill();
- //360 block
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) - mob[i].radius < netfieldRange && !mob[i].isUnblockable) { // && Matter.Query.ray(map, mob[i].position, m.pos).length === 0
- mob[i].locatePlayer();
- if (this.drainCD > m.cycle) {
- m.pushMass(mob[i], 0);
- } else {
- m.pushMass(mob[i]);
- this.drainCD = m.cycle + 10
- }
- if (mob[i].isShielded) m.fieldCDcycle = m.cycle + 45
- }
- }
- }
- m.harmonicRadius = 1 //for smoothing function when player holds mouse (for harmonicAtomic)
- m.harmonicAtomic = () => { //several ellipses spinning about different axises
- const rotation = simulation.cycle * 0.0031
- const phase = simulation.cycle * 0.023
- const radius = m.fieldRange * m.harmonicRadius
- ctx.lineWidth = 1;
- ctx.strokeStyle = "rgba(110,170,200,0.8)"
- ctx.fillStyle = "rgba(110,170,200," + Math.min(0.7, m.energy * (0.13 + 0.1 * Math.random()) * (3 / tech.harmonics)) + ")";
- // ctx.fillStyle = "rgba(110,170,200," + Math.min(0.7, m.energy * (0.22 - 0.01 * tech.harmonics) * (0.5 + 0.5 * Math.random())) + ")";
- for (let i = 0; i < tech.harmonics; i++) {
- ctx.beginPath();
- ctx.ellipse(m.pos.x, m.pos.y, radius * Math.abs(Math.sin(phase + i / tech.harmonics * Math.PI)), radius, rotation + i / tech.harmonics * Math.PI, 0, 2 * Math.PI);
- ctx.fill();
- ctx.stroke();
- }
- //360 block
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) - mob[i].radius < radius && !mob[i].isUnblockable) { // && Matter.Query.ray(map, mob[i].position, m.pos).length === 0
- mob[i].locatePlayer();
- if (this.drainCD > m.cycle) {
- m.pushMass(mob[i], 0);
- } else {
- m.pushMass(mob[i]);
- this.drainCD = m.cycle + 10
- }
- if (mob[i].isShielded) m.fieldCDcycle = m.cycle + 45
- }
- }
- }
- if (tech.harmonics === 2) {
- m.harmonicShield = m.harmonic3Phase
+ } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
+ m.pickUp();
} else {
- m.harmonicShield = m.harmonicAtomic
+ m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
}
- m.hold = function() {
- if (m.isHolding) {
- m.drawHold(m.holdingTarget);
- m.holding();
- m.throwBlock();
- } else if ((input.field) && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
- m.grabPowerUp();
- m.lookForPickUp();
- } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
- m.pickUp();
- } else {
- m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- }
- if (m.energy > 0.1 && m.fieldCDcycle < m.cycle) {
- if (tech.isStandingWaveExpand) {
- if (input.field) {
- // const oldHarmonicRadius = m.harmonicRadius
- m.harmonicRadius = 0.985 * m.harmonicRadius + 0.015 * 2.5
- // m.energy -= 0.1 * (m.harmonicRadius - oldHarmonicRadius)
- } else {
- m.harmonicRadius = 0.995 * m.harmonicRadius + 0.005
- }
+ m.drawFieldMeter()
+ }
+ }
+ },
+ {
+ name: "standing wave",
+ description: "3 oscillating shields are permanently active
deflecting protects you in every direction
deflecting has 50% less recoil", //drains energy
+ drainCD: 0,
+ effect: () => {
+ m.fieldBlockCD = 0;
+ m.blockingRecoil = 2 //4 is normal
+ m.fieldRange = 175
+ m.fieldShieldingScale = 1.3 * Math.pow(0.6, (tech.harmonics - 2))
+
+ m.harmonic3Phase = () => { //normal standard 3 different 2-d circles
+ const fieldRange1 = (0.7 + 0.3 * Math.sin(m.cycle / 23)) * m.fieldRange * m.harmonicRadius
+ const fieldRange2 = (0.63 + 0.37 * Math.sin(m.cycle / 37)) * m.fieldRange * m.harmonicRadius
+ const fieldRange3 = (0.65 + 0.35 * Math.sin(m.cycle / 47)) * m.fieldRange * m.harmonicRadius
+ const netfieldRange = Math.max(fieldRange1, fieldRange2, fieldRange3)
+ ctx.fillStyle = "rgba(110,170,200," + Math.min(0.73, (0.04 + m.energy * (0.11 + 0.13 * Math.random()))) + ")";
+ ctx.beginPath();
+ ctx.arc(m.pos.x, m.pos.y, fieldRange1, 0, 2 * Math.PI);
+ ctx.fill();
+ ctx.beginPath();
+ ctx.arc(m.pos.x, m.pos.y, fieldRange2, 0, 2 * Math.PI);
+ ctx.fill();
+ ctx.beginPath();
+ ctx.arc(m.pos.x, m.pos.y, fieldRange3, 0, 2 * Math.PI);
+ ctx.fill();
+ //360 block
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) - mob[i].radius < netfieldRange && !mob[i].isUnblockable) { // && Matter.Query.ray(map, mob[i].position, m.pos).length === 0
+ mob[i].locatePlayer();
+ if (this.drainCD > m.cycle) {
+ m.pushMass(mob[i], 0);
+ } else {
+ m.pushMass(mob[i]);
+ this.drainCD = m.cycle + 10
}
- m.harmonicShield()
+ if (mob[i].isShielded) m.fieldCDcycle = m.cycle + 45
}
- m.drawFieldMeter()
}
}
- },
- {
- name: "perfect diamagnetism",
- description: "attract power ups from far away
deflecting does not drain energy
maintains functionality while inactive",
- // description: "attract power ups from far away
deflecting doesn't drain energy
thrown blocks have",
- // description: "gain energy when blocking
no recoil when blocking",
- effect: () => {
- m.fieldShieldingScale = 0;
- m.fieldBlockCD = 3;
- m.grabPowerUpRange2 = 10000000
- m.fieldPosition = { x: m.pos.x, y: m.pos.y }
- m.fieldAngle = m.angle
- m.perfectPush = (isFree = false) => {
- if (m.fieldCDcycle < m.cycle) {
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (
- Vector.magnitude(Vector.sub(mob[i].position, m.fieldPosition)) - mob[i].radius < m.fieldRange &&
- !mob[i].isUnblockable &&
- Vector.dot({ x: Math.cos(m.fieldAngle), y: Math.sin(m.fieldAngle) }, Vector.normalise(Vector.sub(mob[i].position, m.fieldPosition))) > m.fieldThreshold &&
- Matter.Query.ray(map, mob[i].position, m.fieldPosition).length === 0
- ) {
- mob[i].locatePlayer();
- const unit = Vector.normalise(Vector.sub(m.fieldPosition, mob[i].position))
- m.fieldCDcycle = m.cycle + m.fieldBlockCD + (mob[i].isShielded ? 15 : 0);
- if (tech.blockingIce) {
- for (let i = 0; i < 2 * tech.blockingIce; i++) {
- const angle = m.fieldAngle + 1.55 * (Math.random() - 0.5)
- b.iceIX(10, angle, Vector.add(m.fieldPosition, { x: m.fieldRange * Math.cos(angle), y: m.fieldRange * Math.sin(angle) }))
+ m.harmonicRadius = 1 //for smoothing function when player holds mouse (for harmonicAtomic)
+ m.harmonicAtomic = () => { //several ellipses spinning about different axises
+ const rotation = simulation.cycle * 0.0031
+ const phase = simulation.cycle * 0.023
+ const radius = m.fieldRange * m.harmonicRadius
+ ctx.lineWidth = 1;
+ ctx.strokeStyle = "rgba(110,170,200,0.8)"
+ ctx.fillStyle = "rgba(110,170,200," + Math.min(0.7, m.energy * (0.13 + 0.1 * Math.random()) * (3 / tech.harmonics)) + ")";
+ // ctx.fillStyle = "rgba(110,170,200," + Math.min(0.7, m.energy * (0.22 - 0.01 * tech.harmonics) * (0.5 + 0.5 * Math.random())) + ")";
+ for (let i = 0; i < tech.harmonics; i++) {
+ ctx.beginPath();
+ ctx.ellipse(m.pos.x, m.pos.y, radius * Math.abs(Math.sin(phase + i / tech.harmonics * Math.PI)), radius, rotation + i / tech.harmonics * Math.PI, 0, 2 * Math.PI);
+ ctx.fill();
+ ctx.stroke();
+ }
+ //360 block
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) - mob[i].radius < radius && !mob[i].isUnblockable) { // && Matter.Query.ray(map, mob[i].position, m.pos).length === 0
+ mob[i].locatePlayer();
+ if (this.drainCD > m.cycle) {
+ m.pushMass(mob[i], 0);
+ } else {
+ m.pushMass(mob[i]);
+ this.drainCD = m.cycle + 10
+ }
+ if (mob[i].isShielded) m.fieldCDcycle = m.cycle + 45
+ }
+ }
+ }
+ if (tech.harmonics === 2) {
+ m.harmonicShield = m.harmonic3Phase
+ } else {
+ m.harmonicShield = m.harmonicAtomic
+ }
+ m.hold = function () {
+ if (m.isHolding) {
+ m.drawHold(m.holdingTarget);
+ m.holding();
+ m.throwBlock();
+ } else if ((input.field) && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
+ m.grabPowerUp();
+ m.lookForPickUp();
+ } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
+ m.pickUp();
+ } else {
+ m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ }
+ if (m.energy > 0.1 && m.fieldCDcycle < m.cycle) {
+ if (tech.isStandingWaveExpand) {
+ if (input.field) {
+ // const oldHarmonicRadius = m.harmonicRadius
+ m.harmonicRadius = 0.985 * m.harmonicRadius + 0.015 * 2.5
+ // m.energy -= 0.1 * (m.harmonicRadius - oldHarmonicRadius)
+ } else {
+ m.harmonicRadius = 0.995 * m.harmonicRadius + 0.005
+ }
+ }
+ m.harmonicShield()
+ }
+ m.drawFieldMeter()
+ }
+ }
+ },
+ {
+ name: "perfect diamagnetism",
+ description: "attract power ups from far away
deflecting does not drain energy
maintains functionality while inactive",
+ // description: "attract power ups from far away
deflecting doesn't drain energy
thrown blocks have",
+ // description: "gain energy when blocking
no recoil when blocking",
+ effect: () => {
+ m.fieldShieldingScale = 0;
+ m.fieldBlockCD = 3;
+ m.grabPowerUpRange2 = 10000000
+ m.fieldPosition = { x: m.pos.x, y: m.pos.y }
+ m.fieldAngle = m.angle
+ m.perfectPush = (isFree = false) => {
+ if (m.fieldCDcycle < m.cycle) {
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (
+ Vector.magnitude(Vector.sub(mob[i].position, m.fieldPosition)) - mob[i].radius < m.fieldRange &&
+ !mob[i].isUnblockable &&
+ Vector.dot({ x: Math.cos(m.fieldAngle), y: Math.sin(m.fieldAngle) }, Vector.normalise(Vector.sub(mob[i].position, m.fieldPosition))) > m.fieldThreshold &&
+ Matter.Query.ray(map, mob[i].position, m.fieldPosition).length === 0
+ ) {
+ mob[i].locatePlayer();
+ const unit = Vector.normalise(Vector.sub(m.fieldPosition, mob[i].position))
+ m.fieldCDcycle = m.cycle + m.fieldBlockCD + (mob[i].isShielded ? 15 : 0);
+ if (tech.blockingIce) {
+ for (let i = 0; i < 2 * tech.blockingIce; i++) {
+ const angle = m.fieldAngle + 1.55 * (Math.random() - 0.5)
+ b.iceIX(10, angle, Vector.add(m.fieldPosition, { x: m.fieldRange * Math.cos(angle), y: m.fieldRange * Math.sin(angle) }))
+ }
+ }
+ if (tech.blockDmg) { //electricity
+ mob[i].damage(tech.blockDmg * b.dmgScale)
+ const step = 40
+ ctx.beginPath();
+ for (let i = 0, len = 1.5 * tech.blockDmg; i < len; i++) {
+ let x = m.fieldPosition.x - 20 * unit.x;
+ let y = m.fieldPosition.y - 20 * unit.y;
+ ctx.moveTo(x, y);
+ for (let i = 0; i < 8; i++) {
+ x += step * (-unit.x + 1.5 * (Math.random() - 0.5))
+ y += step * (-unit.y + 1.5 * (Math.random() - 0.5))
+ ctx.lineTo(x, y);
}
}
- if (tech.blockDmg) { //electricity
- mob[i].damage(tech.blockDmg * b.dmgScale)
- const step = 40
- ctx.beginPath();
- for (let i = 0, len = 1.5 * tech.blockDmg; i < len; i++) {
- let x = m.fieldPosition.x - 20 * unit.x;
- let y = m.fieldPosition.y - 20 * unit.y;
- ctx.moveTo(x, y);
- for (let i = 0; i < 8; i++) {
- x += step * (-unit.x + 1.5 * (Math.random() - 0.5))
- y += step * (-unit.y + 1.5 * (Math.random() - 0.5))
- ctx.lineTo(x, y);
- }
- }
- ctx.lineWidth = 3;
- ctx.strokeStyle = "#f0f";
- ctx.stroke();
- } else if (isFree) {
- //when blocking draw this graphic
- ctx.fillStyle = "rgba(110,170,200," + (0.2 + 0.4 * Math.random()) + ")";
- ctx.lineWidth = 2;
- ctx.strokeStyle = "#000";
- const len = mob[i].vertices.length - 1;
- const mag = mob[i].radius
- ctx.beginPath();
- ctx.moveTo(mob[i].vertices[len].x + mag * (Math.random() - 0.5), mob[i].vertices[len].y + mag * (Math.random() - 0.5))
- for (let j = 0; j < len; j++) {
- ctx.lineTo(mob[i].vertices[j].x + mag * (Math.random() - 0.5), mob[i].vertices[j].y + mag * (Math.random() - 0.5));
- }
- ctx.lineTo(mob[i].vertices[len].x + mag * (Math.random() - 0.5), mob[i].vertices[len].y + mag * (Math.random() - 0.5))
- ctx.fill();
- ctx.stroke();
- } else {
- //when blocking draw this graphic
- const eye = 15;
- const len = mob[i].vertices.length - 1;
- ctx.fillStyle = "rgba(110,170,200," + (0.2 + 0.4 * Math.random()) + ")";
- ctx.lineWidth = 1;
- ctx.strokeStyle = "#000";
+ ctx.lineWidth = 3;
+ ctx.strokeStyle = "#f0f";
+ ctx.stroke();
+ } else if (isFree) {
+ //when blocking draw this graphic
+ ctx.fillStyle = "rgba(110,170,200," + (0.2 + 0.4 * Math.random()) + ")";
+ ctx.lineWidth = 2;
+ ctx.strokeStyle = "#000";
+ const len = mob[i].vertices.length - 1;
+ const mag = mob[i].radius
+ ctx.beginPath();
+ ctx.moveTo(mob[i].vertices[len].x + mag * (Math.random() - 0.5), mob[i].vertices[len].y + mag * (Math.random() - 0.5))
+ for (let j = 0; j < len; j++) {
+ ctx.lineTo(mob[i].vertices[j].x + mag * (Math.random() - 0.5), mob[i].vertices[j].y + mag * (Math.random() - 0.5));
+ }
+ ctx.lineTo(mob[i].vertices[len].x + mag * (Math.random() - 0.5), mob[i].vertices[len].y + mag * (Math.random() - 0.5))
+ ctx.fill();
+ ctx.stroke();
+ } else {
+ //when blocking draw this graphic
+ const eye = 15;
+ const len = mob[i].vertices.length - 1;
+ ctx.fillStyle = "rgba(110,170,200," + (0.2 + 0.4 * Math.random()) + ")";
+ ctx.lineWidth = 1;
+ ctx.strokeStyle = "#000";
+ ctx.beginPath();
+ ctx.moveTo(m.fieldPosition.x + eye * Math.cos(m.fieldAngle), m.fieldPosition.y + eye * Math.sin(m.fieldAngle));
+ ctx.lineTo(mob[i].vertices[len].x, mob[i].vertices[len].y);
+ ctx.lineTo(mob[i].vertices[0].x, mob[i].vertices[0].y);
+ ctx.fill();
+ ctx.stroke();
+ for (let j = 0; j < len; j++) {
ctx.beginPath();
ctx.moveTo(m.fieldPosition.x + eye * Math.cos(m.fieldAngle), m.fieldPosition.y + eye * Math.sin(m.fieldAngle));
- ctx.lineTo(mob[i].vertices[len].x, mob[i].vertices[len].y);
- ctx.lineTo(mob[i].vertices[0].x, mob[i].vertices[0].y);
+ ctx.lineTo(mob[i].vertices[j].x, mob[i].vertices[j].y);
+ ctx.lineTo(mob[i].vertices[j + 1].x, mob[i].vertices[j + 1].y);
ctx.fill();
ctx.stroke();
- for (let j = 0; j < len; j++) {
- ctx.beginPath();
- ctx.moveTo(m.fieldPosition.x + eye * Math.cos(m.fieldAngle), m.fieldPosition.y + eye * Math.sin(m.fieldAngle));
- ctx.lineTo(mob[i].vertices[j].x, mob[i].vertices[j].y);
- ctx.lineTo(mob[i].vertices[j + 1].x, mob[i].vertices[j + 1].y);
- ctx.fill();
- ctx.stroke();
- }
}
- if (tech.isStunField) mobs.statusStun(mob[i], tech.isStunField)
- //mob knock backs
- const massRoot = Math.sqrt(Math.max(1, mob[i].mass));
- Matter.Body.setVelocity(mob[i], {
- x: player.velocity.x - (30 * unit.x) / massRoot,
- y: player.velocity.y - (30 * unit.y) / massRoot
- });
- if (mob[i].isOrbital) Matter.Body.setVelocity(mob[i], { x: 0, y: 0 });
- if (!isFree) { //player knock backs
- if (mob[i].isDropPowerUp && player.speed < 12) {
- const massRootCap = Math.sqrt(Math.min(10, Math.max(0.2, mob[i].mass)));
- Matter.Body.setVelocity(player, {
- x: 0.9 * player.velocity.x + 0.6 * unit.x * massRootCap,
- y: 0.9 * player.velocity.y + 0.6 * unit.y * massRootCap
- });
- }
+ }
+ if (tech.isStunField) mobs.statusStun(mob[i], tech.isStunField)
+ //mob knock backs
+ const massRoot = Math.sqrt(Math.max(1, mob[i].mass));
+ Matter.Body.setVelocity(mob[i], {
+ x: player.velocity.x - (30 * unit.x) / massRoot,
+ y: player.velocity.y - (30 * unit.y) / massRoot
+ });
+ if (mob[i].isOrbital) Matter.Body.setVelocity(mob[i], { x: 0, y: 0 });
+ if (!isFree) { //player knock backs
+ if (mob[i].isDropPowerUp && player.speed < 12) {
+ const massRootCap = Math.sqrt(Math.min(10, Math.max(0.2, mob[i].mass)));
+ Matter.Body.setVelocity(player, {
+ x: 0.9 * player.velocity.x + 0.6 * unit.x * massRootCap,
+ y: 0.9 * player.velocity.y + 0.6 * unit.y * massRootCap
+ });
}
}
}
}
}
- m.hold = function() {
- const wave = Math.sin(m.cycle * 0.022);
- m.fieldRange = 160 + 12 * wave + 100 * tech.isBigField
- m.fieldArc = 0.34 + 0.04 * wave + 0.065 * tech.isBigField //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
- m.calculateFieldThreshold();
- if (m.isHolding) {
- m.drawHold(m.holdingTarget);
- m.holding();
- m.throwBlock();
- } else if (input.field) { //not hold but field button is pressed
- m.grabPowerUp();
- m.lookForPickUp();
- m.fieldPosition = { x: m.pos.x, y: m.pos.y }
- m.fieldAngle = m.angle
- //draw field attached to player
- if (m.holdingTarget) {
- ctx.fillStyle = "rgba(110,170,200," + (0.06 + 0.03 * Math.random()) + ")";
- ctx.strokeStyle = "rgba(110, 200, 235, " + (0.35 + 0.05 * Math.random()) + ")"
- } else {
- ctx.fillStyle = "rgba(110,170,200," + (0.27 + 0.2 * Math.random() - 0.1 * wave) + ")";
- ctx.strokeStyle = "rgba(110, 200, 235, " + (0.4 + 0.5 * Math.random()) + ")"
- }
+ }
+ m.hold = function () {
+ const wave = Math.sin(m.cycle * 0.022);
+ m.fieldRange = 160 + 12 * wave + 100 * tech.isBigField
+ m.fieldArc = 0.34 + 0.04 * wave + 0.065 * tech.isBigField //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
+ m.calculateFieldThreshold();
+ if (m.isHolding) {
+ m.drawHold(m.holdingTarget);
+ m.holding();
+ m.throwBlock();
+ } else if (input.field) { //not hold but field button is pressed
+ m.grabPowerUp();
+ m.lookForPickUp();
+ m.fieldPosition = { x: m.pos.x, y: m.pos.y }
+ m.fieldAngle = m.angle
+ //draw field attached to player
+ if (m.holdingTarget) {
+ ctx.fillStyle = "rgba(110,170,200," + (0.06 + 0.03 * Math.random()) + ")";
+ ctx.strokeStyle = "rgba(110, 200, 235, " + (0.35 + 0.05 * Math.random()) + ")"
+ } else {
+ ctx.fillStyle = "rgba(110,170,200," + (0.27 + 0.2 * Math.random() - 0.1 * wave) + ")";
+ ctx.strokeStyle = "rgba(110, 200, 235, " + (0.4 + 0.5 * Math.random()) + ")"
+ }
+ ctx.beginPath();
+ ctx.arc(m.pos.x, m.pos.y, m.fieldRange, m.angle - Math.PI * m.fieldArc, m.angle + Math.PI * m.fieldArc, false);
+ ctx.lineWidth = 2.5 - 1.5 * wave;
+ ctx.lineCap = "butt"
+ ctx.stroke();
+ const curve = 0.57 + 0.04 * wave
+ const aMag = (1 - curve * 1.2) * Math.PI * m.fieldArc
+ let a = m.angle + aMag
+ let cp1x = m.pos.x + curve * m.fieldRange * Math.cos(a)
+ let cp1y = m.pos.y + curve * m.fieldRange * Math.sin(a)
+ ctx.quadraticCurveTo(cp1x, cp1y, m.pos.x + 30 * Math.cos(m.angle), m.pos.y + 30 * Math.sin(m.angle))
+ a = m.angle - aMag
+ cp1x = m.pos.x + curve * m.fieldRange * Math.cos(a)
+ cp1y = m.pos.y + curve * m.fieldRange * Math.sin(a)
+ ctx.quadraticCurveTo(cp1x, cp1y, m.pos.x + 1 * m.fieldRange * Math.cos(m.angle - Math.PI * m.fieldArc), m.pos.y + 1 * m.fieldRange * Math.sin(m.angle - Math.PI * m.fieldArc))
+ ctx.fill();
+ m.perfectPush();
+ } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
+ m.pickUp();
+ } else {
+ m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ if (!input.field) { //&& tech.isFieldFree
+ //draw field free of player
+ ctx.fillStyle = "rgba(110,170,200," + (0.27 + 0.2 * Math.random() - 0.1 * wave) + ")";
+ ctx.strokeStyle = "rgba(110, 200, 235, " + (0.4 + 0.5 * Math.random()) + ")"
ctx.beginPath();
- ctx.arc(m.pos.x, m.pos.y, m.fieldRange, m.angle - Math.PI * m.fieldArc, m.angle + Math.PI * m.fieldArc, false);
+ ctx.arc(m.fieldPosition.x, m.fieldPosition.y, m.fieldRange, m.fieldAngle - Math.PI * m.fieldArc, m.fieldAngle + Math.PI * m.fieldArc, false);
ctx.lineWidth = 2.5 - 1.5 * wave;
ctx.lineCap = "butt"
ctx.stroke();
- const curve = 0.57 + 0.04 * wave
+ const curve = 0.8 + 0.06 * wave
const aMag = (1 - curve * 1.2) * Math.PI * m.fieldArc
- let a = m.angle + aMag
- let cp1x = m.pos.x + curve * m.fieldRange * Math.cos(a)
- let cp1y = m.pos.y + curve * m.fieldRange * Math.sin(a)
- ctx.quadraticCurveTo(cp1x, cp1y, m.pos.x + 30 * Math.cos(m.angle), m.pos.y + 30 * Math.sin(m.angle))
- a = m.angle - aMag
- cp1x = m.pos.x + curve * m.fieldRange * Math.cos(a)
- cp1y = m.pos.y + curve * m.fieldRange * Math.sin(a)
- ctx.quadraticCurveTo(cp1x, cp1y, m.pos.x + 1 * m.fieldRange * Math.cos(m.angle - Math.PI * m.fieldArc), m.pos.y + 1 * m.fieldRange * Math.sin(m.angle - Math.PI * m.fieldArc))
- ctx.fill();
- m.perfectPush();
- } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
- m.pickUp();
- } else {
- m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- if (!input.field) { //&& tech.isFieldFree
- //draw field free of player
- ctx.fillStyle = "rgba(110,170,200," + (0.27 + 0.2 * Math.random() - 0.1 * wave) + ")";
- ctx.strokeStyle = "rgba(110, 200, 235, " + (0.4 + 0.5 * Math.random()) + ")"
- ctx.beginPath();
- ctx.arc(m.fieldPosition.x, m.fieldPosition.y, m.fieldRange, m.fieldAngle - Math.PI * m.fieldArc, m.fieldAngle + Math.PI * m.fieldArc, false);
- ctx.lineWidth = 2.5 - 1.5 * wave;
- ctx.lineCap = "butt"
- ctx.stroke();
- const curve = 0.8 + 0.06 * wave
- const aMag = (1 - curve * 1.2) * Math.PI * m.fieldArc
- let a = m.fieldAngle + aMag
- ctx.quadraticCurveTo(m.fieldPosition.x + curve * m.fieldRange * Math.cos(a), m.fieldPosition.y + curve * m.fieldRange * Math.sin(a), m.fieldPosition.x + 1 * m.fieldRange * Math.cos(m.fieldAngle - Math.PI * m.fieldArc), m.fieldPosition.y + 1 * m.fieldRange * Math.sin(m.fieldAngle - Math.PI * m.fieldArc))
- ctx.fill();
- m.perfectPush(true);
- }
- }
- m.drawFieldMeter()
- if (tech.isPerfectBrake) { //cap mob speed around player
- const range = 200 + 140 * wave + 150 * m.energy
- for (let i = 0; i < mob.length; i++) {
- const distance = Vector.magnitude(Vector.sub(m.pos, mob[i].position))
- if (distance < range) {
- const cap = mob[i].isShielded ? 8 : 4
- if (mob[i].speed > cap && Vector.dot(mob[i].velocity, Vector.sub(m.pos, mob[i].position)) > 0) { // if velocity is directed towards player
- Matter.Body.setVelocity(mob[i], Vector.mult(Vector.normalise(mob[i].velocity), cap)); //set velocity to cap, but keep the direction
- }
- }
- }
- ctx.beginPath();
- ctx.arc(m.pos.x, m.pos.y, range, 0, 2 * Math.PI);
- ctx.fillStyle = "hsla(200,50%,61%,0.08)";
+ let a = m.fieldAngle + aMag
+ ctx.quadraticCurveTo(m.fieldPosition.x + curve * m.fieldRange * Math.cos(a), m.fieldPosition.y + curve * m.fieldRange * Math.sin(a), m.fieldPosition.x + 1 * m.fieldRange * Math.cos(m.fieldAngle - Math.PI * m.fieldArc), m.fieldPosition.y + 1 * m.fieldRange * Math.sin(m.fieldAngle - Math.PI * m.fieldArc))
ctx.fill();
+ m.perfectPush(true);
}
}
- }
- },
- {
- name: "negative mass",
- description: "use energy to nullify gravity
reduce harm by 55%
hold blocks as if they have a lower mass",
- fieldDrawRadius: 0,
- effect: () => {
- m.fieldFire = true;
- m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping
- m.fieldMeterColor = "#333"
- m.eyeFillColor = m.fieldMeterColor
- m.fieldHarmReduction = 0.45; //55% reduction
- m.fieldDrawRadius = 0;
-
- m.hold = function() {
- m.airSpeedLimit = 125 //5 * player.mass * player.mass
- m.FxAir = 0.016
- if (m.isHolding) {
- m.drawHold(m.holdingTarget);
- m.holding();
- m.throwBlock();
- } else if (input.field && m.fieldCDcycle < m.cycle) { //push away
- m.grabPowerUp();
- m.lookForPickUp();
- const DRAIN = 0.00035
- if (m.energy > DRAIN) {
- if (tech.isFlyFaster) {
- //look for nearby objects to make zero-g
- function moveThis(who, range, mag = 1.06) {
- for (let i = 0, len = who.length; i < len; ++i) {
- sub = Vector.sub(who[i].position, m.pos);
- dist = Vector.magnitude(sub);
- if (dist < range) {
- who[i].force.y -= who[i].mass * (simulation.g * mag); //add a bit more then standard gravity
- if (input.left) { //blocks move horizontally with the same force as the player
- who[i].force.x -= m.FxAir * who[i].mass / 10; // move player left / a
- } else if (input.right) {
- who[i].force.x += m.FxAir * who[i].mass / 10; //move player right / d
- }
- //loose attraction to player
- // const sub = Vector.sub(m.pos, body[i].position)
- // const unit = Vector.mult(Vector.normalise(sub), who[i].mass * 0.0000002 * Vector.magnitude(sub))
- // body[i].force.x += unit.x
- // body[i].force.y += unit.y
- }
- }
- }
- //control horizontal acceleration
- m.airSpeedLimit = 1000 // 7* player.mass * player.mass
- m.FxAir = 0.01
- //control vertical acceleration
- if (input.down) { //down
- player.force.y += 0.5 * player.mass * simulation.g;
- this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 500 * 0.03;
- moveThis(powerUp, this.fieldDrawRadius, 0);
- moveThis(body, this.fieldDrawRadius, 0);
- } else if (input.up) { //up
- m.energy -= 5 * DRAIN;
- this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 1100 * 0.03;
- player.force.y -= 2.25 * player.mass * simulation.g;
- moveThis(powerUp, this.fieldDrawRadius, 1.8);
- moveThis(body, this.fieldDrawRadius, 1.8);
- } else {
- m.energy -= DRAIN;
- this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 800 * 0.03;
- player.force.y -= 1.07 * player.mass * simulation.g; // slow upward drift
- moveThis(powerUp, this.fieldDrawRadius);
- moveThis(body, this.fieldDrawRadius);
- }
- } else {
- //look for nearby objects to make zero-g
- function verticalForce(who, range, mag = 1.06) {
- for (let i = 0, len = who.length; i < len; ++i) {
- sub = Vector.sub(who[i].position, m.pos);
- dist = Vector.magnitude(sub);
- if (dist < range) who[i].force.y -= who[i].mass * (simulation.g * mag);
- }
- }
- //control horizontal acceleration
- m.airSpeedLimit = 400 // 7* player.mass * player.mass
- m.FxAir = 0.005
- //control vertical acceleration
- if (input.down) { //down
- player.force.y -= 0.5 * player.mass * simulation.g;
- this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 400 * 0.03;
- verticalForce(powerUp, this.fieldDrawRadius, 0.7);
- verticalForce(body, this.fieldDrawRadius, 0.7);
- } else if (input.up) { //up
- m.energy -= 5 * DRAIN;
- this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 850 * 0.03;
- player.force.y -= 1.45 * player.mass * simulation.g;
- verticalForce(powerUp, this.fieldDrawRadius, 1.38);
- verticalForce(body, this.fieldDrawRadius, 1.38);
- } else {
- m.energy -= DRAIN;
- this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 650 * 0.03;
- player.force.y -= 1.07 * player.mass * simulation.g; // slow upward drift
- verticalForce(powerUp, this.fieldDrawRadius);
- verticalForce(body, this.fieldDrawRadius);
- }
+ m.drawFieldMeter()
+ if (tech.isPerfectBrake) { //cap mob speed around player
+ const range = 200 + 140 * wave + 150 * m.energy
+ for (let i = 0; i < mob.length; i++) {
+ const distance = Vector.magnitude(Vector.sub(m.pos, mob[i].position))
+ if (distance < range) {
+ const cap = mob[i].isShielded ? 8 : 4
+ if (mob[i].speed > cap && Vector.dot(mob[i].velocity, Vector.sub(m.pos, mob[i].position)) > 0) { // if velocity is directed towards player
+ Matter.Body.setVelocity(mob[i], Vector.mult(Vector.normalise(mob[i].velocity), cap)); //set velocity to cap, but keep the direction
}
-
- if (m.energy < 0.001) {
- m.fieldCDcycle = m.cycle + 120;
- m.energy = 0;
- }
- //add extra friction for horizontal motion
- if (input.down || input.up || input.left || input.right) {
- Matter.Body.setVelocity(player, {
- x: player.velocity.x * 0.99,
- y: player.velocity.y * 0.98
- });
- } else { //slow rise and fall
- Matter.Body.setVelocity(player, {
- x: player.velocity.x * 0.99,
- y: player.velocity.y * 0.98
- });
- }
- if (tech.isFreezeMobs) {
- const ICE_DRAIN = 0.0002
- for (let i = 0, len = mob.length; i < len; i++) {
- if (((mob[i].distanceToPlayer() + mob[i].radius) < this.fieldDrawRadius) && !mob[i].shield && !mob[i].isShielded) {
- if (m.energy > ICE_DRAIN * 2) {
- m.energy -= ICE_DRAIN;
- this.fieldDrawRadius -= 2;
- mobs.statusSlow(mob[i], 60)
- } else {
- break;
- }
- }
- }
- }
-
- //draw zero-G range
- ctx.beginPath();
- ctx.arc(m.pos.x, m.pos.y, this.fieldDrawRadius, 0, 2 * Math.PI);
- ctx.fillStyle = "#f5f5ff";
- ctx.globalCompositeOperation = "difference";
- ctx.fill();
- ctx.globalCompositeOperation = "source-over";
}
- } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
- m.pickUp();
- this.fieldDrawRadius = 0
- } else {
- m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- this.fieldDrawRadius = 0
}
- m.drawFieldMeter("rgba(0,0,0,0.2)")
+ ctx.beginPath();
+ ctx.arc(m.pos.x, m.pos.y, range, 0, 2 * Math.PI);
+ ctx.fillStyle = "hsla(200,50%,61%,0.08)";
+ ctx.fill();
}
}
- },
- {
- name: "molecular assembler",
- description: "excess energy used to build drones
use energy to deflect mobs
double your default energy regeneration",
- effect: () => {
- // m.fieldMeterColor = "#0c5"
- // m.eyeFillColor = m.fieldMeterColor
- m.hold = function() {
- if (m.energy > m.maxEnergy - 0.02 && m.fieldCDcycle < m.cycle && !input.field && bullet.length < 200 && (m.cycle % 2)) {
- if (tech.isSporeField) {
- if (tech.isSporeWorm) {
- if (m.energy > 0.16) {
- m.energy -= 0.16
- b.worm({ x: m.pos.x + 35 * Math.cos(m.angle), y: m.pos.y + 35 * Math.sin(m.angle) })
- const SPEED = 2 + 1 * Math.random();
- Matter.Body.setVelocity(bullet[bullet.length - 1], {
- x: SPEED * Math.cos(m.angle),
- y: SPEED * Math.sin(m.angle)
- });
+ }
+ },
+ {
+ name: "negative mass",
+ description: "use energy to nullify gravity
reduce harm by 55%
hold blocks as if they have a lower mass",
+ fieldDrawRadius: 0,
+ effect: () => {
+ m.fieldFire = true;
+ m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping
+ m.fieldMeterColor = "#333"
+ m.eyeFillColor = m.fieldMeterColor
+ m.fieldHarmReduction = 0.45; //55% reduction
+ m.fieldDrawRadius = 0;
+
+ m.hold = function () {
+ m.airSpeedLimit = 125 //5 * player.mass * player.mass
+ m.FxAir = 0.016
+ if (m.isHolding) {
+ m.drawHold(m.holdingTarget);
+ m.holding();
+ m.throwBlock();
+ } else if (input.field && m.fieldCDcycle < m.cycle) { //push away
+ m.grabPowerUp();
+ m.lookForPickUp();
+ const DRAIN = 0.00035
+ if (m.energy > DRAIN) {
+ if (tech.isFlyFaster) {
+ //look for nearby objects to make zero-g
+ function moveThis(who, range, mag = 1.06) {
+ for (let i = 0, len = who.length; i < len; ++i) {
+ sub = Vector.sub(who[i].position, m.pos);
+ dist = Vector.magnitude(sub);
+ if (dist < range) {
+ who[i].force.y -= who[i].mass * (simulation.g * mag); //add a bit more then standard gravity
+ if (input.left) { //blocks move horizontally with the same force as the player
+ who[i].force.x -= m.FxAir * who[i].mass / 10; // move player left / a
+ } else if (input.right) {
+ who[i].force.x += m.FxAir * who[i].mass / 10; //move player right / d
+ }
+ //loose attraction to player
+ // const sub = Vector.sub(m.pos, body[i].position)
+ // const unit = Vector.mult(Vector.normalise(sub), who[i].mass * 0.0000002 * Vector.magnitude(sub))
+ // body[i].force.x += unit.x
+ // body[i].force.y += unit.y
+ }
}
+ }
+ //control horizontal acceleration
+ m.airSpeedLimit = 1000 // 7* player.mass * player.mass
+ m.FxAir = 0.01
+ //control vertical acceleration
+ if (input.down) { //down
+ player.force.y += 0.5 * player.mass * simulation.g;
+ this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 500 * 0.03;
+ moveThis(powerUp, this.fieldDrawRadius, 0);
+ moveThis(body, this.fieldDrawRadius, 0);
+ } else if (input.up) { //up
+ m.energy -= 5 * DRAIN;
+ this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 1100 * 0.03;
+ player.force.y -= 2.25 * player.mass * simulation.g;
+ moveThis(powerUp, this.fieldDrawRadius, 1.8);
+ moveThis(body, this.fieldDrawRadius, 1.8);
} else {
- for (let i = 0, len = Math.random() * 20; i < len; i++) {
- m.energy -= 0.08
- if (m.energy > 0) {
- b.spore(m.pos)
+ m.energy -= DRAIN;
+ this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 800 * 0.03;
+ player.force.y -= 1.07 * player.mass * simulation.g; // slow upward drift
+ moveThis(powerUp, this.fieldDrawRadius);
+ moveThis(body, this.fieldDrawRadius);
+ }
+ } else {
+ //look for nearby objects to make zero-g
+ function verticalForce(who, range, mag = 1.06) {
+ for (let i = 0, len = who.length; i < len; ++i) {
+ sub = Vector.sub(who[i].position, m.pos);
+ dist = Vector.magnitude(sub);
+ if (dist < range) who[i].force.y -= who[i].mass * (simulation.g * mag);
+ }
+ }
+ //control horizontal acceleration
+ m.airSpeedLimit = 400 // 7* player.mass * player.mass
+ m.FxAir = 0.005
+ //control vertical acceleration
+ if (input.down) { //down
+ player.force.y -= 0.5 * player.mass * simulation.g;
+ this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 400 * 0.03;
+ verticalForce(powerUp, this.fieldDrawRadius, 0.7);
+ verticalForce(body, this.fieldDrawRadius, 0.7);
+ } else if (input.up) { //up
+ m.energy -= 5 * DRAIN;
+ this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 850 * 0.03;
+ player.force.y -= 1.45 * player.mass * simulation.g;
+ verticalForce(powerUp, this.fieldDrawRadius, 1.38);
+ verticalForce(body, this.fieldDrawRadius, 1.38);
+ } else {
+ m.energy -= DRAIN;
+ this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 650 * 0.03;
+ player.force.y -= 1.07 * player.mass * simulation.g; // slow upward drift
+ verticalForce(powerUp, this.fieldDrawRadius);
+ verticalForce(body, this.fieldDrawRadius);
+ }
+ }
+
+ if (m.energy < 0.001) {
+ m.fieldCDcycle = m.cycle + 120;
+ m.energy = 0;
+ }
+ //add extra friction for horizontal motion
+ if (input.down || input.up || input.left || input.right) {
+ Matter.Body.setVelocity(player, {
+ x: player.velocity.x * 0.99,
+ y: player.velocity.y * 0.98
+ });
+ } else { //slow rise and fall
+ Matter.Body.setVelocity(player, {
+ x: player.velocity.x * 0.99,
+ y: player.velocity.y * 0.98
+ });
+ }
+ if (tech.isFreezeMobs) {
+ const ICE_DRAIN = 0.0002
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (((mob[i].distanceToPlayer() + mob[i].radius) < this.fieldDrawRadius) && !mob[i].shield && !mob[i].isShielded) {
+ if (m.energy > ICE_DRAIN * 2) {
+ m.energy -= ICE_DRAIN;
+ this.fieldDrawRadius -= 2;
+ mobs.statusSlow(mob[i], 60)
} else {
- m.energy = 0.001
break;
}
}
}
- } else if (tech.isMissileField) {
- m.energy -= 0.3;
- b.missile({ x: m.pos.x, y: m.pos.y - 40 }, -Math.PI / 2 + 0.5 * (Math.random() - 0.5), 0, 1)
- } else if (tech.isIceField) {
- m.energy -= 0.04;
- b.iceIX(1)
- } else if (tech.isDroneRadioactive) {
- m.energy -= 0.8;
- b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 25)
- } else {
- m.energy -= 0.45 * tech.droneEnergyReduction;
- b.drone()
}
- }
+ //draw zero-G range
+ ctx.beginPath();
+ ctx.arc(m.pos.x, m.pos.y, this.fieldDrawRadius, 0, 2 * Math.PI);
+ ctx.fillStyle = "#f5f5ff";
+ ctx.globalCompositeOperation = "difference";
+ ctx.fill();
+ ctx.globalCompositeOperation = "source-over";
+ }
+ } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
+ m.pickUp();
+ this.fieldDrawRadius = 0
+ } else {
+ m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ this.fieldDrawRadius = 0
+ }
+ m.drawFieldMeter("rgba(0,0,0,0.2)")
+ }
+ }
+ },
+ {
+ name: "molecular assembler",
+ description: "excess energy used to build drones
use energy to deflect mobs
double your default energy regeneration",
+ effect: () => {
+ // m.fieldMeterColor = "#0c5"
+ // m.eyeFillColor = m.fieldMeterColor
+ m.hold = function () {
+ if (m.energy > m.maxEnergy - 0.02 && m.fieldCDcycle < m.cycle && !input.field && bullet.length < 200 && (m.cycle % 2)) {
+ if (tech.isSporeField) {
+ if (tech.isSporeWorm) {
+ if (m.energy > 0.16) {
+ m.energy -= 0.16
+ b.worm({ x: m.pos.x + 35 * Math.cos(m.angle), y: m.pos.y + 35 * Math.sin(m.angle) })
+ const SPEED = 2 + 1 * Math.random();
+ Matter.Body.setVelocity(bullet[bullet.length - 1], {
+ x: SPEED * Math.cos(m.angle),
+ y: SPEED * Math.sin(m.angle)
+ });
+ }
+ } else {
+ for (let i = 0, len = Math.random() * 20; i < len; i++) {
+ m.energy -= 0.08
+ if (m.energy > 0) {
+ b.spore(m.pos)
+ } else {
+ m.energy = 0.001
+ break;
+ }
+ }
+ }
+ } else if (tech.isMissileField) {
+ m.energy -= 0.3;
+ b.missile({ x: m.pos.x, y: m.pos.y - 40 }, -Math.PI / 2 + 0.5 * (Math.random() - 0.5), 0, 1)
+ } else if (tech.isIceField) {
+ m.energy -= 0.04;
+ b.iceIX(1)
+ } else if (tech.isDroneRadioactive) {
+ m.energy -= 0.8;
+ b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 25)
+ } else {
+ m.energy -= 0.45 * tech.droneEnergyReduction;
+ b.drone()
+ }
+ }
+
+ if (m.isHolding) {
+ m.drawHold(m.holdingTarget);
+ m.holding();
+ m.throwBlock();
+ } else if ((input.field && m.fieldCDcycle < m.cycle)) { //not hold but field button is pressed
+ m.grabPowerUp();
+ m.lookForPickUp();
+ if (m.energy > 0.05) {
+ m.drawField();
+ m.pushMobsFacing();
+ }
+ } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
+ m.pickUp();
+ } else {
+ m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ }
+ m.regenEnergy()
+ m.drawFieldMeter()
+ }
+ }
+ },
+ // {
+ // name: "plasma torch",
+ // description: "use energy to emit short range plasma
damages and pushes mobs away",
+ // effect() {
+ // m.fieldMeterColor = "#f0f"
+ // m.eyeFillColor = m.fieldMeterColor
+ // m.hold = function() {
+ // b.isExtruderOn = false
+ // if (m.isHolding) {
+ // m.drawHold(m.holdingTarget);
+ // m.holding();
+ // m.throwBlock();
+ // } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
+ // m.grabPowerUp();
+ // m.lookForPickUp();
+ // if (tech.isExtruder) {
+ // b.extruder();
+ // } else {
+ // b.plasma();
+ // }
+ // } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
+ // m.pickUp();
+ // } else {
+ // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ // }
+ // m.drawFieldMeter("rgba(0, 0, 0, 0.2)")
+
+ // if (tech.isExtruder) {
+ // if (input.field) {
+ // b.wasExtruderOn = true
+ // } else {
+ // b.wasExtruderOn = false
+ // b.canExtruderFire = true
+ // }
+ // ctx.beginPath(); //draw all the wave bullets
+ // for (let i = 0, len = bullet.length; i < len; i++) {
+ // if (bullet[i].isWave) {
+ // if (bullet[i].isBranch) {
+ // ctx.moveTo(bullet[i].position.x, bullet[i].position.y)
+ // } else {
+ // ctx.lineTo(bullet[i].position.x, bullet[i].position.y)
+ // }
+ // }
+ // }
+ // if (b.wasExtruderOn && b.isExtruderOn) ctx.lineTo(m.pos.x + 15 * Math.cos(m.angle), m.pos.y + 15 * Math.sin(m.angle))
+ // ctx.lineWidth = 4;
+ // ctx.strokeStyle = "#f07"
+ // ctx.stroke();
+ // ctx.lineWidth = tech.extruderRange;
+ // ctx.strokeStyle = "rgba(255,0,110,0.05)"
+ // ctx.stroke();
+ // }
+ // }
+ // }
+ // },
+ {
+ name: "plasma torch",
+ description: "use energy to emit short range plasma
damages and pushes mobs away",
+ set() {
+ b.isExtruderOn = false
+ if (tech.isExtruder) {
+ m.hold = function () {
+ b.isExtruderOn = false
if (m.isHolding) {
m.drawHold(m.holdingTarget);
m.holding();
m.throwBlock();
- } else if ((input.field && m.fieldCDcycle < m.cycle)) { //not hold but field button is pressed
+ } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
m.grabPowerUp();
m.lookForPickUp();
- if (m.energy > 0.05) {
- m.drawField();
- m.pushMobsFacing();
- }
+ b.extruder();
} else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
m.pickUp();
} else {
m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
}
- m.regenEnergy()
- m.drawFieldMeter()
+ m.drawFieldMeter("rgba(0, 0, 0, 0.2)")
+ if (input.field) {
+ b.wasExtruderOn = true
+ } else {
+ b.wasExtruderOn = false
+ b.canExtruderFire = true
+ }
+ ctx.beginPath(); //draw all the wave bullets
+ for (let i = 1, len = bullet.length; i < len; i++) { //skip the first bullet (which is is oldest bullet)
+ if (bullet[i].isWave) {
+ if (bullet[i].isBranch || bullet[i - 1].isBranch) {
+ ctx.moveTo(bullet[i].position.x, bullet[i].position.y)
+ } else {
+ ctx.lineTo(bullet[i].position.x, bullet[i].position.y)
+ }
+ }
+ }
+ if (b.wasExtruderOn && b.isExtruderOn) ctx.lineTo(m.pos.x + 15 * Math.cos(m.angle), m.pos.y + 15 * Math.sin(m.angle))
+ ctx.lineWidth = 4;
+ ctx.strokeStyle = "#f07"
+ ctx.stroke();
+ ctx.lineWidth = tech.extruderRange;
+ ctx.strokeStyle = "rgba(255,0,110,0.06)"
+ ctx.stroke();
+ }
+ } else {
+ m.hold = function () {
+ if (m.isHolding) {
+ m.drawHold(m.holdingTarget);
+ m.holding();
+ m.throwBlock();
+ } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
+ m.grabPowerUp();
+ m.lookForPickUp();
+ b.plasma();
+ } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
+ m.pickUp();
+ } else {
+ m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ }
+ m.drawFieldMeter("rgba(0, 0, 0, 0.2)")
}
}
},
- // {
- // name: "plasma torch",
- // description: "use energy to emit short range plasma
damages and pushes mobs away",
- // effect() {
- // m.fieldMeterColor = "#f0f"
- // m.eyeFillColor = m.fieldMeterColor
- // m.hold = function() {
- // b.isExtruderOn = false
- // if (m.isHolding) {
- // m.drawHold(m.holdingTarget);
- // m.holding();
- // m.throwBlock();
- // } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
- // m.grabPowerUp();
- // m.lookForPickUp();
- // if (tech.isExtruder) {
- // b.extruder();
- // } else {
- // b.plasma();
- // }
- // } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
- // m.pickUp();
- // } else {
- // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- // }
- // m.drawFieldMeter("rgba(0, 0, 0, 0.2)")
+ effect() {
+ m.fieldMeterColor = "#f0f"
+ m.eyeFillColor = m.fieldMeterColor
+ this.set();
+ }
+ },
+ {
+ name: "time dilation",
+ // description: "use energy to stop time
while time is stopped you can move and fire
and collisions do 50% less harm",
+ description: "use energy to stop time
move and fire while time is stopped
but, collisions still do harm",
+ set() {
+ if (tech.isRewindField) {
+ this.rewindCount = 0
+ m.grabPowerUpRange2 = 300000
+ m.hold = function () {
+ if (m.isHolding) {
+ m.drawHold(m.holdingTarget);
+ m.holding();
+ m.throwBlock();
+ } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
+ m.grabPowerUp();
+ if (this.rewindCount === 0) m.lookForPickUp();
- // if (tech.isExtruder) {
- // if (input.field) {
- // b.wasExtruderOn = true
- // } else {
- // b.wasExtruderOn = false
- // b.canExtruderFire = true
- // }
- // ctx.beginPath(); //draw all the wave bullets
- // for (let i = 0, len = bullet.length; i < len; i++) {
- // if (bullet[i].isWave) {
- // if (bullet[i].isBranch) {
- // ctx.moveTo(bullet[i].position.x, bullet[i].position.y)
- // } else {
- // ctx.lineTo(bullet[i].position.x, bullet[i].position.y)
- // }
- // }
- // }
- // if (b.wasExtruderOn && b.isExtruderOn) ctx.lineTo(m.pos.x + 15 * Math.cos(m.angle), m.pos.y + 15 * Math.sin(m.angle))
- // ctx.lineWidth = 4;
- // ctx.strokeStyle = "#f07"
- // ctx.stroke();
- // ctx.lineWidth = tech.extruderRange;
- // ctx.strokeStyle = "rgba(255,0,110,0.05)"
- // ctx.stroke();
- // }
- // }
- // }
- // },
- {
- name: "plasma torch",
- description: "use energy to emit short range plasma
damages and pushes mobs away",
- set() {
- b.isExtruderOn = false
- if (tech.isExtruder) {
- m.hold = function() {
- b.isExtruderOn = false
- if (m.isHolding) {
- m.drawHold(m.holdingTarget);
- m.holding();
- m.throwBlock();
- } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
- m.grabPowerUp();
- m.lookForPickUp();
- b.extruder();
- } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
- m.pickUp();
- } else {
- m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- }
- m.drawFieldMeter("rgba(0, 0, 0, 0.2)")
- if (input.field) {
- b.wasExtruderOn = true
- } else {
- b.wasExtruderOn = false
- b.canExtruderFire = true
- }
- ctx.beginPath(); //draw all the wave bullets
- for (let i = 1, len = bullet.length; i < len; i++) { //skip the first bullet (which is is oldest bullet)
- if (bullet[i].isWave) {
- if (bullet[i].isBranch || bullet[i - 1].isBranch) {
- ctx.moveTo(bullet[i].position.x, bullet[i].position.y)
- } else {
- ctx.lineTo(bullet[i].position.x, bullet[i].position.y)
- }
- }
- }
- if (b.wasExtruderOn && b.isExtruderOn) ctx.lineTo(m.pos.x + 15 * Math.cos(m.angle), m.pos.y + 15 * Math.sin(m.angle))
- ctx.lineWidth = 4;
- ctx.strokeStyle = "#f07"
- ctx.stroke();
- ctx.lineWidth = tech.extruderRange;
- ctx.strokeStyle = "rgba(255,0,110,0.06)"
- ctx.stroke();
- }
- } else {
- m.hold = function() {
- if (m.isHolding) {
- m.drawHold(m.holdingTarget);
- m.holding();
- m.throwBlock();
- } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
- m.grabPowerUp();
- m.lookForPickUp();
- b.plasma();
- } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
- m.pickUp();
- } else {
- m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- }
- m.drawFieldMeter("rgba(0, 0, 0, 0.2)")
- }
- }
- },
- effect() {
- m.fieldMeterColor = "#f0f"
- m.eyeFillColor = m.fieldMeterColor
- this.set();
- }
- },
- {
- name: "time dilation",
- // description: "use energy to stop time
while time is stopped you can move and fire
and collisions do 50% less harm",
- description: "use energy to stop time
move and fire while time is stopped
but, collisions still do harm",
- set() {
- if (tech.isRewindField) {
- this.rewindCount = 0
- m.grabPowerUpRange2 = 300000
- m.hold = function() {
- if (m.isHolding) {
- m.drawHold(m.holdingTarget);
- m.holding();
- m.throwBlock();
- } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
- m.grabPowerUp();
- if (this.rewindCount === 0) m.lookForPickUp();
-
- if (!m.holdingTarget) {
- this.rewindCount += 6;
- const DRAIN = 0.001
- let history = m.history[(m.cycle - this.rewindCount) % 600]
- if (this.rewindCount > 599 || m.energy < DRAIN) {
- this.rewindCount = 0;
- m.resetHistory();
- if (m.fireCDcycle < m.cycle + 60) m.fieldCDcycle = m.cycle + 60
- m.immuneCycle = m.cycle //if you reach the end of the history disable harm immunity
- } else {
- //draw field everywhere
- ctx.globalCompositeOperation = "saturation"
- ctx.fillStyle = "#ccc";
- ctx.fillRect(-100000, -100000, 200000, 200000)
- ctx.globalCompositeOperation = "source-over"
- // m.grabPowerUp(); //a second grab power up to make the power ups easier to grab, and they more fast which matches the time theme
- m.energy -= DRAIN
- if (m.immuneCycle < m.cycle + 60) m.immuneCycle = m.cycle + 60; //player is immune to damage for __ cycles
- Matter.Body.setPosition(player, history.position);
- Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
- if (m.health < history.health) {
- m.health = history.health
- if (m.health > m.maxHealth) m.health = m.maxHealth
- m.displayHealth();
- }
- m.yOff = history.yOff
- if (m.yOff < 48) {
- m.doCrouch()
- } else {
- m.undoCrouch()
- }
- //grab power ups
- for (let i = 0, len = powerUp.length; i < len; ++i) {
- if (
- Vector.magnitudeSquared(Vector.sub(m.pos, powerUp[i].position)) < 100000 &&
- !simulation.isChoosing &&
- (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal)
- ) {
- powerUps.onPickUp(powerUp[i]);
- powerUp[i].effect();
- Matter.Composite.remove(engine.world, powerUp[i]);
- powerUp.splice(i, 1);
- break; //because the array order is messed up after splice
- }
- }
- if (!(this.rewindCount % 30)) {
- if (tech.isRewindBot) {
- for (let i = 0; i < tech.isRewindBot; i++) {
- b.randomBot(m.pos, false, false)
- bullet[bullet.length - 1].endCycle = simulation.cycle + 480 + Math.floor(120 * Math.random()) //8-9 seconds
- }
- }
-
- if (tech.isRewindGrenade) {
- b.grenade(m.pos, this.rewindCount) //Math.PI / 2
- const who = bullet[bullet.length - 1]
- // Matter.Body.setVelocity(who, {
- // x: 0,
- // y: 0
- // });
- who.endCycle = simulation.cycle + 60
- // if (tech.isVacuumBomb) {
- // Matter.Body.setVelocity(who, {
- // x: who.velocity.x * 0.5,
- // y: who.velocity.y * 0.5
- // });
- // } else if (tech.isRPG) {
- // who.endCycle = simulation.cycle + 10
- // } else if (tech.isNeutronBomb) {
- // Matter.Body.setVelocity(who, {
- // x: who.velocity.x * 0.3,
- // y: who.velocity.y * 0.3
- // });
- // } else {
- // Matter.Body.setVelocity(who, {
- // x: who.velocity.x * 0.5,
- // y: who.velocity.y * 0.5
- // });
- // who.endCycle = simulation.cycle + 30
- // }
- }
-
-
- }
- }
- }
- } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
- m.pickUp();
- this.rewindCount = 0;
- } else {
- m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- this.rewindCount = 0;
- }
- m.drawFieldMeter()
-
-
-
-
- // // console.log(this.rewindCount)
- // if (input.field && m.fieldCDcycle < m.cycle) { //button has been held down
- // if (m.isHolding) {
- // m.drawHold(m.holdingTarget);
- // m.holding();
- // m.throwBlock();
- // } else {
- // m.grabPowerUp();
- // m.lookForPickUp();
- // if (!m.holdingTarget) {
- // this.rewindCount += 8;
- // const DRAIN = 0.001
- // let history = m.history[(m.cycle - this.rewindCount) % 600]
- // if (this.rewindCount > 599 || m.energy < DRAIN) {
- // this.rewindCount = 0;
- // m.resetHistory();
- // } else {
- // // m.grabPowerUp(); //a second grab power up to make the power ups easier to grab, and they more fast which matches the time theme
- // m.energy -= DRAIN
- // if (m.immuneCycle < m.cycle + 30) m.immuneCycle = m.cycle + 30; //player is immune to damage for 30 cycles
- // Matter.Body.setPosition(player, history.position);
- // Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
- // if (m.health < history.health) {
- // m.health = history.health
- // m.displayHealth();
- // }
- // m.yOff = history.yOff
- // if (m.yOff < 48) {
- // m.doCrouch()
- // } else {
- // m.undoCrouch()
- // }
- // //grab power ups
- // for (let i = 0, len = powerUp.length; i < len; ++i) {
- // if (
- // Vector.magnitudeSquared(Vector.sub(m.pos, powerUp[i].position)) < 100000 &&
- // !simulation.isChoosing &&
- // (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal)
- // ) {
- // powerUps.onPickUp(powerUp[i]);
- // powerUp[i].effect();
- // Matter.Composite.remove(engine.world, powerUp[i]);
- // powerUp.splice(i, 1);
- // break; //because the array order is messed up after splice
- // }
- // }
- // }
- // }
- // }
- // } else { //button is held the first time
- // this.rewindCount = 0;
- // if (m.holdingTarget && m.fieldCDcycle < m.cycle) {
- // m.pickUp();
- // } else {
- // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- // }
- // }
-
- }
- } else {
- m.fieldFire = true;
- m.isBodiesAsleep = false;
- m.drain = 0.0005
- m.hold = function() {
- if (m.isHolding) {
- m.wakeCheck();
- m.drawHold(m.holdingTarget);
- m.holding();
- m.throwBlock();
- } else if (input.field && m.fieldCDcycle < m.cycle) {
- m.grabPowerUp();
- m.lookForPickUp();
-
- m.drain += 0.0000025 //also increases inside tech.isTimeSkip
- if (m.energy > m.drain) {
- m.energy -= m.drain;
- if (m.energy < m.drain) {
- m.fieldCDcycle = m.cycle + 120;
- m.energy = 0;
- m.wakeCheck();
- }
+ if (!m.holdingTarget) {
+ this.rewindCount += 6;
+ const DRAIN = 0.001
+ let history = m.history[(m.cycle - this.rewindCount) % 600]
+ if (this.rewindCount > 599 || m.energy < DRAIN) {
+ this.rewindCount = 0;
+ m.resetHistory();
+ if (m.fireCDcycle < m.cycle + 60) m.fieldCDcycle = m.cycle + 60
+ m.immuneCycle = m.cycle //if you reach the end of the history disable harm immunity
+ } else {
//draw field everywhere
ctx.globalCompositeOperation = "saturation"
ctx.fillStyle = "#ccc";
ctx.fillRect(-100000, -100000, 200000, 200000)
ctx.globalCompositeOperation = "source-over"
- //stop time
- m.isBodiesAsleep = true;
-
- function sleep(who) {
- for (let i = 0, len = who.length; i < len; ++i) {
- if (!who[i].isSleeping) {
- who[i].storeVelocity = who[i].velocity
- who[i].storeAngularVelocity = who[i].angularVelocity
- }
- Matter.Sleeping.set(who[i], true)
- }
+ // m.grabPowerUp(); //a second grab power up to make the power ups easier to grab, and they more fast which matches the time theme
+ m.energy -= DRAIN
+ if (m.immuneCycle < m.cycle + 60) m.immuneCycle = m.cycle + 60; //player is immune to damage for __ cycles
+ Matter.Body.setPosition(player, history.position);
+ Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
+ if (m.health < history.health) {
+ m.health = history.health
+ if (m.health > m.maxHealth) m.health = m.maxHealth
+ m.displayHealth();
}
- sleep(mob);
- sleep(body);
- sleep(bullet);
-
- simulation.cycle--; //pause all functions that depend on game cycle increasing
- if (tech.isTimeSkip) {
- m.immuneCycle = 0;
- m.drain += 0.0000025
- m.regenEnergy(); //immunity disables normal regen, so turn off immunity for just this function
- m.immuneCycle = m.cycle + 10;
- simulation.isTimeSkipping = true;
- m.cycle++;
- simulation.gravity();
- if (tech.isFireMoveLock && input.fire) {
- player.force.x = 0
- player.force.y = 0
- }
- Engine.update(engine, simulation.delta);
- m.move();
- simulation.checks();
- m.walk_cycle += m.flipLegs * m.Vx;
- b.fire();
- b.bulletDo();
- simulation.isTimeSkipping = false;
+ m.yOff = history.yOff
+ if (m.yOff < 48) {
+ m.doCrouch()
+ } else {
+ m.undoCrouch()
}
- } else { //holding, but field button is released
- m.wakeCheck();
- }
- } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
- m.wakeCheck();
- m.pickUp();
- } else {
- if (m.drain > 0.0005) m.drain -= 0.000005 //return drain to base level
- m.wakeCheck();
- m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- }
- // console.log(m.drain.toFixed(6))
- m.drawFieldMeter()
- }
- }
- },
- effect() {
- // m.fieldMeterColor = "#000"
- this.set();
- }
- },
- {
- name: "metamaterial cloaking", //"weak photonic coupling" "electromagnetically induced transparency" "optical non-coupling" "slow light field" "electro-optic transparency"
- description: "when not firing activate a cloaking effect
+333% damage if a mob hasn't recently died
collisions do 50% less harm when cloaked",
- effect: () => {
- m.fieldFire = true;
- m.fieldMeterColor = "#333";
- m.eyeFillColor = m.fieldMeterColor
- // m.eyeFillColor = '#333'
- m.fieldPhase = 0;
- m.isCloak = false
- // m.fieldDamage = 2.46 // 1 + 146/100
- m.fieldDrawRadius = 0
- m.isSneakAttack = true;
- const drawRadius = 900
-
- m.hold = function() {
- // console.log(m.holdingTarget)
- if (m.isHolding) {
- m.drawHold(m.holdingTarget);
- m.holding();
- m.throwBlock();
- } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold and field button is pressed
- m.grabPowerUp();
- m.lookForPickUp();
- } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding target exists, and field button is not pressed
- m.pickUp();
- } else {
- m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- }
-
- //not shooting (or using field) enable cloak
- if (m.energy < 0.05 && m.fireCDcycle < m.cycle && !input.fire) m.fireCDcycle = m.cycle
- if (m.fireCDcycle + 30 < m.cycle && !input.fire) { //automatically cloak if not firing
- if (!m.isCloak) {
- m.isCloak = true //enter cloak
- if (tech.isIntangible) {
- for (let i = 0; i < bullet.length; i++) {
- if (bullet[i].botType && bullet[i].botType !== "orbit") bullet[i].collisionFilter.mask = cat.map | cat.bullet | cat.mobBullet | cat.mobShield
- }
- }
- }
- } else if (m.isCloak) { //exit cloak
- m.isCloak = false
- if (tech.isIntangible) {
- for (let i = 0; i < bullet.length; i++) {
- if (bullet[i].botType && bullet[i].botType !== "orbit") bullet[i].collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield
- }
- }
- if (tech.isCloakStun) { //stun nearby mobs after exiting cloak
- let isMobsAround = false
- const stunRange = m.fieldDrawRadius * 1.5
- const drain = 0.15
- const stunTime = 240
- if (m.energy > drain) {
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) < stunRange && Matter.Query.ray(map, mob[i].position, m.pos).length === 0 && !mob[i].isBadTarget) {
- isMobsAround = true
- mobs.statusStun(mob[i], stunTime)
- }
- }
- if (isMobsAround) {
- m.energy -= drain
- simulation.drawList.push({
- x: m.pos.x,
- y: m.pos.y,
- radius: stunRange,
- color: "hsla(0,50%,100%,0.7)",
- time: 7
- });
- }
- }
- }
- }
-
- function drawField() {
- m.fieldPhase += 0.007
- const wiggle = 0.15 * Math.sin(m.fieldPhase * 0.5)
- ctx.beginPath();
- ctx.ellipse(m.pos.x, m.pos.y, m.fieldDrawRadius * (1 - wiggle), m.fieldDrawRadius * (1 + wiggle), m.fieldPhase, 0, 2 * Math.PI);
- // if (m.fireCDcycle > m.cycle && (input.field)) {}
- ctx.fillStyle = "#fff"
- ctx.lineWidth = 2;
- ctx.strokeStyle = "#000"
- ctx.stroke()
- // ctx.fillStyle = "#fff" //`rgba(0,0,0,${0.5+0.5*m.energy})`;
- ctx.globalCompositeOperation = "destination-in";
- ctx.fill();
- ctx.globalCompositeOperation = "source-over";
- ctx.clip();
- }
-
- // const energy = Math.max(0.01, Math.min(m.energy, 1))
- if (m.isCloak) {
- this.fieldRange = this.fieldRange * 0.9 + 0.1 * drawRadius
- m.fieldDrawRadius = this.fieldRange * 0.88 //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy));
- drawField()
- } else if (this.fieldRange < 3000) {
- this.fieldRange += 50
- m.fieldDrawRadius = this.fieldRange //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy));
- drawField()
- }
- if (tech.isIntangible) {
- if (m.isCloak) {
- player.collisionFilter.mask = cat.map
- let inPlayer = Matter.Query.region(mob, player.bounds)
- if (inPlayer.length > 0) {
- for (let i = 0; i < inPlayer.length; i++) {
- if (m.energy > 0 && inPlayer[i].shield) m.energy -= 0.014;
- }
- }
- } else {
- player.collisionFilter.mask = cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield //normal collisions
- }
- }
-
- this.drawFieldMeterCloaking()
- //show sneak attack status
-
- if (m.cycle > m.lastKillCycle + 240) {
- ctx.strokeStyle = "rgba(0,0,0,0.4)" //m.fieldMeterColor; //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})`
- ctx.beginPath();
- ctx.arc(m.pos.x, m.pos.y, 28, 0, 2 * Math.PI);
- ctx.lineWidth = 2
- ctx.stroke();
- }
- }
- }
- },
- // {
- // name: "phase decoherence field",
- // description: "use energy to become intangible
firing and touching shields drains energy
unable to see and be seen by mobs",
- // effect: () => {
- // m.fieldFire = true;
- // m.fieldMeterColor = "#fff";
- // m.fieldPhase = 0;
-
- // m.hold = function () {
- // function drawField(radius) {
- // radius *= Math.min(4, 0.9 + 2.2 * m.energy * m.energy);
- // const rotate = m.cycle * 0.005;
- // m.fieldPhase += 0.5 - 0.5 * Math.sqrt(Math.max(0.01, Math.min(m.energy, 1)));
- // const off1 = 1 + 0.06 * Math.sin(m.fieldPhase);
- // const off2 = 1 - 0.06 * Math.sin(m.fieldPhase);
- // ctx.beginPath();
- // ctx.ellipse(m.pos.x, m.pos.y, radius * off1, radius * off2, rotate, 0, 2 * Math.PI);
- // if (m.fireCDcycle > m.cycle && (input.field)) {
- // ctx.lineWidth = 5;
- // ctx.strokeStyle = `rgba(0, 204, 255,1)`
- // ctx.stroke()
- // }
- // ctx.fillStyle = "#fff" //`rgba(0,0,0,${0.5+0.5*m.energy})`;
- // ctx.globalCompositeOperation = "destination-in"; //in or atop
- // ctx.fill();
- // ctx.globalCompositeOperation = "source-over";
- // ctx.clip();
- // }
-
- // m.isCloak = false //isCloak disables most uses of foundPlayer()
- // player.collisionFilter.mask = cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield //normal collisions
- // if (m.isHolding) {
- // if (this.fieldRange < 2000) {
- // this.fieldRange += 100
- // drawField(this.fieldRange)
- // }
- // m.drawHold(m.holdingTarget);
- // m.holding();
- // m.throwBlock();
- // } else if (input.field) {
- // m.grabPowerUp();
- // m.lookForPickUp();
-
- // if (m.fieldCDcycle < m.cycle) {
- // // simulation.draw.bodyFill = "transparent"
- // // simulation.draw.bodyStroke = "transparent"
-
- // const DRAIN = 0.00013 + (m.fireCDcycle > m.cycle ? 0.005 : 0)
- // if (m.energy > DRAIN) {
- // m.energy -= DRAIN;
- // // if (m.energy < 0.001) {
- // // m.fieldCDcycle = m.cycle + 120;
- // // m.energy = 0;
- // // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- // // }
- // this.fieldRange = this.fieldRange * 0.8 + 0.2 * 160
- // drawField(this.fieldRange)
-
- // m.isCloak = true //isCloak disables most uses of foundPlayer()
- // player.collisionFilter.mask = cat.map
-
-
- // let inPlayer = Matter.Query.region(mob, player.bounds)
- // if (inPlayer.length > 0) {
- // for (let i = 0; i < inPlayer.length; i++) {
- // if (inPlayer[i].shield) {
- // m.energy -= 0.005; //shields drain player energy
- // //draw outline of shield
- // ctx.fillStyle = `rgba(140,217,255,0.5)`
- // ctx.fill()
- // } else if (tech.superposition && inPlayer[i].isDropPowerUp) {
- // // inPlayer[i].damage(0.4 * b.dmgScale); //damage mobs inside the player
- // // m.energy += 0.005;
-
- // mobs.statusStun(inPlayer[i], 300)
- // //draw outline of mob in a few random locations to show blurriness
- // const vertices = inPlayer[i].vertices;
- // const off = 30
- // for (let k = 0; k < 3; k++) {
- // const xOff = off * (Math.random() - 0.5)
- // const yOff = off * (Math.random() - 0.5)
- // ctx.beginPath();
- // ctx.moveTo(xOff + vertices[0].x, yOff + vertices[0].y);
- // for (let j = 1, len = vertices.length; j < len; ++j) {
- // ctx.lineTo(xOff + vertices[j].x, yOff + vertices[j].y);
- // }
- // ctx.lineTo(xOff + vertices[0].x, yOff + vertices[0].y);
- // ctx.fillStyle = "rgba(0,0,0,0.1)"
- // ctx.fill()
- // }
- // break;
- // }
- // }
- // }
- // } else {
- // m.fieldCDcycle = m.cycle + 120;
- // m.energy = 0;
- // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- // drawField(this.fieldRange)
- // }
- // }
- // } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
- // m.pickUp();
- // if (this.fieldRange < 2000) {
- // this.fieldRange += 100
- // drawField(this.fieldRange)
- // }
- // } else {
- // // this.fieldRange = 3000
- // if (this.fieldRange < 2000 && m.holdingTarget === null) {
- // this.fieldRange += 100
- // drawField(this.fieldRange)
- // }
- // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- // }
-
- // if (m.energy < m.maxEnergy) {
- // m.energy += m.fieldRegen;
- // const xOff = m.pos.x - m.radius * m.maxEnergy
- // const yOff = m.pos.y - 50
- // ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
- // ctx.fillRect(xOff, yOff, 60 * m.maxEnergy, 10);
- // ctx.fillStyle = m.fieldMeterColor;
- // ctx.fillRect(xOff, yOff, 60 * m.energy, 10);
- // ctx.beginPath()
- // ctx.rect(xOff, yOff, 60 * m.maxEnergy, 10);
- // ctx.strokeStyle = "rgb(0, 0, 0)";
- // ctx.lineWidth = 1;
- // ctx.stroke();
- // }
- // if (m.energy < 0) m.energy = 0
- // }
- // }
- // },
- {
- name: "pilot wave",
- description: "use energy to push blocks with your mouse
blocks can't collide with intangible mobs
field radius decreases out of line of sight",
- effect: () => {
- m.fieldPhase = 0;
- m.fieldPosition = {
- x: simulation.mouseInGame.x,
- y: simulation.mouseInGame.y
- }
- m.lastFieldPosition = {
- x: simulation.mouseInGame.x,
- y: simulation.mouseInGame.y
- }
- m.fieldOn = false;
- m.fieldRadius = 0;
- m.drop();
- m.hold = function() {
- if (input.field) {
- if (m.fieldCDcycle < m.cycle) {
- const scale = 25
- const bounds = {
- min: {
- x: m.fieldPosition.x - scale,
- y: m.fieldPosition.y - scale
- },
- max: {
- x: m.fieldPosition.x + scale,
- y: m.fieldPosition.y + scale
- }
- }
- const isInMap = Matter.Query.region(map, bounds).length
- // const isInMap = Matter.Query.point(map, m.fieldPosition).length
-
- if (!m.fieldOn) { // if field was off, and it starting up, teleport to new mouse location
- m.fieldOn = true;
- // m.fieldPosition = { //smooth the mouse position, set to starting at player
- // x: m.pos.x,
- // y: m.pos.y
- // }
- m.fieldPosition = { //smooth the mouse position, set to mouse's current location
- x: simulation.mouseInGame.x,
- y: simulation.mouseInGame.y
- }
- m.lastFieldPosition = { //used to find velocity of field changes
- x: m.fieldPosition.x,
- y: m.fieldPosition.y
- }
- } else { //when field is on it smoothly moves towards the mouse
- m.lastFieldPosition = { //used to find velocity of field changes
- x: m.fieldPosition.x,
- y: m.fieldPosition.y
- }
- const smooth = isInMap ? 0.985 : 0.96;
- m.fieldPosition = { //smooth the mouse position
- x: m.fieldPosition.x * smooth + simulation.mouseInGame.x * (1 - smooth),
- y: m.fieldPosition.y * smooth + simulation.mouseInGame.y * (1 - smooth),
- }
- }
-
- //grab power ups into the field
- for (let i = 0, len = powerUp.length; i < len; ++i) {
- const dxP = m.fieldPosition.x - powerUp[i].position.x;
- const dyP = m.fieldPosition.y - powerUp[i].position.y;
- const dist2 = dxP * dxP + dyP * dyP + 200;
- // float towards field if looking at and in range or if very close to player
- if (
- dist2 < m.fieldRadius * m.fieldRadius &&
- (m.lookingAt(powerUp[i]) || dist2 < 16000)
- ) {
- powerUp[i].force.x += 0.05 * (dxP / Math.sqrt(dist2)) * powerUp[i].mass;
- powerUp[i].force.y += 0.05 * (dyP / Math.sqrt(dist2)) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity
- //extra friction
- Matter.Body.setVelocity(powerUp[i], {
- x: powerUp[i].velocity.x * 0.11,
- y: powerUp[i].velocity.y * 0.11
- });
+ //grab power ups
+ for (let i = 0, len = powerUp.length; i < len; ++i) {
if (
- dist2 < 5000 &&
+ Vector.magnitudeSquared(Vector.sub(m.pos, powerUp[i].position)) < 100000 &&
!simulation.isChoosing &&
(powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal)
- // (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth)
- // (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity)
- ) { //use power up if it is close enough
+ ) {
powerUps.onPickUp(powerUp[i]);
powerUp[i].effect();
Matter.Composite.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1);
- // m.fieldRadius += 50
break; //because the array order is messed up after splice
}
}
- }
- //grab power ups normally too
- m.grabPowerUp();
-
- if (m.energy > 0.01) {
- //find mouse velocity
- const diff = Vector.sub(m.fieldPosition, m.lastFieldPosition)
- const speed = Vector.magnitude(diff)
- const velocity = Vector.mult(Vector.normalise(diff), Math.min(speed, 60)) //limit velocity
- let radius, radiusSmooth
- if (Matter.Query.ray(map, m.fieldPosition, player.position).length) { //is there something block the player's view of the field
- radius = 0
- radiusSmooth = Math.max(0, isInMap ? 0.96 - 0.02 * speed : 0.995); //0.99
- } else {
- radius = Math.max(50, 250 - 2 * speed)
- radiusSmooth = 0.97
- }
- m.fieldRadius = m.fieldRadius * radiusSmooth + radius * (1 - radiusSmooth)
-
- for (let i = 0, len = body.length; i < len; ++i) {
- if (Vector.magnitude(Vector.sub(body[i].position, m.fieldPosition)) < m.fieldRadius && !body[i].isNotHoldable) {
- const DRAIN = speed * body[i].mass * 0.000006 // * (1 + m.energy * m.energy) //drain more energy when you have more energy
- if (m.energy > DRAIN) {
- m.energy -= DRAIN;
- Matter.Body.setVelocity(body[i], velocity); //give block mouse velocity
- Matter.Body.setAngularVelocity(body[i], body[i].angularVelocity * 0.8)
- // body[i].force.y -= body[i].mass * simulation.g; //remove gravity effects
- //blocks drift towards center of pilot wave
- const sub = Vector.sub(m.fieldPosition, body[i].position)
- const push = Vector.mult(Vector.normalise(sub), 0.0001 * body[i].mass * Vector.magnitude(sub))
- body[i].force.x += push.x
- body[i].force.y += push.y - body[i].mass * simulation.g //remove gravity effects
- // if (body[i].collisionFilter.category !== cat.bullet) {
- // body[i].collisionFilter.category = cat.bullet;
- // }
- } else {
- m.fieldCDcycle = m.cycle + 120;
- m.fieldOn = false
- m.fieldRadius = 0
- break
+ if (!(this.rewindCount % 30)) {
+ if (tech.isRewindBot) {
+ for (let i = 0; i < tech.isRewindBot; i++) {
+ b.randomBot(m.pos, false, false)
+ bullet[bullet.length - 1].endCycle = simulation.cycle + 480 + Math.floor(120 * Math.random()) //8-9 seconds
}
}
- }
-
- // m.holdingTarget.collisionFilter.category = cat.bullet;
- // m.holdingTarget.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield;
- // //check every second to see if player is away from thrown body, and make solid
- // const solid = function(that) {
- // const dx = that.position.x - player.position.x;
- // const dy = that.position.y - player.position.y;
- // if (that.speed < 3 && dx * dx + dy * dy > 10000 && that !== m.holdingTarget) {
- // that.collisionFilter.category = cat.body; //make solid
- // that.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet; //can hit player now
- // } else {
- // setTimeout(solid, 40, that);
- // }
- // };
- // setTimeout(solid, 200, m.holdingTarget);
-
-
-
- if (tech.isFreezeMobs) {
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (Vector.magnitude(Vector.sub(mob[i].position, m.fieldPosition)) < m.fieldRadius) {
- mobs.statusSlow(mob[i], 180)
- }
+ if (tech.isRewindGrenade) {
+ b.grenade(m.pos, this.rewindCount) //Math.PI / 2
+ const who = bullet[bullet.length - 1]
+ // Matter.Body.setVelocity(who, {
+ // x: 0,
+ // y: 0
+ // });
+ who.endCycle = simulation.cycle + 60
+ // if (tech.isVacuumBomb) {
+ // Matter.Body.setVelocity(who, {
+ // x: who.velocity.x * 0.5,
+ // y: who.velocity.y * 0.5
+ // });
+ // } else if (tech.isRPG) {
+ // who.endCycle = simulation.cycle + 10
+ // } else if (tech.isNeutronBomb) {
+ // Matter.Body.setVelocity(who, {
+ // x: who.velocity.x * 0.3,
+ // y: who.velocity.y * 0.3
+ // });
+ // } else {
+ // Matter.Body.setVelocity(who, {
+ // x: who.velocity.x * 0.5,
+ // y: who.velocity.y * 0.5
+ // });
+ // who.endCycle = simulation.cycle + 30
+ // }
}
- }
- ctx.beginPath();
- const rotate = m.cycle * 0.008;
- m.fieldPhase += 0.2 // - 0.5 * Math.sqrt(Math.min(m.energy, 1));
- const off1 = 1 + 0.06 * Math.sin(m.fieldPhase);
- const off2 = 1 - 0.06 * Math.sin(m.fieldPhase);
- ctx.beginPath();
- ctx.ellipse(m.fieldPosition.x, m.fieldPosition.y, 1.2 * m.fieldRadius * off1, 1.2 * m.fieldRadius * off2, rotate, 0, 2 * Math.PI);
- ctx.globalCompositeOperation = "exclusion"; //"exclusion" "difference";
- ctx.fillStyle = "#fff"; //"#eef";
- ctx.fill();
- ctx.globalCompositeOperation = "source-over";
- ctx.beginPath();
- ctx.ellipse(m.fieldPosition.x, m.fieldPosition.y, 1.2 * m.fieldRadius * off1, 1.2 * m.fieldRadius * off2, rotate, 0, 2 * Math.PI * m.energy / m.maxEnergy);
- ctx.strokeStyle = "#000";
- ctx.lineWidth = 4;
- ctx.stroke();
- } else {
- m.fieldCDcycle = m.cycle + 120;
- m.fieldOn = false
- m.fieldRadius = 0
+
+ }
}
- } else {
- m.grabPowerUp();
}
+ } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
+ m.pickUp();
+ this.rewindCount = 0;
} else {
- m.fieldOn = false
- m.fieldRadius = 0
+ m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ this.rewindCount = 0;
}
m.drawFieldMeter()
+
+
+
+
+ // // console.log(this.rewindCount)
+ // if (input.field && m.fieldCDcycle < m.cycle) { //button has been held down
+ // if (m.isHolding) {
+ // m.drawHold(m.holdingTarget);
+ // m.holding();
+ // m.throwBlock();
+ // } else {
+ // m.grabPowerUp();
+ // m.lookForPickUp();
+ // if (!m.holdingTarget) {
+ // this.rewindCount += 8;
+ // const DRAIN = 0.001
+ // let history = m.history[(m.cycle - this.rewindCount) % 600]
+ // if (this.rewindCount > 599 || m.energy < DRAIN) {
+ // this.rewindCount = 0;
+ // m.resetHistory();
+ // } else {
+ // // m.grabPowerUp(); //a second grab power up to make the power ups easier to grab, and they more fast which matches the time theme
+ // m.energy -= DRAIN
+ // if (m.immuneCycle < m.cycle + 30) m.immuneCycle = m.cycle + 30; //player is immune to damage for 30 cycles
+ // Matter.Body.setPosition(player, history.position);
+ // Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
+ // if (m.health < history.health) {
+ // m.health = history.health
+ // m.displayHealth();
+ // }
+ // m.yOff = history.yOff
+ // if (m.yOff < 48) {
+ // m.doCrouch()
+ // } else {
+ // m.undoCrouch()
+ // }
+ // //grab power ups
+ // for (let i = 0, len = powerUp.length; i < len; ++i) {
+ // if (
+ // Vector.magnitudeSquared(Vector.sub(m.pos, powerUp[i].position)) < 100000 &&
+ // !simulation.isChoosing &&
+ // (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal)
+ // ) {
+ // powerUps.onPickUp(powerUp[i]);
+ // powerUp[i].effect();
+ // Matter.Composite.remove(engine.world, powerUp[i]);
+ // powerUp.splice(i, 1);
+ // break; //because the array order is messed up after splice
+ // }
+ // }
+ // }
+ // }
+ // }
+ // } else { //button is held the first time
+ // this.rewindCount = 0;
+ // if (m.holdingTarget && m.fieldCDcycle < m.cycle) {
+ // m.pickUp();
+ // } else {
+ // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ // }
+ // }
+
+ }
+ } else {
+ m.fieldFire = true;
+ m.isBodiesAsleep = false;
+ m.drain = 0.0005
+ m.hold = function () {
+ if (m.isHolding) {
+ m.wakeCheck();
+ m.drawHold(m.holdingTarget);
+ m.holding();
+ m.throwBlock();
+ } else if (input.field && m.fieldCDcycle < m.cycle) {
+ m.grabPowerUp();
+ m.lookForPickUp();
+
+ m.drain += 0.0000025 //also increases inside tech.isTimeSkip
+ if (m.energy > m.drain) {
+ m.energy -= m.drain;
+ if (m.energy < m.drain) {
+ m.fieldCDcycle = m.cycle + 120;
+ m.energy = 0;
+ m.wakeCheck();
+ }
+ //draw field everywhere
+ ctx.globalCompositeOperation = "saturation"
+ ctx.fillStyle = "#ccc";
+ ctx.fillRect(-100000, -100000, 200000, 200000)
+ ctx.globalCompositeOperation = "source-over"
+ //stop time
+ m.isBodiesAsleep = true;
+
+ function sleep(who) {
+ for (let i = 0, len = who.length; i < len; ++i) {
+ if (!who[i].isSleeping) {
+ who[i].storeVelocity = who[i].velocity
+ who[i].storeAngularVelocity = who[i].angularVelocity
+ }
+ Matter.Sleeping.set(who[i], true)
+ }
+ }
+ sleep(mob);
+ sleep(body);
+ sleep(bullet);
+
+ simulation.cycle--; //pause all functions that depend on game cycle increasing
+ if (tech.isTimeSkip) {
+ m.immuneCycle = 0;
+ m.drain += 0.0000025
+ m.regenEnergy(); //immunity disables normal regen, so turn off immunity for just this function
+ m.immuneCycle = m.cycle + 10;
+ simulation.isTimeSkipping = true;
+ m.cycle++;
+ simulation.gravity();
+ if (tech.isFireMoveLock && input.fire) {
+ player.force.x = 0
+ player.force.y = 0
+ }
+ Engine.update(engine, simulation.delta);
+ m.move();
+ simulation.checks();
+ m.walk_cycle += m.flipLegs * m.Vx;
+ b.fire();
+ b.bulletDo();
+ simulation.isTimeSkipping = false;
+ }
+ } else { //holding, but field button is released
+ m.wakeCheck();
+ }
+ } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
+ m.wakeCheck();
+ m.pickUp();
+ } else {
+ if (m.drain > 0.0005) m.drain -= 0.000005 //return drain to base level
+ m.wakeCheck();
+ m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ }
+ // console.log(m.drain.toFixed(6))
+ m.drawFieldMeter()
}
}
},
- {
- name: "wormhole",
- description: "use energy to tunnel through a wormhole
wormholes attract blocks and power ups
7% chance to duplicate spawned power ups", //
bullets may also traverse wormholes
- effect: function() {
- m.duplicateChance = 0.07
- m.fieldRange = 0
- powerUps.setDupChance(); //needed after adjusting duplication chance
+ effect() {
+ // m.fieldMeterColor = "#000"
+ this.set();
+ }
+ },
+ {
+ name: "metamaterial cloaking", //"weak photonic coupling" "electromagnetically induced transparency" "optical non-coupling" "slow light field" "electro-optic transparency"
+ description: "when not firing activate a cloaking effect
+333% damage if a mob hasn't recently died
collisions do 50% less harm when cloaked",
+ effect: () => {
+ m.fieldFire = true;
+ m.fieldMeterColor = "#333";
+ m.eyeFillColor = m.fieldMeterColor
+ // m.eyeFillColor = '#333'
+ m.fieldPhase = 0;
+ m.isCloak = false
+ // m.fieldDamage = 2.46 // 1 + 146/100
+ m.fieldDrawRadius = 0
+ m.isSneakAttack = true;
+ const drawRadius = 900
- m.hold = function() {
- // m.hole = { //this is reset with each new field, but I'm leaving it here for reference
- // isOn: false,
- // isReady: true,
- // pos1: {x: 0,y: 0},
- // pos2: {x: 0,y: 0},
- // angle: 0,
- // unit:{x:0,y:0},
- // }
- if (m.hole.isOn) {
- // draw holes
- m.fieldRange = 0.97 * m.fieldRange + 0.03 * (50 + 10 * Math.sin(simulation.cycle * 0.025))
- const semiMajorAxis = m.fieldRange + 30
- const edge1a = Vector.add(Vector.mult(m.hole.unit, semiMajorAxis), m.hole.pos1)
- const edge1b = Vector.add(Vector.mult(m.hole.unit, -semiMajorAxis), m.hole.pos1)
- const edge2a = Vector.add(Vector.mult(m.hole.unit, semiMajorAxis), m.hole.pos2)
- const edge2b = Vector.add(Vector.mult(m.hole.unit, -semiMajorAxis), m.hole.pos2)
- ctx.beginPath();
- ctx.moveTo(edge1a.x, edge1a.y)
- ctx.bezierCurveTo(m.hole.pos1.x, m.hole.pos1.y, m.hole.pos2.x, m.hole.pos2.y, edge2a.x, edge2a.y);
- ctx.lineTo(edge2b.x, edge2b.y)
- ctx.bezierCurveTo(m.hole.pos2.x, m.hole.pos2.y, m.hole.pos1.x, m.hole.pos1.y, edge1b.x, edge1b.y);
- ctx.fillStyle = `rgba(255,255,255,${200 / m.fieldRange / m.fieldRange})` //"rgba(0,0,0,0.1)"
- ctx.fill();
- ctx.beginPath();
- ctx.ellipse(m.hole.pos1.x, m.hole.pos1.y, m.fieldRange, semiMajorAxis, m.hole.angle, 0, 2 * Math.PI)
- ctx.ellipse(m.hole.pos2.x, m.hole.pos2.y, m.fieldRange, semiMajorAxis, m.hole.angle, 0, 2 * Math.PI)
- ctx.fillStyle = `rgba(255,255,255,${32 / m.fieldRange})`
- ctx.fill();
+ m.hold = function () {
+ // console.log(m.holdingTarget)
+ if (m.isHolding) {
+ m.drawHold(m.holdingTarget);
+ m.holding();
+ m.throwBlock();
+ } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold and field button is pressed
+ m.grabPowerUp();
+ m.lookForPickUp();
+ } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding target exists, and field button is not pressed
+ m.pickUp();
+ } else {
+ m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ }
- //suck power ups
- for (let i = 0, len = powerUp.length; i < len; ++i) {
- //which hole is closer
- const dxP1 = m.hole.pos1.x - powerUp[i].position.x;
- const dyP1 = m.hole.pos1.y - powerUp[i].position.y;
- const dxP2 = m.hole.pos2.x - powerUp[i].position.x;
- const dyP2 = m.hole.pos2.y - powerUp[i].position.y;
- let dxP, dyP, dist2
- if (dxP1 * dxP1 + dyP1 * dyP1 < dxP2 * dxP2 + dyP2 * dyP2) {
- dxP = dxP1
- dyP = dyP1
- } else {
- dxP = dxP2
- dyP = dyP2
+ //not shooting (or using field) enable cloak
+ if (m.energy < 0.05 && m.fireCDcycle < m.cycle && !input.fire) m.fireCDcycle = m.cycle
+ if (m.fireCDcycle + 30 < m.cycle && !input.fire) { //automatically cloak if not firing
+ if (!m.isCloak) {
+ m.isCloak = true //enter cloak
+ if (tech.isIntangible) {
+ for (let i = 0; i < bullet.length; i++) {
+ if (bullet[i].botType && bullet[i].botType !== "orbit") bullet[i].collisionFilter.mask = cat.map | cat.bullet | cat.mobBullet | cat.mobShield
}
- dist2 = dxP * dxP + dyP * dyP;
- if (dist2 < 600000) { //&& !(m.health === m.maxHealth && powerUp[i].name === "heal")
- powerUp[i].force.x += 4 * (dxP / dist2) * powerUp[i].mass; // float towards hole
- powerUp[i].force.y += 4 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity
- Matter.Body.setVelocity(powerUp[i], { //extra friction
- x: powerUp[i].velocity.x * 0.05,
- y: powerUp[i].velocity.y * 0.05
+ }
+ }
+ } else if (m.isCloak) { //exit cloak
+ m.isCloak = false
+ if (tech.isIntangible) {
+ for (let i = 0; i < bullet.length; i++) {
+ if (bullet[i].botType && bullet[i].botType !== "orbit") bullet[i].collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield
+ }
+ }
+ if (tech.isCloakStun) { //stun nearby mobs after exiting cloak
+ let isMobsAround = false
+ const stunRange = m.fieldDrawRadius * 1.5
+ const drain = 0.15
+ const stunTime = 240
+ if (m.energy > drain) {
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) < stunRange && Matter.Query.ray(map, mob[i].position, m.pos).length === 0 && !mob[i].isBadTarget) {
+ isMobsAround = true
+ mobs.statusStun(mob[i], stunTime)
+ }
+ }
+ if (isMobsAround) {
+ m.energy -= drain
+ simulation.drawList.push({
+ x: m.pos.x,
+ y: m.pos.y,
+ radius: stunRange,
+ color: "hsla(0,50%,100%,0.7)",
+ time: 7
});
- if (dist2 < 1000 && !simulation.isChoosing) { //use power up if it is close enough
+ }
+ }
+ }
+ }
- // if (true) { //AoE radiation effect
- // const range = 800
+ function drawField() {
+ m.fieldPhase += 0.007
+ const wiggle = 0.15 * Math.sin(m.fieldPhase * 0.5)
+ ctx.beginPath();
+ ctx.ellipse(m.pos.x, m.pos.y, m.fieldDrawRadius * (1 - wiggle), m.fieldDrawRadius * (1 + wiggle), m.fieldPhase, 0, 2 * Math.PI);
+ // if (m.fireCDcycle > m.cycle && (input.field)) {}
+ ctx.fillStyle = "#fff"
+ ctx.lineWidth = 2;
+ ctx.strokeStyle = "#000"
+ ctx.stroke()
+ // ctx.fillStyle = "#fff" //`rgba(0,0,0,${0.5+0.5*m.energy})`;
+ ctx.globalCompositeOperation = "destination-in";
+ ctx.fill();
+ ctx.globalCompositeOperation = "source-over";
+ ctx.clip();
+ }
- // for (let i = 0, len = mob.length; i < len; ++i) {
- // if (mob[i].alive && !mob[i].isShielded) {
- // dist = Vector.magnitude(Vector.sub(powerUp[i].position, mob[i].position)) - mob[i].radius;
- // if (dist < range) mobs.statusDoT(mob[i], 0.5) //apply radiation damage status effect on direct hits
- // }
- // }
+ // const energy = Math.max(0.01, Math.min(m.energy, 1))
+ if (m.isCloak) {
+ this.fieldRange = this.fieldRange * 0.9 + 0.1 * drawRadius
+ m.fieldDrawRadius = this.fieldRange * 0.88 //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy));
+ drawField()
+ } else if (this.fieldRange < 3000) {
+ this.fieldRange += 50
+ m.fieldDrawRadius = this.fieldRange //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy));
+ drawField()
+ }
+ if (tech.isIntangible) {
+ if (m.isCloak) {
+ player.collisionFilter.mask = cat.map
+ let inPlayer = Matter.Query.region(mob, player.bounds)
+ if (inPlayer.length > 0) {
+ for (let i = 0; i < inPlayer.length; i++) {
+ if (m.energy > 0 && inPlayer[i].shield) m.energy -= 0.014;
+ }
+ }
+ } else {
+ player.collisionFilter.mask = cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield //normal collisions
+ }
+ }
- // simulation.drawList.push({
- // x: powerUp[i].position.x,
- // y: powerUp[i].position.y,
- // radius: range,
- // color: "rgba(0,150,200,0.3)",
- // time: 4
- // });
- // }
+ this.drawFieldMeterCloaking()
+ //show sneak attack status
- m.fieldRange *= 0.8
+ if (m.cycle > m.lastKillCycle + 240) {
+ ctx.strokeStyle = "rgba(0,0,0,0.4)" //m.fieldMeterColor; //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})`
+ ctx.beginPath();
+ ctx.arc(m.pos.x, m.pos.y, 28, 0, 2 * Math.PI);
+ ctx.lineWidth = 2
+ ctx.stroke();
+ }
+ }
+ }
+ },
+ // {
+ // name: "phase decoherence field",
+ // description: "use energy to become intangible
firing and touching shields drains energy
unable to see and be seen by mobs",
+ // effect: () => {
+ // m.fieldFire = true;
+ // m.fieldMeterColor = "#fff";
+ // m.fieldPhase = 0;
+
+ // m.hold = function () {
+ // function drawField(radius) {
+ // radius *= Math.min(4, 0.9 + 2.2 * m.energy * m.energy);
+ // const rotate = m.cycle * 0.005;
+ // m.fieldPhase += 0.5 - 0.5 * Math.sqrt(Math.max(0.01, Math.min(m.energy, 1)));
+ // const off1 = 1 + 0.06 * Math.sin(m.fieldPhase);
+ // const off2 = 1 - 0.06 * Math.sin(m.fieldPhase);
+ // ctx.beginPath();
+ // ctx.ellipse(m.pos.x, m.pos.y, radius * off1, radius * off2, rotate, 0, 2 * Math.PI);
+ // if (m.fireCDcycle > m.cycle && (input.field)) {
+ // ctx.lineWidth = 5;
+ // ctx.strokeStyle = `rgba(0, 204, 255,1)`
+ // ctx.stroke()
+ // }
+ // ctx.fillStyle = "#fff" //`rgba(0,0,0,${0.5+0.5*m.energy})`;
+ // ctx.globalCompositeOperation = "destination-in"; //in or atop
+ // ctx.fill();
+ // ctx.globalCompositeOperation = "source-over";
+ // ctx.clip();
+ // }
+
+ // m.isCloak = false //isCloak disables most uses of foundPlayer()
+ // player.collisionFilter.mask = cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield //normal collisions
+ // if (m.isHolding) {
+ // if (this.fieldRange < 2000) {
+ // this.fieldRange += 100
+ // drawField(this.fieldRange)
+ // }
+ // m.drawHold(m.holdingTarget);
+ // m.holding();
+ // m.throwBlock();
+ // } else if (input.field) {
+ // m.grabPowerUp();
+ // m.lookForPickUp();
+
+ // if (m.fieldCDcycle < m.cycle) {
+ // // simulation.draw.bodyFill = "transparent"
+ // // simulation.draw.bodyStroke = "transparent"
+
+ // const DRAIN = 0.00013 + (m.fireCDcycle > m.cycle ? 0.005 : 0)
+ // if (m.energy > DRAIN) {
+ // m.energy -= DRAIN;
+ // // if (m.energy < 0.001) {
+ // // m.fieldCDcycle = m.cycle + 120;
+ // // m.energy = 0;
+ // // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ // // }
+ // this.fieldRange = this.fieldRange * 0.8 + 0.2 * 160
+ // drawField(this.fieldRange)
+
+ // m.isCloak = true //isCloak disables most uses of foundPlayer()
+ // player.collisionFilter.mask = cat.map
+
+
+ // let inPlayer = Matter.Query.region(mob, player.bounds)
+ // if (inPlayer.length > 0) {
+ // for (let i = 0; i < inPlayer.length; i++) {
+ // if (inPlayer[i].shield) {
+ // m.energy -= 0.005; //shields drain player energy
+ // //draw outline of shield
+ // ctx.fillStyle = `rgba(140,217,255,0.5)`
+ // ctx.fill()
+ // } else if (tech.superposition && inPlayer[i].isDropPowerUp) {
+ // // inPlayer[i].damage(0.4 * b.dmgScale); //damage mobs inside the player
+ // // m.energy += 0.005;
+
+ // mobs.statusStun(inPlayer[i], 300)
+ // //draw outline of mob in a few random locations to show blurriness
+ // const vertices = inPlayer[i].vertices;
+ // const off = 30
+ // for (let k = 0; k < 3; k++) {
+ // const xOff = off * (Math.random() - 0.5)
+ // const yOff = off * (Math.random() - 0.5)
+ // ctx.beginPath();
+ // ctx.moveTo(xOff + vertices[0].x, yOff + vertices[0].y);
+ // for (let j = 1, len = vertices.length; j < len; ++j) {
+ // ctx.lineTo(xOff + vertices[j].x, yOff + vertices[j].y);
+ // }
+ // ctx.lineTo(xOff + vertices[0].x, yOff + vertices[0].y);
+ // ctx.fillStyle = "rgba(0,0,0,0.1)"
+ // ctx.fill()
+ // }
+ // break;
+ // }
+ // }
+ // }
+ // } else {
+ // m.fieldCDcycle = m.cycle + 120;
+ // m.energy = 0;
+ // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ // drawField(this.fieldRange)
+ // }
+ // }
+ // } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
+ // m.pickUp();
+ // if (this.fieldRange < 2000) {
+ // this.fieldRange += 100
+ // drawField(this.fieldRange)
+ // }
+ // } else {
+ // // this.fieldRange = 3000
+ // if (this.fieldRange < 2000 && m.holdingTarget === null) {
+ // this.fieldRange += 100
+ // drawField(this.fieldRange)
+ // }
+ // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ // }
+
+ // if (m.energy < m.maxEnergy) {
+ // m.energy += m.fieldRegen;
+ // const xOff = m.pos.x - m.radius * m.maxEnergy
+ // const yOff = m.pos.y - 50
+ // ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
+ // ctx.fillRect(xOff, yOff, 60 * m.maxEnergy, 10);
+ // ctx.fillStyle = m.fieldMeterColor;
+ // ctx.fillRect(xOff, yOff, 60 * m.energy, 10);
+ // ctx.beginPath()
+ // ctx.rect(xOff, yOff, 60 * m.maxEnergy, 10);
+ // ctx.strokeStyle = "rgb(0, 0, 0)";
+ // ctx.lineWidth = 1;
+ // ctx.stroke();
+ // }
+ // if (m.energy < 0) m.energy = 0
+ // }
+ // }
+ // },
+ {
+ name: "pilot wave",
+ description: "use energy to push blocks with your mouse
blocks can't collide with intangible mobs
field radius decreases out of line of sight",
+ effect: () => {
+ m.fieldPhase = 0;
+ m.fieldPosition = {
+ x: simulation.mouseInGame.x,
+ y: simulation.mouseInGame.y
+ }
+ m.lastFieldPosition = {
+ x: simulation.mouseInGame.x,
+ y: simulation.mouseInGame.y
+ }
+ m.fieldOn = false;
+ m.fieldRadius = 0;
+ m.drop();
+ m.hold = function () {
+ if (input.field) {
+ if (m.fieldCDcycle < m.cycle) {
+ const scale = 25
+ const bounds = {
+ min: {
+ x: m.fieldPosition.x - scale,
+ y: m.fieldPosition.y - scale
+ },
+ max: {
+ x: m.fieldPosition.x + scale,
+ y: m.fieldPosition.y + scale
+ }
+ }
+ const isInMap = Matter.Query.region(map, bounds).length
+ // const isInMap = Matter.Query.point(map, m.fieldPosition).length
+
+ if (!m.fieldOn) { // if field was off, and it starting up, teleport to new mouse location
+ m.fieldOn = true;
+ // m.fieldPosition = { //smooth the mouse position, set to starting at player
+ // x: m.pos.x,
+ // y: m.pos.y
+ // }
+ m.fieldPosition = { //smooth the mouse position, set to mouse's current location
+ x: simulation.mouseInGame.x,
+ y: simulation.mouseInGame.y
+ }
+ m.lastFieldPosition = { //used to find velocity of field changes
+ x: m.fieldPosition.x,
+ y: m.fieldPosition.y
+ }
+ } else { //when field is on it smoothly moves towards the mouse
+ m.lastFieldPosition = { //used to find velocity of field changes
+ x: m.fieldPosition.x,
+ y: m.fieldPosition.y
+ }
+ const smooth = isInMap ? 0.985 : 0.96;
+ m.fieldPosition = { //smooth the mouse position
+ x: m.fieldPosition.x * smooth + simulation.mouseInGame.x * (1 - smooth),
+ y: m.fieldPosition.y * smooth + simulation.mouseInGame.y * (1 - smooth),
+ }
+ }
+
+ //grab power ups into the field
+ for (let i = 0, len = powerUp.length; i < len; ++i) {
+ const dxP = m.fieldPosition.x - powerUp[i].position.x;
+ const dyP = m.fieldPosition.y - powerUp[i].position.y;
+ const dist2 = dxP * dxP + dyP * dyP + 200;
+ // float towards field if looking at and in range or if very close to player
+ if (
+ dist2 < m.fieldRadius * m.fieldRadius &&
+ (m.lookingAt(powerUp[i]) || dist2 < 16000)
+ ) {
+ powerUp[i].force.x += 0.05 * (dxP / Math.sqrt(dist2)) * powerUp[i].mass;
+ powerUp[i].force.y += 0.05 * (dyP / Math.sqrt(dist2)) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity
+ //extra friction
+ Matter.Body.setVelocity(powerUp[i], {
+ x: powerUp[i].velocity.x * 0.11,
+ y: powerUp[i].velocity.y * 0.11
+ });
+ if (
+ dist2 < 5000 &&
+ !simulation.isChoosing &&
+ (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal)
+ // (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth)
+ // (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity)
+ ) { //use power up if it is close enough
powerUps.onPickUp(powerUp[i]);
powerUp[i].effect();
Matter.Composite.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1);
+ // m.fieldRadius += 50
break; //because the array order is messed up after splice
}
}
}
- //suck and shrink blocks
- const suckRange = 500
- const shrinkRange = 100
- const shrinkScale = 0.97;
- const slowScale = 0.9
- for (let i = 0, len = body.length; i < len; i++) {
- if (!body[i].isNotHoldable) {
- const dist1 = Vector.magnitude(Vector.sub(m.hole.pos1, body[i].position))
- const dist2 = Vector.magnitude(Vector.sub(m.hole.pos2, body[i].position))
- if (dist1 < dist2) {
- if (dist1 < suckRange) {
- const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos1, body[i].position)), 1)
- const slow = Vector.mult(body[i].velocity, slowScale)
- Matter.Body.setVelocity(body[i], Vector.add(slow, pull));
- //shrink
- if (Vector.magnitude(Vector.sub(m.hole.pos1, body[i].position)) < shrinkRange) {
- Matter.Body.scale(body[i], shrinkScale, shrinkScale);
- if (body[i].mass < 0.05) {
- Matter.Composite.remove(engine.world, body[i]);
- body.splice(i, 1);
- m.fieldRange *= 0.8
- if (tech.isWormholeEnergy) m.energy += 0.63
- if (tech.isWormholeSpores) { //pandimensional spermia
- for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) {
- if (tech.isSporeWorm) {
- b.worm(Vector.add(m.hole.pos2, Vector.rotate({
- x: m.fieldRange * 0.4,
- y: 0
- }, 2 * Math.PI * Math.random())))
- Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -5));
- } else {
- b.spore(Vector.add(m.hole.pos2, Vector.rotate({
- x: m.fieldRange * 0.4,
- y: 0
- }, 2 * Math.PI * Math.random())))
- Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -15));
- }
- }
- }
- break
- }
- }
+ //grab power ups normally too
+ m.grabPowerUp();
+
+ if (m.energy > 0.01) {
+ //find mouse velocity
+ const diff = Vector.sub(m.fieldPosition, m.lastFieldPosition)
+ const speed = Vector.magnitude(diff)
+ const velocity = Vector.mult(Vector.normalise(diff), Math.min(speed, 60)) //limit velocity
+ let radius, radiusSmooth
+ if (Matter.Query.ray(map, m.fieldPosition, player.position).length) { //is there something block the player's view of the field
+ radius = 0
+ radiusSmooth = Math.max(0, isInMap ? 0.96 - 0.02 * speed : 0.995); //0.99
+ } else {
+ radius = Math.max(50, 250 - 2 * speed)
+ radiusSmooth = 0.97
+ }
+ m.fieldRadius = m.fieldRadius * radiusSmooth + radius * (1 - radiusSmooth)
+
+ for (let i = 0, len = body.length; i < len; ++i) {
+ if (Vector.magnitude(Vector.sub(body[i].position, m.fieldPosition)) < m.fieldRadius && !body[i].isNotHoldable) {
+ const DRAIN = speed * body[i].mass * 0.000006 // * (1 + m.energy * m.energy) //drain more energy when you have more energy
+ if (m.energy > DRAIN) {
+ m.energy -= DRAIN;
+ Matter.Body.setVelocity(body[i], velocity); //give block mouse velocity
+ Matter.Body.setAngularVelocity(body[i], body[i].angularVelocity * 0.8)
+ // body[i].force.y -= body[i].mass * simulation.g; //remove gravity effects
+ //blocks drift towards center of pilot wave
+ const sub = Vector.sub(m.fieldPosition, body[i].position)
+ const push = Vector.mult(Vector.normalise(sub), 0.0001 * body[i].mass * Vector.magnitude(sub))
+ body[i].force.x += push.x
+ body[i].force.y += push.y - body[i].mass * simulation.g //remove gravity effects
+ // if (body[i].collisionFilter.category !== cat.bullet) {
+ // body[i].collisionFilter.category = cat.bullet;
+ // }
+ } else {
+ m.fieldCDcycle = m.cycle + 120;
+ m.fieldOn = false
+ m.fieldRadius = 0
+ break
}
- } else if (dist2 < suckRange) {
- const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos2, body[i].position)), 1)
+ }
+ }
+
+
+ // m.holdingTarget.collisionFilter.category = cat.bullet;
+ // m.holdingTarget.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield;
+ // //check every second to see if player is away from thrown body, and make solid
+ // const solid = function(that) {
+ // const dx = that.position.x - player.position.x;
+ // const dy = that.position.y - player.position.y;
+ // if (that.speed < 3 && dx * dx + dy * dy > 10000 && that !== m.holdingTarget) {
+ // that.collisionFilter.category = cat.body; //make solid
+ // that.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet; //can hit player now
+ // } else {
+ // setTimeout(solid, 40, that);
+ // }
+ // };
+ // setTimeout(solid, 200, m.holdingTarget);
+
+
+
+ if (tech.isFreezeMobs) {
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (Vector.magnitude(Vector.sub(mob[i].position, m.fieldPosition)) < m.fieldRadius) {
+ mobs.statusSlow(mob[i], 180)
+ }
+ }
+ }
+
+ ctx.beginPath();
+ const rotate = m.cycle * 0.008;
+ m.fieldPhase += 0.2 // - 0.5 * Math.sqrt(Math.min(m.energy, 1));
+ const off1 = 1 + 0.06 * Math.sin(m.fieldPhase);
+ const off2 = 1 - 0.06 * Math.sin(m.fieldPhase);
+ ctx.beginPath();
+ ctx.ellipse(m.fieldPosition.x, m.fieldPosition.y, 1.2 * m.fieldRadius * off1, 1.2 * m.fieldRadius * off2, rotate, 0, 2 * Math.PI);
+ ctx.globalCompositeOperation = "exclusion"; //"exclusion" "difference";
+ ctx.fillStyle = "#fff"; //"#eef";
+ ctx.fill();
+ ctx.globalCompositeOperation = "source-over";
+ ctx.beginPath();
+ ctx.ellipse(m.fieldPosition.x, m.fieldPosition.y, 1.2 * m.fieldRadius * off1, 1.2 * m.fieldRadius * off2, rotate, 0, 2 * Math.PI * m.energy / m.maxEnergy);
+ ctx.strokeStyle = "#000";
+ ctx.lineWidth = 4;
+ ctx.stroke();
+ } else {
+ m.fieldCDcycle = m.cycle + 120;
+ m.fieldOn = false
+ m.fieldRadius = 0
+ }
+ } else {
+ m.grabPowerUp();
+ }
+ } else {
+ m.fieldOn = false
+ m.fieldRadius = 0
+ }
+ m.drawFieldMeter()
+ }
+ }
+ },
+ {
+ name: "wormhole",
+ description: "use energy to tunnel through a wormhole
wormholes attract blocks and power ups
7% chance to duplicate spawned power ups", //
bullets may also traverse wormholes
+ drain: 0,
+ effect: function () {
+ m.duplicateChance = 0.07
+ m.fieldRange = 0
+ powerUps.setDupChance(); //needed after adjusting duplication chance
+
+ m.hold = function () {
+ // m.hole = { //this is reset with each new field, but I'm leaving it here for reference
+ // isOn: false,
+ // isReady: true,
+ // pos1: {x: 0,y: 0},
+ // pos2: {x: 0,y: 0},
+ // angle: 0,
+ // unit:{x:0,y:0},
+ // }
+ if (m.hole.isOn) {
+ // draw holes
+ m.fieldRange = 0.97 * m.fieldRange + 0.03 * (50 + 10 * Math.sin(simulation.cycle * 0.025))
+ const semiMajorAxis = m.fieldRange + 30
+ const edge1a = Vector.add(Vector.mult(m.hole.unit, semiMajorAxis), m.hole.pos1)
+ const edge1b = Vector.add(Vector.mult(m.hole.unit, -semiMajorAxis), m.hole.pos1)
+ const edge2a = Vector.add(Vector.mult(m.hole.unit, semiMajorAxis), m.hole.pos2)
+ const edge2b = Vector.add(Vector.mult(m.hole.unit, -semiMajorAxis), m.hole.pos2)
+ ctx.beginPath();
+ ctx.moveTo(edge1a.x, edge1a.y)
+ ctx.bezierCurveTo(m.hole.pos1.x, m.hole.pos1.y, m.hole.pos2.x, m.hole.pos2.y, edge2a.x, edge2a.y);
+ ctx.lineTo(edge2b.x, edge2b.y)
+ ctx.bezierCurveTo(m.hole.pos2.x, m.hole.pos2.y, m.hole.pos1.x, m.hole.pos1.y, edge1b.x, edge1b.y);
+ ctx.fillStyle = `rgba(255,255,255,${200 / m.fieldRange / m.fieldRange})` //"rgba(0,0,0,0.1)"
+ ctx.fill();
+ ctx.beginPath();
+ ctx.ellipse(m.hole.pos1.x, m.hole.pos1.y, m.fieldRange, semiMajorAxis, m.hole.angle, 0, 2 * Math.PI)
+ ctx.ellipse(m.hole.pos2.x, m.hole.pos2.y, m.fieldRange, semiMajorAxis, m.hole.angle, 0, 2 * Math.PI)
+ ctx.fillStyle = `rgba(255,255,255,${32 / m.fieldRange})`
+ ctx.fill();
+
+ //suck power ups
+ for (let i = 0, len = powerUp.length; i < len; ++i) {
+ //which hole is closer
+ const dxP1 = m.hole.pos1.x - powerUp[i].position.x;
+ const dyP1 = m.hole.pos1.y - powerUp[i].position.y;
+ const dxP2 = m.hole.pos2.x - powerUp[i].position.x;
+ const dyP2 = m.hole.pos2.y - powerUp[i].position.y;
+ let dxP, dyP, dist2
+ if (dxP1 * dxP1 + dyP1 * dyP1 < dxP2 * dxP2 + dyP2 * dyP2) {
+ dxP = dxP1
+ dyP = dyP1
+ } else {
+ dxP = dxP2
+ dyP = dyP2
+ }
+ dist2 = dxP * dxP + dyP * dyP;
+ if (dist2 < 600000) { //&& !(m.health === m.maxHealth && powerUp[i].name === "heal")
+ powerUp[i].force.x += 4 * (dxP / dist2) * powerUp[i].mass; // float towards hole
+ powerUp[i].force.y += 4 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity
+ Matter.Body.setVelocity(powerUp[i], { //extra friction
+ x: powerUp[i].velocity.x * 0.05,
+ y: powerUp[i].velocity.y * 0.05
+ });
+ if (dist2 < 1000 && !simulation.isChoosing) { //use power up if it is close enough
+
+ // if (true) { //AoE radiation effect
+ // const range = 800
+
+ // for (let i = 0, len = mob.length; i < len; ++i) {
+ // if (mob[i].alive && !mob[i].isShielded) {
+ // dist = Vector.magnitude(Vector.sub(powerUp[i].position, mob[i].position)) - mob[i].radius;
+ // if (dist < range) mobs.statusDoT(mob[i], 0.5) //apply radiation damage status effect on direct hits
+ // }
+ // }
+
+ // simulation.drawList.push({
+ // x: powerUp[i].position.x,
+ // y: powerUp[i].position.y,
+ // radius: range,
+ // color: "rgba(0,150,200,0.3)",
+ // time: 4
+ // });
+ // }
+
+ m.fieldRange *= 0.8
+ powerUps.onPickUp(powerUp[i]);
+ powerUp[i].effect();
+ Matter.Composite.remove(engine.world, powerUp[i]);
+ powerUp.splice(i, 1);
+ break; //because the array order is messed up after splice
+ }
+ }
+ }
+ //suck and shrink blocks
+ const suckRange = 500
+ const shrinkRange = 100
+ const shrinkScale = 0.97;
+ const slowScale = 0.9
+ for (let i = 0, len = body.length; i < len; i++) {
+ if (!body[i].isNotHoldable) {
+ const dist1 = Vector.magnitude(Vector.sub(m.hole.pos1, body[i].position))
+ const dist2 = Vector.magnitude(Vector.sub(m.hole.pos2, body[i].position))
+ if (dist1 < dist2) {
+ if (dist1 < suckRange) {
+ const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos1, body[i].position)), 1)
const slow = Vector.mult(body[i].velocity, slowScale)
Matter.Body.setVelocity(body[i], Vector.add(slow, pull));
//shrink
- if (Vector.magnitude(Vector.sub(m.hole.pos2, body[i].position)) < shrinkRange) {
+ if (Vector.magnitude(Vector.sub(m.hole.pos1, body[i].position)) < shrinkRange) {
Matter.Body.scale(body[i], shrinkScale, shrinkScale);
if (body[i].mass < 0.05) {
Matter.Composite.remove(engine.world, body[i]);
body.splice(i, 1);
m.fieldRange *= 0.8
- // if (tech.isWormholeEnergy && m.energy < m.maxEnergy * 2) m.energy = m.maxEnergy * 2
- if (tech.isWormholeEnergy && m.immuneCycle < m.cycle) m.energy += 0.63
+ if (tech.isWormholeEnergy) m.energy += 0.63
if (tech.isWormholeSpores) { //pandimensional spermia
for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) {
if (tech.isSporeWorm) {
- b.worm(Vector.add(m.hole.pos1, Vector.rotate({
+ b.worm(Vector.add(m.hole.pos2, Vector.rotate({
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
- Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), 5));
+ Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -5));
} else {
- b.spore(Vector.add(m.hole.pos1, Vector.rotate({
+ b.spore(Vector.add(m.hole.pos2, Vector.rotate({
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
- Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), 15));
+ Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -15));
}
}
}
@@ -3062,338 +2988,372 @@ const m = {
}
}
}
- }
- }
- if (tech.isWormBullets) {
- //teleport bullets
- for (let i = 0, len = bullet.length; i < len; ++i) { //teleport bullets from hole1 to hole2
- if (!bullet[i].botType && !bullet[i].isInHole) { //don't teleport bots
- if (Vector.magnitude(Vector.sub(m.hole.pos1, bullet[i].position)) < m.fieldRange) { //find if bullet is touching hole1
- Matter.Body.setPosition(bullet[i], Vector.add(m.hole.pos2, Vector.sub(m.hole.pos1, bullet[i].position)));
- m.fieldRange += 5
- bullet[i].isInHole = true
- } else if (Vector.magnitude(Vector.sub(m.hole.pos2, bullet[i].position)) < m.fieldRange) { //find if bullet is touching hole1
- Matter.Body.setPosition(bullet[i], Vector.add(m.hole.pos1, Vector.sub(m.hole.pos2, bullet[i].position)));
- m.fieldRange += 5
- bullet[i].isInHole = true
- }
- }
- }
- // mobs get pushed away
- for (let i = 0, len = mob.length; i < len; i++) {
- if (Vector.magnitude(Vector.sub(m.hole.pos1, mob[i].position)) < 200) {
- const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos1, mob[i].position)), -0.07)
- Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
- }
- if (Vector.magnitude(Vector.sub(m.hole.pos2, mob[i].position)) < 200) {
- const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos2, mob[i].position)), -0.07)
- Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
- }
- }
- }
- }
-
- if (m.fieldCDcycle < m.cycle) {
- const scale = 60
- const justPastMouse = Vector.add(Vector.mult(Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)), 50), simulation.mouseInGame)
- const sub = Vector.sub(simulation.mouseInGame, m.pos)
- const mag = Vector.magnitude(sub)
- const drain = tech.isFreeWormHole ? 0 : 0.06 + 0.006 * Math.sqrt(mag)
- if (input.field) {
- m.grabPowerUp();
-
- //draw possible wormhole
- if (mag > 250 && m.energy > drain) {
- const unit = Vector.perp(Vector.normalise(sub))
- const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
- m.fieldRange = 0.97 * m.fieldRange + 0.03 * (50 + 10 * Math.sin(simulation.cycle * 0.025))
- const edge2a = Vector.add(Vector.mult(unit, 1.5 * m.fieldRange), simulation.mouseInGame)
- const edge2b = Vector.add(Vector.mult(unit, -1.5 * m.fieldRange), simulation.mouseInGame)
- ctx.beginPath();
- ctx.moveTo(where.x, where.y)
- ctx.bezierCurveTo(where.x, where.y, simulation.mouseInGame.x, simulation.mouseInGame.y, edge2a.x, edge2a.y);
- ctx.moveTo(where.x, where.y)
- ctx.bezierCurveTo(where.x, where.y, simulation.mouseInGame.x, simulation.mouseInGame.y, edge2b.x, edge2b.y);
- if (
- Matter.Query.region(map, {
- min: {
- x: simulation.mouseInGame.x - scale,
- y: simulation.mouseInGame.y - scale
- },
- max: {
- x: simulation.mouseInGame.x + scale,
- y: simulation.mouseInGame.y + scale
- }
- }).length === 0 &&
- Matter.Query.ray(map, m.pos, justPastMouse).length === 0
- ) {
- m.hole.isReady = true;
- // ctx.fillStyle = "rgba(255,255,255,0.5)"
- // ctx.fill();
- ctx.lineWidth = 1
- ctx.strokeStyle = "#000"
- ctx.stroke();
- } else {
- m.hole.isReady = false;
- ctx.lineWidth = 1
- ctx.strokeStyle = "#000"
- ctx.lineDashOffset = 30 * Math.random()
- ctx.setLineDash([20, 40]);
- ctx.stroke();
- ctx.setLineDash([]);
- }
- } else {
- m.hole.isReady = false;
- }
- } else {
- //make new wormhole
- if (
- m.hole.isReady && mag > 250 && m.energy > drain &&
- Matter.Query.region(map, {
- min: {
- x: simulation.mouseInGame.x - scale,
- y: simulation.mouseInGame.y - scale
- },
- max: {
- x: simulation.mouseInGame.x + scale,
- y: simulation.mouseInGame.y + scale
- }
- }).length === 0 &&
- Matter.Query.ray(map, m.pos, justPastMouse).length === 0
- ) {
- m.energy -= drain
- m.hole.isReady = false;
- m.fieldRange = 0
- Matter.Body.setPosition(player, simulation.mouseInGame);
- m.buttonCD_jump = 0 //this might fix a bug with jumping
- const velocity = Vector.mult(Vector.normalise(sub), 20)
- Matter.Body.setVelocity(player, {
- x: velocity.x,
- y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer
- });
- if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 15; //player is immune to damage for 1/4 seconds
- // move bots to player
- for (let i = 0; i < bullet.length; i++) {
- if (bullet[i].botType) {
- Matter.Body.setPosition(bullet[i], Vector.add(player.position, {
- x: 250 * (Math.random() - 0.5),
- y: 250 * (Math.random() - 0.5)
- }));
- Matter.Body.setVelocity(bullet[i], {
- x: 0,
- y: 0
- });
- }
- }
-
- //set holes
- m.hole.isOn = true;
- m.hole.pos1.x = m.pos.x
- m.hole.pos1.y = m.pos.y
- m.hole.pos2.x = player.position.x
- m.hole.pos2.y = player.position.y
- m.hole.angle = Math.atan2(sub.y, sub.x)
- m.hole.unit = Vector.perp(Vector.normalise(sub))
-
- if (tech.isWormholeDamage) {
- who = Matter.Query.ray(mob, m.pos, simulation.mouseInGame, 100)
- for (let i = 0; i < who.length; i++) {
- if (who[i].body.alive) {
- mobs.statusDoT(who[i].body, 1, 420)
- mobs.statusStun(who[i].body, 360)
+ } else if (dist2 < suckRange) {
+ const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos2, body[i].position)), 1)
+ const slow = Vector.mult(body[i].velocity, slowScale)
+ Matter.Body.setVelocity(body[i], Vector.add(slow, pull));
+ //shrink
+ if (Vector.magnitude(Vector.sub(m.hole.pos2, body[i].position)) < shrinkRange) {
+ Matter.Body.scale(body[i], shrinkScale, shrinkScale);
+ if (body[i].mass < 0.05) {
+ Matter.Composite.remove(engine.world, body[i]);
+ body.splice(i, 1);
+ m.fieldRange *= 0.8
+ // if (tech.isWormholeEnergy && m.energy < m.maxEnergy * 2) m.energy = m.maxEnergy * 2
+ if (tech.isWormholeEnergy && m.immuneCycle < m.cycle) m.energy += 0.63
+ if (tech.isWormholeSpores) { //pandimensional spermia
+ for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) {
+ if (tech.isSporeWorm) {
+ b.worm(Vector.add(m.hole.pos1, Vector.rotate({
+ x: m.fieldRange * 0.4,
+ y: 0
+ }, 2 * Math.PI * Math.random())))
+ Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), 5));
+ } else {
+ b.spore(Vector.add(m.hole.pos1, Vector.rotate({
+ x: m.fieldRange * 0.4,
+ y: 0
+ }, 2 * Math.PI * Math.random())))
+ Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), 15));
+ }
+ }
}
+ break
}
}
}
}
}
-
- // if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
- // const justPastMouse = Vector.add(Vector.mult(Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)), 50), simulation.mouseInGame)
- // const scale = 60
- // // console.log(Matter.Query.region(map, bounds))
- // const sub = Vector.sub(simulation.mouseInGame, m.pos)
- // const mag = Vector.magnitude(sub)
- // const drain = tech.isFreeWormHole ? 0 : 0.06 + 0.006 * Math.sqrt(mag)
- // if (m.hole.isReady && mag > 250 && m.energy > drain) {
- // if (
- // Matter.Query.region(map, {
- // min: {
- // x: simulation.mouseInGame.x - scale,
- // y: simulation.mouseInGame.y - scale
- // },
- // max: {
- // x: simulation.mouseInGame.x + scale,
- // y: simulation.mouseInGame.y + scale
- // }
- // }).length === 0 &&
- // Matter.Query.ray(map, m.pos, justPastMouse).length === 0
- // // Matter.Query.ray(map, m.pos, simulation.mouseInGame).length === 0 &&
- // // Matter.Query.ray(map, player.position, simulation.mouseInGame).length === 0 &&
- // // Matter.Query.ray(map, player.position, justPastMouse).length === 0
- // ) {
- // m.energy -= drain
- // m.hole.isReady = false;
- // m.fieldRange = 0
- // Matter.Body.setPosition(player, simulation.mouseInGame);
- // m.buttonCD_jump = 0 //this might fix a bug with jumping
- // const velocity = Vector.mult(Vector.normalise(sub), 20)
- // Matter.Body.setVelocity(player, {
- // x: velocity.x,
- // y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer
- // });
- // if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 15; //player is immune to damage for 1/4 seconds
- // // move bots to player
- // for (let i = 0; i < bullet.length; i++) {
- // if (bullet[i].botType) {
- // Matter.Body.setPosition(bullet[i], Vector.add(player.position, {
- // x: 250 * (Math.random() - 0.5),
- // y: 250 * (Math.random() - 0.5)
- // }));
- // Matter.Body.setVelocity(bullet[i], {
- // x: 0,
- // y: 0
- // });
- // }
- // }
-
- // //set holes
- // m.hole.isOn = true;
- // m.hole.pos1.x = m.pos.x
- // m.hole.pos1.y = m.pos.y
- // m.hole.pos2.x = player.position.x
- // m.hole.pos2.y = player.position.y
- // m.hole.angle = Math.atan2(sub.y, sub.x)
- // m.hole.unit = Vector.perp(Vector.normalise(sub))
-
- // if (tech.isWormholeDamage) {
- // who = Matter.Query.ray(mob, m.pos, simulation.mouseInGame, 100)
- // for (let i = 0; i < who.length; i++) {
- // if (who[i].body.alive) {
- // mobs.statusDoT(who[i].body, 1, 420)
- // mobs.statusStun(who[i].body, 360)
- // }
- // }
- // }
- // } else {
- // //draw failed wormhole
- // const unit = Vector.perp(Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)))
- // const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle), }
- // m.fieldRange = 0.97 * m.fieldRange + 0.03 * (50 + 10 * Math.sin(simulation.cycle * 0.025))
- // const edge2a = Vector.add(Vector.mult(unit, 1.5 * m.fieldRange), simulation.mouseInGame)
- // const edge2b = Vector.add(Vector.mult(unit, -1.5 * m.fieldRange), simulation.mouseInGame)
- // ctx.beginPath();
- // ctx.moveTo(where.x, where.y)
- // ctx.bezierCurveTo(where.x, where.y, simulation.mouseInGame.x, simulation.mouseInGame.y, edge2a.x, edge2a.y);
- // ctx.lineTo(edge2b.x, edge2b.y)
- // ctx.bezierCurveTo(simulation.mouseInGame.x, simulation.mouseInGame.y, where.x, where.y, where.x, where.y);
- // // ctx.fillStyle = "rgba(255,255,255,0.5)"
- // // ctx.fill();
- // ctx.lineWidth = 1
- // ctx.strokeStyle = "#000"
- // ctx.lineDashOffset = 30 * Math.random()
- // ctx.setLineDash([20, 40]);
- // ctx.stroke();
- // ctx.setLineDash([]);
- // }
- // }
- // m.grabPowerUp();
- // } else {
- // m.hole.isReady = true;
- // }
-
-
-
-
- m.drawFieldMeter()
+ if (tech.isWormBullets) {
+ //teleport bullets
+ for (let i = 0, len = bullet.length; i < len; ++i) { //teleport bullets from hole1 to hole2
+ if (!bullet[i].botType && !bullet[i].isInHole) { //don't teleport bots
+ if (Vector.magnitude(Vector.sub(m.hole.pos1, bullet[i].position)) < m.fieldRange) { //find if bullet is touching hole1
+ Matter.Body.setPosition(bullet[i], Vector.add(m.hole.pos2, Vector.sub(m.hole.pos1, bullet[i].position)));
+ m.fieldRange += 5
+ bullet[i].isInHole = true
+ } else if (Vector.magnitude(Vector.sub(m.hole.pos2, bullet[i].position)) < m.fieldRange) { //find if bullet is touching hole1
+ Matter.Body.setPosition(bullet[i], Vector.add(m.hole.pos1, Vector.sub(m.hole.pos2, bullet[i].position)));
+ m.fieldRange += 5
+ bullet[i].isInHole = true
+ }
+ }
+ }
+ // mobs get pushed away
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (Vector.magnitude(Vector.sub(m.hole.pos1, mob[i].position)) < 200) {
+ const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos1, mob[i].position)), -0.07)
+ Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
+ }
+ if (Vector.magnitude(Vector.sub(m.hole.pos2, mob[i].position)) < 200) {
+ const pull = Vector.mult(Vector.normalise(Vector.sub(m.hole.pos2, mob[i].position)), -0.07)
+ Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
+ }
+ }
+ }
}
- },
- // rewind: function() {
- // if (input.down) {
- // if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
- // const DRAIN = 0.01
- // if (this.rewindCount < 289 && m.energy > DRAIN) {
- // m.energy -= DRAIN
+ if (m.fieldCDcycle < m.cycle) {
+ const scale = 60
+ const justPastMouse = Vector.add(Vector.mult(Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)), 50), simulation.mouseInGame)
+ const sub = Vector.sub(simulation.mouseInGame, m.pos)
+ const mag = Vector.magnitude(sub)
+
+ if (input.field) {
+ m.grabPowerUp();
+ //draw possible wormhole
+ if (tech.isWormholeMapIgnore && Matter.Query.ray(map, m.pos, justPastMouse).length !== 0) {
+ this.drain = (0.06 + 0.006 * Math.sqrt(mag)) * 2
+ } else {
+ this.drain = tech.isFreeWormHole ? 0 : 0.06 + 0.006 * Math.sqrt(mag)
+ }
+ const unit = Vector.perp(Vector.normalise(sub))
+ const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
+ m.fieldRange = 0.97 * m.fieldRange + 0.03 * (50 + 10 * Math.sin(simulation.cycle * 0.025))
+ const edge2a = Vector.add(Vector.mult(unit, 1.5 * m.fieldRange), simulation.mouseInGame)
+ const edge2b = Vector.add(Vector.mult(unit, -1.5 * m.fieldRange), simulation.mouseInGame)
+ ctx.beginPath();
+ ctx.moveTo(where.x, where.y)
+ ctx.bezierCurveTo(where.x, where.y, simulation.mouseInGame.x, simulation.mouseInGame.y, edge2a.x, edge2a.y);
+ ctx.moveTo(where.x, where.y)
+ ctx.bezierCurveTo(where.x, where.y, simulation.mouseInGame.x, simulation.mouseInGame.y, edge2b.x, edge2b.y);
+ if (
+ mag > 250 && m.energy > this.drain &&
+ (tech.isWormholeMapIgnore || Matter.Query.ray(map, m.pos, justPastMouse).length === 0) &&
+ Matter.Query.region(map, {
+ min: {
+ x: simulation.mouseInGame.x - scale,
+ y: simulation.mouseInGame.y - scale
+ },
+ max: {
+ x: simulation.mouseInGame.x + scale,
+ y: simulation.mouseInGame.y + scale
+ }
+ }).length === 0
+ ) {
+ m.hole.isReady = true;
+ // ctx.fillStyle = "rgba(255,255,255,0.5)"
+ // ctx.fill();
+ ctx.lineWidth = 1
+ ctx.strokeStyle = "#000"
+ ctx.stroke();
+ } else {
+ m.hole.isReady = false;
+ ctx.lineWidth = 1
+ ctx.strokeStyle = "#000"
+ ctx.lineDashOffset = 30 * Math.random()
+ ctx.setLineDash([20, 40]);
+ ctx.stroke();
+ ctx.setLineDash([]);
+ }
+ } else {
+ //make new wormhole
+ if (
+ m.hole.isReady && mag > 250 && m.energy > this.drain &&
+ (tech.isWormholeMapIgnore || Matter.Query.ray(map, m.pos, justPastMouse).length === 0) &&
+ Matter.Query.region(map, {
+ min: {
+ x: simulation.mouseInGame.x - scale,
+ y: simulation.mouseInGame.y - scale
+ },
+ max: {
+ x: simulation.mouseInGame.x + scale,
+ y: simulation.mouseInGame.y + scale
+ }
+ }).length === 0
+ ) {
+ m.energy -= this.drain
+ m.hole.isReady = false;
+ m.fieldRange = 0
+ Matter.Body.setPosition(player, simulation.mouseInGame);
+ m.buttonCD_jump = 0 //this might fix a bug with jumping
+ const velocity = Vector.mult(Vector.normalise(sub), 20)
+ Matter.Body.setVelocity(player, {
+ x: velocity.x,
+ y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer
+ });
+ if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 15; //player is immune to damage for 1/4 seconds
+ // move bots to player
+ for (let i = 0; i < bullet.length; i++) {
+ if (bullet[i].botType) {
+ Matter.Body.setPosition(bullet[i], Vector.add(player.position, {
+ x: 250 * (Math.random() - 0.5),
+ y: 250 * (Math.random() - 0.5)
+ }));
+ Matter.Body.setVelocity(bullet[i], {
+ x: 0,
+ y: 0
+ });
+ }
+ }
+
+ //set holes
+ m.hole.isOn = true;
+ m.hole.pos1.x = m.pos.x
+ m.hole.pos1.y = m.pos.y
+ m.hole.pos2.x = player.position.x
+ m.hole.pos2.y = player.position.y
+ m.hole.angle = Math.atan2(sub.y, sub.x)
+ m.hole.unit = Vector.perp(Vector.normalise(sub))
+
+ if (tech.isWormholeDamage) {
+ who = Matter.Query.ray(mob, m.pos, simulation.mouseInGame, 100)
+ for (let i = 0; i < who.length; i++) {
+ if (who[i].body.alive) {
+ mobs.statusDoT(who[i].body, 1, 420)
+ mobs.statusStun(who[i].body, 360)
+ }
+ }
+ }
+ }
+ }
+ }
+ // if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
+ // const justPastMouse = Vector.add(Vector.mult(Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)), 50), simulation.mouseInGame)
+ // const scale = 60
+ // // console.log(Matter.Query.region(map, bounds))
+ // const sub = Vector.sub(simulation.mouseInGame, m.pos)
+ // const mag = Vector.magnitude(sub)
+ // const drain = tech.isFreeWormHole ? 0 : 0.06 + 0.006 * Math.sqrt(mag)
+ // if (m.hole.isReady && mag > 250 && m.energy > drain) {
+ // if (
+ // Matter.Query.region(map, {
+ // min: {
+ // x: simulation.mouseInGame.x - scale,
+ // y: simulation.mouseInGame.y - scale
+ // },
+ // max: {
+ // x: simulation.mouseInGame.x + scale,
+ // y: simulation.mouseInGame.y + scale
+ // }
+ // }).length === 0 &&
+ // Matter.Query.ray(map, m.pos, justPastMouse).length === 0
+ // // Matter.Query.ray(map, m.pos, simulation.mouseInGame).length === 0 &&
+ // // Matter.Query.ray(map, player.position, simulation.mouseInGame).length === 0 &&
+ // // Matter.Query.ray(map, player.position, justPastMouse).length === 0
+ // ) {
+ // m.energy -= drain
+ // m.hole.isReady = false;
+ // m.fieldRange = 0
+ // Matter.Body.setPosition(player, simulation.mouseInGame);
+ // m.buttonCD_jump = 0 //this might fix a bug with jumping
+ // const velocity = Vector.mult(Vector.normalise(sub), 20)
+ // Matter.Body.setVelocity(player, {
+ // x: velocity.x,
+ // y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer
+ // });
+ // if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 15; //player is immune to damage for 1/4 seconds
+ // // move bots to player
+ // for (let i = 0; i < bullet.length; i++) {
+ // if (bullet[i].botType) {
+ // Matter.Body.setPosition(bullet[i], Vector.add(player.position, {
+ // x: 250 * (Math.random() - 0.5),
+ // y: 250 * (Math.random() - 0.5)
+ // }));
+ // Matter.Body.setVelocity(bullet[i], {
+ // x: 0,
+ // y: 0
+ // });
+ // }
+ // }
+
+ // //set holes
+ // m.hole.isOn = true;
+ // m.hole.pos1.x = m.pos.x
+ // m.hole.pos1.y = m.pos.y
+ // m.hole.pos2.x = player.position.x
+ // m.hole.pos2.y = player.position.y
+ // m.hole.angle = Math.atan2(sub.y, sub.x)
+ // m.hole.unit = Vector.perp(Vector.normalise(sub))
+
+ // if (tech.isWormholeDamage) {
+ // who = Matter.Query.ray(mob, m.pos, simulation.mouseInGame, 100)
+ // for (let i = 0; i < who.length; i++) {
+ // if (who[i].body.alive) {
+ // mobs.statusDoT(who[i].body, 1, 420)
+ // mobs.statusStun(who[i].body, 360)
+ // }
+ // }
+ // }
+ // } else {
+ // //draw failed wormhole
+ // const unit = Vector.perp(Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)))
+ // const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle), }
+ // m.fieldRange = 0.97 * m.fieldRange + 0.03 * (50 + 10 * Math.sin(simulation.cycle * 0.025))
+ // const edge2a = Vector.add(Vector.mult(unit, 1.5 * m.fieldRange), simulation.mouseInGame)
+ // const edge2b = Vector.add(Vector.mult(unit, -1.5 * m.fieldRange), simulation.mouseInGame)
+ // ctx.beginPath();
+ // ctx.moveTo(where.x, where.y)
+ // ctx.bezierCurveTo(where.x, where.y, simulation.mouseInGame.x, simulation.mouseInGame.y, edge2a.x, edge2a.y);
+ // ctx.lineTo(edge2b.x, edge2b.y)
+ // ctx.bezierCurveTo(simulation.mouseInGame.x, simulation.mouseInGame.y, where.x, where.y, where.x, where.y);
+ // // ctx.fillStyle = "rgba(255,255,255,0.5)"
+ // // ctx.fill();
+ // ctx.lineWidth = 1
+ // ctx.strokeStyle = "#000"
+ // ctx.lineDashOffset = 30 * Math.random()
+ // ctx.setLineDash([20, 40]);
+ // ctx.stroke();
+ // ctx.setLineDash([]);
+ // }
+ // }
+ // m.grabPowerUp();
+ // } else {
+ // m.hole.isReady = true;
+ // }
- // if (this.rewindCount === 0) {
- // const shortPause = function() {
- // if (m.defaultFPSCycle < m.cycle) { //back to default values
- // simulation.fpsCap = simulation.fpsCapDefault
- // simulation.fpsInterval = 1000 / simulation.fpsCap;
- // // document.getElementById("dmg").style.transition = "opacity 1s";
- // // document.getElementById("dmg").style.opacity = "0";
- // } else {
- // requestAnimationFrame(shortPause);
- // }
- // };
- // if (m.defaultFPSCycle < m.cycle) requestAnimationFrame(shortPause);
- // simulation.fpsCap = 4 //1 is longest pause, 4 is standard
- // simulation.fpsInterval = 1000 / simulation.fpsCap;
- // m.defaultFPSCycle = m.cycle
- // }
- // this.rewindCount += 10;
- // simulation.wipe = function() { //set wipe to have trails
- // // ctx.fillStyle = "rgba(255,255,255,0)";
- // ctx.fillStyle = `rgba(221,221,221,${0.004})`;
- // ctx.fillRect(0, 0, canvas.width, canvas.height);
- // }
- // let history = m.history[(m.cycle - this.rewindCount) % 300]
- // Matter.Body.setPosition(player, history.position);
- // Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
- // if (history.health > m.health) {
- // m.health = history.health
- // m.displayHealth();
- // }
- // //grab power ups
- // for (let i = 0, len = powerUp.length; i < len; ++i) {
- // const dxP = player.position.x - powerUp[i].position.x;
- // const dyP = player.position.y - powerUp[i].position.y;
- // if (dxP * dxP + dyP * dyP < 50000 && !simulation.isChoosing && !(m.health === m.maxHealth && powerUp[i].name === "heal")) {
- // powerUps.onPickUp(player.position);
- // powerUp[i].effect();
- // Matter.Composite.remove(engine.world, powerUp[i]);
- // powerUp.splice(i, 1);
- // const shortPause = function() {
- // if (m.defaultFPSCycle < m.cycle) { //back to default values
- // simulation.fpsCap = simulation.fpsCapDefault
- // simulation.fpsInterval = 1000 / simulation.fpsCap;
- // // document.getElementById("dmg").style.transition = "opacity 1s";
- // // document.getElementById("dmg").style.opacity = "0";
- // } else {
- // requestAnimationFrame(shortPause);
- // }
- // };
- // if (m.defaultFPSCycle < m.cycle) requestAnimationFrame(shortPause);
- // simulation.fpsCap = 3 //1 is longest pause, 4 is standard
- // simulation.fpsInterval = 1000 / simulation.fpsCap;
- // m.defaultFPSCycle = m.cycle
- // break; //because the array order is messed up after splice
- // }
- // }
- // m.immuneCycle = m.cycle + 5; //player is immune to damage for 30 cycles
- // } else {
- // m.fieldCDcycle = m.cycle + 30;
- // // m.resetHistory();
- // }
- // } else {
- // if (this.rewindCount !== 0) {
- // m.fieldCDcycle = m.cycle + 30;
- // m.resetHistory();
- // this.rewindCount = 0;
- // simulation.wipe = function() { //set wipe to normal
- // ctx.clearRect(0, 0, canvas.width, canvas.height);
- // }
- // }
- // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- // }
- // }
- // m.drawFieldMeter()
- // },
+ m.drawFieldMeter()
+ }
},
+
+ // rewind: function() {
+ // if (input.down) {
+ // if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
+ // const DRAIN = 0.01
+ // if (this.rewindCount < 289 && m.energy > DRAIN) {
+ // m.energy -= DRAIN
+
+
+ // if (this.rewindCount === 0) {
+ // const shortPause = function() {
+ // if (m.defaultFPSCycle < m.cycle) { //back to default values
+ // simulation.fpsCap = simulation.fpsCapDefault
+ // simulation.fpsInterval = 1000 / simulation.fpsCap;
+ // // document.getElementById("dmg").style.transition = "opacity 1s";
+ // // document.getElementById("dmg").style.opacity = "0";
+ // } else {
+ // requestAnimationFrame(shortPause);
+ // }
+ // };
+ // if (m.defaultFPSCycle < m.cycle) requestAnimationFrame(shortPause);
+ // simulation.fpsCap = 4 //1 is longest pause, 4 is standard
+ // simulation.fpsInterval = 1000 / simulation.fpsCap;
+ // m.defaultFPSCycle = m.cycle
+ // }
+
+
+ // this.rewindCount += 10;
+ // simulation.wipe = function() { //set wipe to have trails
+ // // ctx.fillStyle = "rgba(255,255,255,0)";
+ // ctx.fillStyle = `rgba(221,221,221,${0.004})`;
+ // ctx.fillRect(0, 0, canvas.width, canvas.height);
+ // }
+ // let history = m.history[(m.cycle - this.rewindCount) % 300]
+ // Matter.Body.setPosition(player, history.position);
+ // Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
+ // if (history.health > m.health) {
+ // m.health = history.health
+ // m.displayHealth();
+ // }
+ // //grab power ups
+ // for (let i = 0, len = powerUp.length; i < len; ++i) {
+ // const dxP = player.position.x - powerUp[i].position.x;
+ // const dyP = player.position.y - powerUp[i].position.y;
+ // if (dxP * dxP + dyP * dyP < 50000 && !simulation.isChoosing && !(m.health === m.maxHealth && powerUp[i].name === "heal")) {
+ // powerUps.onPickUp(player.position);
+ // powerUp[i].effect();
+ // Matter.Composite.remove(engine.world, powerUp[i]);
+ // powerUp.splice(i, 1);
+ // const shortPause = function() {
+ // if (m.defaultFPSCycle < m.cycle) { //back to default values
+ // simulation.fpsCap = simulation.fpsCapDefault
+ // simulation.fpsInterval = 1000 / simulation.fpsCap;
+ // // document.getElementById("dmg").style.transition = "opacity 1s";
+ // // document.getElementById("dmg").style.opacity = "0";
+ // } else {
+ // requestAnimationFrame(shortPause);
+ // }
+ // };
+ // if (m.defaultFPSCycle < m.cycle) requestAnimationFrame(shortPause);
+ // simulation.fpsCap = 3 //1 is longest pause, 4 is standard
+ // simulation.fpsInterval = 1000 / simulation.fpsCap;
+ // m.defaultFPSCycle = m.cycle
+ // break; //because the array order is messed up after splice
+ // }
+ // }
+ // m.immuneCycle = m.cycle + 5; //player is immune to damage for 30 cycles
+ // } else {
+ // m.fieldCDcycle = m.cycle + 30;
+ // // m.resetHistory();
+ // }
+ // } else {
+ // if (this.rewindCount !== 0) {
+ // m.fieldCDcycle = m.cycle + 30;
+ // m.resetHistory();
+ // this.rewindCount = 0;
+ // simulation.wipe = function() { //set wipe to normal
+ // ctx.clearRect(0, 0, canvas.width, canvas.height);
+ // }
+ // }
+ // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
+ // }
+ // }
+ // m.drawFieldMeter()
+ // },
+ },
],
//************************************************************************************
//************************************************************************************
diff --git a/js/powerup.js b/js/powerup.js
index 1f5c936..09087dd 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -321,7 +321,7 @@ const powerUps = {
}
if (tech.isRerollBots) {
let delay = 0
- for (const cost = 2 + Math.floor(0.2 * b.totalBots()); powerUps.research.count > cost - 1; powerUps.research.count -= cost) {
+ for (const cost = 2 + Math.floor(0.1666 * b.totalBots()); powerUps.research.count > cost - 1; powerUps.research.count -= cost) {
delay += 500
setTimeout(() => {
b.randomBot()
@@ -469,30 +469,30 @@ const powerUps = {
if (tech.ammoCap) {
const ammoAdded = Math.ceil(target.ammoPack * 0.7 * tech.ammoCap) //0.7 is average
target.ammo = ammoAdded
- simulation.makeTextLog(`${target.name}.ammo = ${ammoAdded}`)
+ // simulation.makeTextLog(`${target.name}.ammo = ${ammoAdded}`)
} else {
const ammoAdded = Math.ceil((0.7 * Math.random() + 0.7 * Math.random()) * target.ammoPack)
target.ammo += ammoAdded
- simulation.makeTextLog(`${target.name}.ammo += ${ammoAdded}`)
+ // simulation.makeTextLog(`${target.name}.ammo += ${ammoAdded}`)
}
}
} else { //give ammo to all guns in inventory
- let textLog = ""
+ // let textLog = ""
for (let i = 0, len = b.inventory.length; i < len; i++) {
const target = b.guns[b.inventory[i]]
if (target.ammo !== Infinity) {
if (tech.ammoCap) {
const ammoAdded = Math.ceil(target.ammoPack * 0.45 * tech.ammoCap) //0.45 is average
target.ammo = ammoAdded
- textLog += `${target.name}.ammo = ${ammoAdded}
`
+ // textLog += `${target.name}.ammo = ${ammoAdded}
`
} else {
const ammoAdded = Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack) //Math.ceil(Math.random() * target.ammoPack)
target.ammo += ammoAdded
- textLog += `${target.name}.ammo += ${ammoAdded}
`
+ // textLog += `${target.name}.ammo += ${ammoAdded}
`
}
}
}
- simulation.makeTextLog(textLog)
+ // simulation.makeTextLog(textLog)
}
// } else { //give ammo to all guns in inventory
// for (let i = 0, len = b.inventory.length; i < len; i++) {
diff --git a/js/simulation.js b/js/simulation.js
index 56b5269..809c09f 100644
--- a/js/simulation.js
+++ b/js/simulation.js
@@ -354,7 +354,7 @@ const simulation = {
//
' + text;
diff --git a/js/spawn.js b/js/spawn.js
index 8471eb1..1034c97 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -13,12 +13,13 @@ const spawn = {
"grenadier", "grenadier",
"striker", "striker",
"laser", "laser",
- "exploder", "exploder",
"stabber", "stabber",
- "launcher", "launcher",
"springer", "springer",
"pulsar", "pulsar",
- "sneaker", "sneaker",
+ "exploder",
+ "sneaker",
+ "launcher",
+ "launcherOne",
"sucker",
"sniper",
"spinner",
@@ -28,7 +29,7 @@ const spawn = {
"spawner",
"ghoster",
],
- allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "stabber", "sniper", "pulsar", "grenadier", "slasher"],
+ allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "launcherOne", "stabber", "sniper", "pulsar", "grenadier", "slasher"],
setSpawnList() { //this is run at the start of each new level to determine the possible mobs for the level
//each level has 2 mobs: one new mob and one from the last level
spawn.pickList.splice(0, 1);
@@ -136,7 +137,7 @@ const spawn = {
me.isMACHO = true;
me.frictionAir = 0.006
- me.do = function() {
+ me.do = function () {
const sine = Math.sin(simulation.cycle * 0.015)
this.radius = 370 * (1 + 0.1 * sine)
//chase player
@@ -155,6 +156,7 @@ const spawn = {
if (mag < this.radius) { //buff to player when inside radius
tech.isHarmMACHO = true;
+
//draw halo
ctx.strokeStyle = "rgba(80,120,200,0.2)" //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})`
ctx.beginPath();
@@ -191,7 +193,7 @@ const spawn = {
me.collisionFilter.mask = 0; //cat.player //| cat.body
me.chaseSpeed = 1 + 1.5 * Math.random()
- me.awake = function() {
+ me.awake = function () {
//chase player
const sub = Vector.sub(player.position, this.position)
const where = Vector.add(this.position, Vector.mult(Vector.normalise(sub), this.chaseSpeed))
@@ -241,7 +243,7 @@ const spawn = {
ctx.arc(this.position.x, this.position.y, this.radius, 0, 2 * Math.PI);
// ctx.fillStyle = "hsla(160, 100%, 35%,0.75)" //"rgba(255,0,255,0.2)";
// ctx.globalCompositeOperation = "lighter"
- ctx.fillStyle = `rgba(25,139,170,${0.2+0.12*Math.random()})`;
+ ctx.fillStyle = `rgba(25,139,170,${0.2 + 0.12 * Math.random()})`;
ctx.fill();
this.radius = 100 * (1 + 0.25 * Math.sin(simulation.cycle * 0.03))
// ctx.fillStyle = "#fff";
@@ -249,7 +251,7 @@ const spawn = {
// ctx.fill();
// ctx.globalCompositeOperation = "source-over"
}
- me.do = function() { //wake up 2 seconds after the player moves
+ me.do = function () { //wake up 2 seconds after the player moves
if (player.speed > 1 && !m.isCloak) {
setTimeout(() => { this.do = this.awake; }, 2000);
}
@@ -271,10 +273,7 @@ const spawn = {
});
Composite.add(engine.world, me.constraint);
}, 2000); //add in a delay in case the level gets flipped left right
-
me.isBoss = true;
-
-
me.frictionAir = 0.01;
me.memory = Infinity;
me.hasRunDeathScript = false
@@ -282,7 +281,7 @@ const spawn = {
const density = 0.2
Matter.Body.setDensity(me, density); //extra dense //normal is 0.001 //makes effective life much larger
// spawn.shield(me, x, y, 1);
- me.onDeath = function() {
+ me.onDeath = function () {
if (!this.hasRunDeathScript) {
this.hasRunDeathScript = true
//make a block body to replace this one
@@ -296,7 +295,7 @@ const spawn = {
body[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet;
body[len].classType = "body";
Composite.add(engine.world, body[len]); //add to world
- const expand = function(that, massLimit) {
+ const expand = function (that, massLimit) {
const scale = 1.05;
Matter.Body.scale(that, scale, scale);
if (that.mass < massLimit) setTimeout(expand, 20, that, massLimit);
@@ -318,7 +317,7 @@ const spawn = {
//add lore level as next level if player took lore tech earlier in the game
if (lore.techCount > (lore.techGoal - 1) && !simulation.isCheating) {
simulation.makeTextLog(`undefined = ${lore.techCount}/${lore.techGoal}`, 360);
- setTimeout(function() {
+ setTimeout(function () {
simulation.makeTextLog(`level.levels.push("null")`, 720);
unlockExit()
level.levels.push("null")
@@ -332,7 +331,7 @@ const spawn = {
count++
if (count < 660) {
if (count === 1) simulation.makeTextLog(`//enter testing mode to set level.levels.length to Infinite`);
- if (!(count % 60)) simulation.makeTextLog(`simulation.analysis = ${((count/60- Math.random())*0.1 ).toFixed(3)}`);
+ if (!(count % 60)) simulation.makeTextLog(`simulation.analysis = ${((count / 60 - Math.random()) * 0.1).toFixed(3)}`);
} else if (count === 660) {
simulation.makeTextLog(`simulation.analysis = 1 //analysis complete`);
} else if (count === 780) {
@@ -351,7 +350,7 @@ const spawn = {
document.getElementById("text-log").style.opacity = 0; //fade out any active text logs
document.getElementById("fade-out").style.opacity = 1; //slowly fades out
// build.shareURL(false)
- setTimeout(function() {
+ setTimeout(function () {
simulation.paused = true;
// simulation.clearMap();
// Matter.Composite.clear(composite, keepStatic, [deep = false])
@@ -365,7 +364,7 @@ const spawn = {
}
if (simulation.testing) {
unlockExit()
- setTimeout(function() {
+ setTimeout(function () {
simulation.makeTextLog(`level.levels.length = Infinite`);
}, 1500);
} else {
@@ -408,13 +407,13 @@ const spawn = {
}
}
};
- me.onDamage = function() {};
+ me.onDamage = function () { };
me.cycle = 420;
me.endCycle = 780;
me.totalCycles = 0
me.mode = 0;
- me.damageReduction = 0.25
- me.do = function() {
+ me.damageReduction = 0.25 //reset on each new mode
+ me.do = function () {
// this.armor();
// Matter.Body.setPosition(this, {
// x: x,
@@ -433,6 +432,7 @@ const spawn = {
if (this.cycle > this.endCycle) {
this.cycle = 0;
this.mode++
+ this.damageReduction = 0.25
if (this.mode > 2) {
this.mode = 0;
this.fill = "#50f";
@@ -477,14 +477,14 @@ const spawn = {
}
// }
};
- me.modeDo = function() {}
- me.modeAll = function() {
+ me.modeDo = function () { }
+ me.modeAll = function () {
this.modeSpawns()
this.modeSuck()
this.modeLasers()
}
me.spawnInterval = 395
- me.modeSpawns = function() {
+ me.modeSpawns = function () {
if (!(this.cycle % this.spawnInterval) && !m.isBodiesAsleep && mob.length < 40) {
if (this.mode !== 3) Matter.Body.setAngularVelocity(this, 0.1)
//fire a bullet from each vertex
@@ -508,7 +508,22 @@ const spawn = {
}
me.eventHorizon = 1300
me.eventHorizonCycleRate = 4 * Math.PI / me.endCycle
- me.modeSuck = function() {
+ me.modeSuck = function () {
+ if (!(this.cycle % 60)) {
+ const index = Math.floor((this.cycle % 360) / 60)
+ spawn.seeker(this.vertices[index].x, this.vertices[index].y, 20 * (0.5 + Math.random()), 9); //give the bullet a rotational velocity as if they were attached to a vertex
+ const who = mob[mob.length - 1]
+ Matter.Body.setDensity(who, 0.00003); //normal is 0.001
+ who.timeLeft = 760 //* (0.8 + 0.4 * Math.random());
+ who.accelMag = 0.0003 * simulation.accelScale; //* (0.8 + 0.4 * Math.random())
+ who.frictionAir = 0.01 //* (0.8 + 0.4 * Math.random());
+ const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[index]))), -7)
+ Matter.Body.setVelocity(who, {
+ x: this.velocity.x + velocity.x,
+ y: this.velocity.y + velocity.y
+ });
+ }
+
//eventHorizon waves in and out
const eventHorizon = this.eventHorizon * (1 - 0.25 * Math.cos(simulation.cycle * this.eventHorizonCycleRate)) //0.014
//draw darkness
@@ -557,8 +572,8 @@ const spawn = {
}
me.rotateVelocity = 0.0025
me.rotateCount = 0;
- me.lasers = function(where, angle, dmg = 0.14 * simulation.dmgScale) {
- const vertexCollision = function(v1, v1End, domain) {
+ me.lasers = function (where, angle, dmg = 0.14 * simulation.dmgScale) {
+ const vertexCollision = function (v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices;
const len = vertices.length - 1;
@@ -628,7 +643,7 @@ const spawn = {
ctx.moveTo(where.x, where.y);
ctx.lineTo(best.x, best.y);
}
- me.modeLasers = function() {
+ me.modeLasers = function () {
if (!m.isBodiesAsleep && !this.isStunned) {
let slowed = false //check if slowed
for (let i = 0; i < this.status.length; i++) {
@@ -660,7 +675,7 @@ const spawn = {
ctx.stroke(); // Draw it
ctx.setLineDash([]);
ctx.lineWidth = 20;
- ctx.strokeStyle = `rgba(80,0,255,${0.07*scale})`;
+ ctx.strokeStyle = `rgba(80,0,255,${0.07 * scale})`;
ctx.stroke(); // Draw it
} else {
ctx.beginPath();
@@ -690,7 +705,7 @@ const spawn = {
// me.memory = 120;
me.seeAtDistance2 = 2000000 //1400 vision range
Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback
- me.do = function() {
+ me.do = function () {
this.seePlayerByLookingAt();
this.attraction();
this.repulsion();
@@ -715,7 +730,7 @@ const spawn = {
me.isGrouper = true;
me.seeAtDistance2 = 600 * 600
me.seePlayerFreq = Math.floor(50 + 50 * Math.random())
- me.do = function() {
+ me.do = function () {
this.gravity();
this.checkStatus();
this.seePlayerCheck();
@@ -755,7 +770,7 @@ const spawn = {
me.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); //extra reduction for a boss, because normal density
me.frictionAir = 0.01;
me.accelMag = 0.0002;
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y);
for (const who of mob) {
if (who.isNecroMob) { //blockMobs leave their body, and die
@@ -765,7 +780,7 @@ const spawn = {
}
}
me.target = player; // the target to lock on. Usually a block, but will be the player under certain conditions
- me.do = function() {
+ me.do = function () {
this.checkStatus();
this.seePlayerCheck();
if (this.target) { //(this.target === player && this.seePlayer.yes) || this.target !== player
@@ -875,7 +890,7 @@ const spawn = {
me.isDropPowerUp = false;
// me.showHealthBar = false;
me.cycle = 0
- me.do = function() { //grow phase only occurs for growCycles
+ me.do = function () { //grow phase only occurs for growCycles
this.checkStatus();
this.seePlayerCheck();
@@ -891,7 +906,7 @@ const spawn = {
}
}
}
- me.normalDo = function() {
+ me.normalDo = function () {
this.gravity();
this.checkStatus();
this.seePlayerCheck();
@@ -921,21 +936,21 @@ const spawn = {
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body | cat.map
Matter.Body.setDensity(me, 0.00035) // normal density is 0.001 // this reduces life by half and decreases knockback
const k = 642 //k=r^2/m
- me.split = function() {
+ me.split = function () {
Matter.Body.scale(this, 0.45, 0.45);
this.radius = Math.sqrt(this.mass * k / Math.PI)
spawn.cellBoss(this.position.x, this.position.y, this.radius, this.cellID);
mob[mob.length - 1].health = this.health
}
- me.onHit = function() { //run this function on hitting player
+ me.onHit = function () { //run this function on hitting player
this.health = 1;
this.split();
};
- me.onDamage = function(dmg) {
+ me.onDamage = function (dmg) {
if (Math.random() < 0.34 * dmg * Math.sqrt(this.mass) && this.health > dmg) this.split();
}
me.damageReduction = 0.17 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); //me.damageReductionGoal
- me.do = function() {
+ me.do = function () {
// // this.armor();
if (!m.isBodiesAsleep) {
this.seePlayerByDistOrLOS();
@@ -964,7 +979,7 @@ const spawn = {
}
}
};
- me.onDeath = function() {
+ me.onDeath = function () {
this.isCell = false;
let count = 0 //count other cells by id
// console.log(this.cellID)
@@ -1004,11 +1019,11 @@ const spawn = {
Matter.Body.setAngularVelocity(me, 0.12 * (Math.random() - 0.5))
// spawn.shield(me, x, y, 1);
- me.onHit = function() { //run this function on hitting player
+ me.onHit = function () { //run this function on hitting player
this.explode();
};
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1);
- me.doAwake = function() {
+ me.doAwake = function () {
if (!m.isBodiesAsleep) {
// this.armor();
this.alwaysSeePlayer();
@@ -1032,7 +1047,7 @@ const spawn = {
}
}
}
- me.do = function() {
+ me.do = function () {
this.checkStatus();
if (this.seePlayer.recall) {
this.do = this.doAwake
@@ -1042,7 +1057,7 @@ const spawn = {
}
}
};
- me.onDeath = function() {
+ me.onDeath = function () {
this.isSpawnBoss = false;
let count = 0 //count other cells by id
// console.log(this.spawnID)
@@ -1097,18 +1112,18 @@ const spawn = {
me.buffCount = 0
me.accelMag = 0.00005 //* simulation.accelScale;
- me.setBuffed = function() {
+ me.setBuffed = function () {
this.buffCount++
this.accelMag += 0.000035 //* Math.sqrt(simulation.accelScale)
// Matter.Body.setDensity(this, 0.001 + 0.0003 * this.buffCount) // normal density is 0.001 //+ 0.0005 * Math.sqrt(simulation.difficulty)
- this.fill = `hsl(144, ${5+10*this.buffCount}%, 50%)`
+ this.fill = `hsl(144, ${5 + 10 * this.buffCount}%, 50%)`
const scale = 1.132;
Matter.Body.scale(this, scale, scale);
this.radius *= scale;
// this.health += 0.03
// if (this.health > 1) this.health = 1
}
- me.onDeath = function() {
+ me.onDeath = function () {
this.isBuffBoss = false;
let count = 0 //count other cells by id
for (let i = 0, len = mob.length; i < len; i++) {
@@ -1126,7 +1141,7 @@ const spawn = {
}
}
me.damageReduction = 0.18 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.alwaysSeePlayer();
this.checkStatus();
@@ -1169,12 +1184,12 @@ const spawn = {
} else if (!m.isCloak) {
me.foundPlayer();
}
- me.onHit = function() { //run this function on hitting player
+ me.onHit = function () { //run this function on hitting player
powerUps.ejectTech()
powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "ammo");
powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "research");
};
- me.onDeath = function() {
+ me.onDeath = function () {
this.leaveBody = false;
if (vertices > 3) {
this.isDropPowerUp = false;
@@ -1187,9 +1202,9 @@ const spawn = {
for (let i = 0; i < powerUp.length; i++) powerUp[i].collisionFilter.mask = cat.map | cat.powerUp
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
- this.stroke = `hsl(0,0%,${80+25*Math.sin(simulation.cycle*0.01)}%)`
+ this.stroke = `hsl(0,0%,${80 + 25 * Math.sin(simulation.cycle * 0.01)}%)`
//steal all power ups
for (let i = 0; i < Math.min(powerUp.length, this.vertices.length); i++) {
@@ -1233,7 +1248,7 @@ const spawn = {
// me.onDeath = function () { //helps collisions functions work better after vertex have been changed
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices))
// }
- me.do = function() {
+ me.do = function () {
this.seePlayerByLookingAt();
this.checkStatus();
this.attraction();
@@ -1281,14 +1296,14 @@ const spawn = {
Composite.add(engine.world, cons[cons.length - 1]);
cons[len2].length = 100 + 1.5 * radius;
me.cons2 = cons[len2];
- me.do = function() {
+ me.do = function () {
this.gravity();
this.searchSpring();
this.checkStatus();
this.springAttack();
};
- me.onDeath = function() {
+ me.onDeath = function () {
this.removeCons();
};
spawn.shield(me, x, y);
@@ -1306,7 +1321,7 @@ const spawn = {
me.randomHopFrequency = 200 + Math.floor(Math.random() * 150);
me.randomHopCD = simulation.cycle + me.randomHopFrequency;
spawn.shield(me, x, y);
- me.do = function() {
+ me.do = function () {
this.gravity();
this.seePlayerCheck();
this.checkStatus();
@@ -1351,12 +1366,12 @@ const spawn = {
Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger
spawn.shield(me, x, y, 1);
spawn.spawnOrbitals(me, radius + 60, 1)
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
me.lastSpeed = me.speed
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.gravity();
this.seePlayerCheck();
@@ -1439,7 +1454,7 @@ const spawn = {
me.lookTorque = 0.0000014;
me.restitution = 0;
spawn.shield(me, x, y);
- me.look = function() {
+ me.look = function () {
this.seePlayerByLookingAt();
this.checkStatus();
if (this.seePlayer.recall && this.cd < simulation.cycle) {
@@ -1449,7 +1464,7 @@ const spawn = {
}
}
me.do = me.look
- me.spin = function() {
+ me.spin = function () {
this.checkStatus();
this.torque += 0.000035 * this.inertia;
this.fill = randomColor({
@@ -1486,7 +1501,7 @@ const spawn = {
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body
me.memory = Infinity;
Matter.Body.setDensity(me, 0.008); //extra dense //normal is 0.001 //makes effective life much larger
- me.do = function() {
+ me.do = function () {
//keep it slow, to stop issues from explosion knock backs
if (this.speed > 5) {
Matter.Body.setVelocity(this, {
@@ -1565,7 +1580,7 @@ const spawn = {
// me.frictionAir = 0.005;
me.memory = 1600;
Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger
- me.onDeath = function() {
+ me.onDeath = function () {
//applying forces to player doesn't seem to work inside this method, not sure why
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
if (simulation.difficulty > 5) {
@@ -1583,12 +1598,11 @@ const spawn = {
}
toMe(body, this.position, this.eventHorizon)
toMe(mob, this.position, this.eventHorizon)
- // toMe(bullet, this.position, this.eventHorizon)
+ // toMe(bullet, this.position, this.eventHorizon))
}
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
- // this.armor();
+ me.do = function () {
//keep it slow, to stop issues from explosion knock backs
if (this.speed > 1) {
Matter.Body.setVelocity(this, {
@@ -1606,6 +1620,21 @@ const spawn = {
}
this.checkStatus();
if (this.seePlayer.recall) {
+ //throw large seekers
+ if (!(simulation.cycle % 240) && !m.isBodiesAsleep) {
+ spawn.seeker(this.position.x, this.position.y, 15 * (0.7 + 0.5 * Math.random()), 7); //give the bullet a rotational velocity as if they were attached to a vertex
+ const who = mob[mob.length - 1]
+ Matter.Body.setDensity(who, 0.00001); //normal is 0.001
+ who.timeLeft = 600
+ who.accelMag = 0.0002 * simulation.accelScale; //* (0.8 + 0.4 * Math.random())
+ who.frictionAir = 0.01 //* (0.
+ const velocity = Vector.mult(Vector.normalise(Vector.sub(m.pos, this.position)), -20); //set direction to turn to fire //Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[index]))), -35)
+ Matter.Body.setVelocity(who, {
+ x: this.velocity.x + velocity.x,
+ y: this.velocity.y + velocity.y
+ });
+ }
+
//accelerate towards the player
const forceMag = this.accelMag * this.mass;
const dx = this.seePlayer.position.x - this.position.x
@@ -1711,7 +1740,7 @@ const spawn = {
cons[len2].length = 100 + 1.5 * radius;
me.cons2 = cons[len2];
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) //normal is 1, most bosses have 0.25
- me.do = function() {
+ me.do = function () {
// this.armor();
this.gravity();
this.searchSpring();
@@ -1719,7 +1748,7 @@ const spawn = {
this.springAttack();
};
- me.onDeath = function() {
+ me.onDeath = function () {
this.removeCons();
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
@@ -1845,7 +1874,7 @@ const spawn = {
me.frictionStatic = 0;
me.friction = 0;
spawn.shield(me, x, y);
- me.do = function() {
+ me.do = function () {
this.seePlayerByLookingAt();
this.checkStatus();
this.attraction();
@@ -1871,11 +1900,11 @@ const spawn = {
me.stroke = "transparent"; //used for drawGhost
me.collisionFilter.mask = cat.bullet | cat.body
me.memory = Infinity
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
me.damageReduction = 0.35 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) // me.damageReductionGoal
- me.awake = function() {
+ me.awake = function () {
// this.armor();
this.checkStatus();
//health bar needs to be here because the position is being set
@@ -1950,7 +1979,7 @@ const spawn = {
Matter.Body.setPosition(this, { x: history.position.x, y: history.position.y - history.yOff + 24.2859 }) //bullets move with player
}
}
- me.do = function() {
+ me.do = function () {
if (this.seePlayer.recall || (!(simulation.cycle % this.seePlayerFreq) && this.distanceToPlayer2() < this.seeAtDistance2 && !m.isCloak)) {
setTimeout(() => {
this.do = this.awake
@@ -1973,11 +2002,11 @@ const spawn = {
me.accelMag = 0.00009 * simulation.accelScale;
me.frictionStatic = 0;
me.friction = 0;
- me.onDamage = function() {
+ me.onDamage = function () {
this.laserPos = this.position;
};
spawn.shield(me, x, y);
- me.do = function() {
+ me.do = function () {
if (!m.isBodiesAsleep) {
this.seePlayerByLookingAt();
this.checkStatus();
@@ -2018,7 +2047,7 @@ const spawn = {
sub = Vector.normalise(Vector.sub(laserOffL, this.position));
laserOffL = Vector.add(laserOffL, Vector.mult(sub, rangeWidth));
ctx.lineTo(laserOffL.x, laserOffL.y);
- ctx.fillStyle = `rgba(0,0,255,${Math.max(0,0.3*r/targetDist)})`
+ ctx.fillStyle = `rgba(0,0,255,${Math.max(0, 0.3 * r / targetDist)})`
ctx.fill();
}
} else {
@@ -2046,16 +2075,16 @@ const spawn = {
Matter.Body.setDensity(me, 0.008); //extra dense //normal is 0.001 //makes effective life much larger
spawn.shield(me, x, y, 1);
spawn.spawnOrbitals(me, radius + 200 + 300 * Math.random())
- me.onHit = function() {
+ me.onHit = function () {
//run this function on hitting player
// this.explode();
};
// spawn.shield(me, x, y, 1); //not working, not sure why
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.seePlayerByLookingAt();
this.checkStatus();
@@ -2083,7 +2112,7 @@ const spawn = {
// this.force.y += mag * Math.sin(this.angle)
// }
- const vertexCollision = function(v1, v1End, domain) {
+ const vertexCollision = function (v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices;
const len = vertices.length - 1;
@@ -2186,14 +2215,14 @@ const spawn = {
Matter.Body.setDensity(me, 0.01); //extra dense //normal is 0.001 //makes effective life much larger
spawn.shield(me, x, y, 1);
spawn.spawnOrbitals(me, radius + 200 + 300 * Math.random())
- me.onHit = function() {};
- me.onDeath = function() {
+ me.onHit = function () { };
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.targetingCount = 0;
me.targetingTime = 60 - Math.min(58, 3 * simulation.difficulty)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.seePlayerByLookingAt();
this.checkStatus();
@@ -2212,7 +2241,7 @@ const spawn = {
} else if (c < -threshold) {
this.torque -= 0.000004 * this.inertia;
}
- const vertexCollision = function(v1, v1End, domain) {
+ const vertexCollision = function (v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices;
const len = vertices.length - 1;
@@ -2337,10 +2366,10 @@ const spawn = {
me.delay = 30 + 35 * simulation.CDScale;
me.nextBlinkCycle = me.delay;
spawn.shield(me, x, y, 1);
- me.onDamage = function() {
+ me.onDamage = function () {
// this.cd = simulation.cycle + this.delay;
};
- me.onDeath = function() {
+ me.onDeath = function () {
const offAngle = Math.PI * Math.random()
for (let i = 0, len = 3; i < len; i++) {
spawn.grenade(this.position.x, this.position.y, this.grenadeDelay);
@@ -2355,7 +2384,7 @@ const spawn = {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
}
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.seePlayerByHistory()
if (this.nextBlinkCycle < simulation.cycle && this.seePlayer.yes) { //teleport towards the player
@@ -2413,15 +2442,15 @@ const spawn = {
spawn.shield(me, x, y, 1);
spawn.spawnOrbitals(me, radius + 200 + 300 * Math.random(), 1)
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
- me.onHit = function() {};
- me.do = function() {
+ me.onHit = function () { };
+ me.do = function () {
if (player.speed > 5) this.do = this.fire //don't attack until player moves
}
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.fire = function() {
+ me.fire = function () {
// this.armor();
this.checkStatus();
if (!m.isBodiesAsleep) {
@@ -2521,8 +2550,8 @@ const spawn = {
me.pulseRadius = Math.min(400, 170 + simulation.difficulty * 3)
me.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5)
me.isFiring = false
- me.onHit = function() {};
- me.canSeeTarget = function() {
+ me.onHit = function () { };
+ me.canSeeTarget = function () {
const angle = this.angle + Math.PI / 2;
const dot = Vector.dot({
x: Math.cos(angle),
@@ -2540,7 +2569,7 @@ const spawn = {
return true
}
}
- me.do = function() {
+ me.do = function () {
this.seePlayerByLookingAt();
this.checkStatus();
if (!m.isBodiesAsleep) {
@@ -2636,11 +2665,11 @@ const spawn = {
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
me.accelMag = 0.0001 * simulation.accelScale;
- me.onHit = function() {
+ me.onHit = function () {
//run this function on hitting player
this.explode();
};
- me.do = function() {
+ me.do = function () {
this.seePlayerByLookingAt();
this.checkStatus();
this.attraction();
@@ -2679,12 +2708,12 @@ const spawn = {
me.isBoss = true;
// spawn.shield(me, x, y, 1); //not working, not sure why
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
me.rotateVelocity = Math.min(0.0045, 0.0015 * simulation.accelScale * simulation.accelScale) * (level.levelsCleared > 8 ? 1 : -1) * (simulation.isHorizontalFlipped ? -1 : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.fill = '#' + Math.random().toString(16).substr(-6); //flash colors
this.checkStatus();
@@ -2727,8 +2756,8 @@ const spawn = {
// Matter.Body.setPosition(this, this.startingPosition);
};
- me.lasers = function(where, angle) {
- const vertexCollision = function(v1, v1End, domain) {
+ me.lasers = function (where, angle) {
+ const vertexCollision = function (v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices;
const len = vertices.length - 1;
@@ -2816,7 +2845,7 @@ const spawn = {
Matter.Body.rotate(me, Math.PI * 0.1);
spawn.shield(me, x, y);
// me.onDamage = function () {};
- me.onDeath = function() {
+ me.onDeath = function () {
if (this.spikeLength > 4) {
this.spikeLength = 4
const spike = Vector.mult(Vector.normalise(Vector.sub(this.vertices[this.spikeVertex], this.position)), this.radius * this.spikeLength)
@@ -2825,7 +2854,7 @@ const spawn = {
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices))
}
};
- me.do = function() {
+ me.do = function () {
if (!m.isBodiesAsleep) {
// this.gravity();
this.seePlayerByLookingAt();
@@ -2891,10 +2920,10 @@ const spawn = {
me.cd = Infinity;
Matter.Body.rotate(me, Math.PI * 0.1);
spawn.shield(me, x, y);
- me.onDamage = function() {
+ me.onDamage = function () {
this.cd = simulation.cycle + this.delay;
};
- me.do = function() {
+ me.do = function () {
this.gravity();
if (!(simulation.cycle % this.seePlayerFreq)) { // this.seePlayerCheck(); from mobs
if (
@@ -2951,11 +2980,11 @@ const spawn = {
Matter.Body.setDensity(me, 0.005); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.11 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isBoss = true;
- me.onDamage = function() {};
- me.onDeath = function() {
+ me.onDamage = function () { };
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
- me.do = function() {
+ me.do = function () {
this.checkStatus();
this.seePlayerByHistory(60);
this.attraction();
@@ -2968,8 +2997,8 @@ const spawn = {
if (long > 0) this.laserSword(this.vertices[i], bend + this.angle + (i + 0.5) / sides * 2 * Math.PI, Math.abs(long));
}
};
- me.laserSword = function(where, angle, length) {
- const vertexCollision = function(v1, v1End, domain) {
+ me.laserSword = function (where, angle, length) {
+ const vertexCollision = function (v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices;
const len = vertices.length - 1;
@@ -3042,14 +3071,14 @@ const spawn = {
me.laserAngle = 3 * Math.PI / 5
const seeDistance2 = 200000
spawn.shield(me, x, y);
- me.onDamage = function() {};
- me.do = function() {
+ me.onDamage = function () { };
+ me.do = function () {
this.checkStatus();
this.seePlayerByHistory(15);
this.attraction();
if (!m.isBodiesAsleep) this.sword() //does various things depending on what stage of the sword swing
};
- me.swordWaiting = function() {
+ me.swordWaiting = function () {
if (
this.seePlayer.recall &&
this.cd < simulation.cycle &&
@@ -3074,7 +3103,7 @@ const spawn = {
}
}
me.sword = me.swordWaiting //base function that changes during different aspects of the sword swing
- me.swordGrow = function() {
+ me.swordGrow = function () {
this.laserSword(this.vertices[this.swordVertex], this.angle + this.laserAngle);
this.swordRadius += this.swordRadiusGrowRate
if (this.swordRadius > this.swordRadiusMax) {
@@ -3082,7 +3111,7 @@ const spawn = {
this.spinCount = 0
}
}
- me.swordSlash = function() {
+ me.swordSlash = function () {
this.laserSword(this.vertices[this.swordVertex], this.angle + this.laserAngle);
this.torque += this.torqueMagnitude;
this.spinCount++
@@ -3093,8 +3122,8 @@ const spawn = {
this.cd = simulation.cycle + this.delay;
}
}
- me.laserSword = function(where, angle) {
- const vertexCollision = function(v1, v1End, domain) {
+ me.laserSword = function (where, angle) {
+ const vertexCollision = function (v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) {
let v = domain[i].vertices;
const len = v.length - 1;
@@ -3160,7 +3189,7 @@ const spawn = {
me.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player
me.showHealthBar = false;
me.memory = 240;
- me.do = function() {
+ me.do = function () {
this.gravity();
this.seePlayerByHistory(15);
this.checkStatus();
@@ -3211,7 +3240,7 @@ const spawn = {
me.collisionFilter.mask = cat.bullet //| cat.body
me.showHealthBar = false;
me.memory = 480;
- me.do = function() {
+ me.do = function () {
//cap max speed
if (this.speed > 5) {
Matter.Body.setVelocity(this, {
@@ -3330,11 +3359,11 @@ const spawn = {
radiusOrbitals = radius + 125 + 350 * Math.random()
for (let i = 0; i < len; i++) spawn.orbital(me, radiusOrbitals, i / len * 2 * Math.PI, -speed)
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.seePlayerCheckByDistance();
this.checkStatus();
@@ -3366,11 +3395,11 @@ const spawn = {
x: 0,
y: 0
};
- me.onDeath = function() { //helps collisions functions work better after vertex have been changed
+ me.onDeath = function () { //helps collisions functions work better after vertex have been changed
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices))
}
// spawn.shield(me, x, y);
- me.do = function() {
+ me.do = function () {
this.seePlayerByLookingAt();
this.checkStatus();
this.fire();
@@ -3416,13 +3445,13 @@ const spawn = {
spawn.spawnOrbitals(me, radius + 75, 1);
}, 100); //have to wait a sec so the tether constraint doesn't attach to an orbital
Matter.Body.setDensity(me, 0.008 + 0.0003 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //helps collisions functions work better after vertex have been changed
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.seePlayerByLookingAt();
this.checkStatus();
@@ -3438,7 +3467,7 @@ const spawn = {
mobs.spawn(x, y, sides, radius, "rgb(255,0,0)");
let me = mob[mob.length - 1];
me.stroke = "transparent";
- me.onHit = function() {
+ me.onHit = function () {
this.explode(this.mass * 20);
};
Matter.Body.setDensity(me, 0.00004); //normal is 0.001
@@ -3453,7 +3482,7 @@ const spawn = {
me.showHealthBar = false;
me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
- me.do = function() {
+ me.do = function () {
this.gravity();
this.timeLimit();
};
@@ -3462,10 +3491,10 @@ const spawn = {
mobs.spawn(x, y, sides, radius, "rgb(255,0,0)");
let me = mob[mob.length - 1];
me.stroke = "transparent";
- me.onHit = function() {
+ me.onHit = function () {
this.explode(this.mass * 120);
};
- me.onDeath = function() {
+ me.onDeath = function () {
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);
@@ -3505,7 +3534,7 @@ const spawn = {
me.showHealthBar = false;
me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
- me.do = function() {
+ me.do = function () {
this.gravity();
this.timeLimit();
};
@@ -3535,11 +3564,11 @@ const spawn = {
x: 0,
y: 0
};
- me.onDeath = function() { //helps collisions functions work better after vertex have been changed
+ me.onDeath = function () { //helps collisions functions work better after vertex have been changed
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices))
}
// spawn.shield(me, x, y);
- me.do = function() {
+ me.do = function () {
// this.seePlayerByLookingAt();
this.seePlayerCheck();
this.checkStatus();
@@ -3630,7 +3659,7 @@ const spawn = {
mobs.spawn(x, y, sides, radius, "rgb(255,0,155)");
let me = mob[mob.length - 1];
me.stroke = "transparent";
- me.onHit = function() {
+ me.onHit = function () {
this.explode(this.mass * 20);
};
Matter.Body.setDensity(me, 0.00005); //normal is 0.001
@@ -3645,7 +3674,7 @@ const spawn = {
me.showHealthBar = false;
me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
- me.do = function() {
+ me.do = function () {
// this.gravity();
this.timeLimit();
if (Matter.Query.collides(this, map).length > 0 || Matter.Query.collides(this, body).length > 0 && this.speed < 3) {
@@ -3654,6 +3683,36 @@ const spawn = {
}
};
},
+ launcherOne(x, y, radius = 30 + Math.ceil(Math.random() * 40)) {
+ mobs.spawn(x, y, 3, radius, "rgb(150,150,255)");
+ let me = mob[mob.length - 1];
+ me.accelMag = 0.00004 * simulation.accelScale;
+ me.fireFreq = Math.floor(420 + 90 * Math.random() * simulation.CDScale)
+ me.frictionStatic = 0;
+ me.friction = 0;
+ me.frictionAir = 0.015;
+ spawn.shield(me, x, y);
+ me.onDamage = function () { };
+ me.do = function () {
+ this.seePlayerCheck();
+ this.checkStatus();
+ this.attraction();
+ if (this.seePlayer.recall && !(simulation.cycle % this.fireFreq) && !m.isBodiesAsleep) {
+ Matter.Body.setAngularVelocity(this, 0.14)
+ spawn.seeker(this.vertices[0].x, this.vertices[0].y, 20, 9); //give the bullet a rotational velocity as if they were attached to a vertex
+ const who = mob[mob.length - 1]
+ Matter.Body.setDensity(who, 0.00003); //normal is 0.001
+ who.timeLeft = 840 //* (0.8 + 0.4 * Math.random());
+ who.accelMag = 0.00035 * simulation.accelScale; //* (0.8 + 0.4 * Math.random())
+ who.frictionAir = 0.01 //* (0.8 + 0.4 * Math.random());
+ const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[0]))), -6)
+ Matter.Body.setVelocity(who, {
+ x: this.velocity.x + velocity.x,
+ y: this.velocity.y + velocity.y
+ });
+ }
+ };
+ },
launcher(x, y, radius = 30 + Math.ceil(Math.random() * 40)) {
mobs.spawn(x, y, 3, radius, "rgb(150,150,255)");
let me = mob[mob.length - 1];
@@ -3663,8 +3722,8 @@ const spawn = {
me.friction = 0;
me.frictionAir = 0.02;
spawn.shield(me, x, y);
- me.onDamage = function() {};
- me.do = function() {
+ me.onDamage = function () { };
+ me.do = function () {
this.seePlayerCheck();
this.checkStatus();
this.attraction();
@@ -3699,13 +3758,13 @@ const spawn = {
spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random())
Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //helps collisions functions work better after vertex have been changed
};
- me.onDamage = function() {};
+ me.onDamage = function () { };
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.seePlayerCheck();
this.checkStatus();
@@ -3743,7 +3802,7 @@ const spawn = {
spawn.spawnOrbitals(me, radius + 125, 1);
spawn.spawnOrbitals(me, radius + 200, 1);
Matter.Body.setDensity(me, 0.004 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
- me.onDeath = function() { //helps collisions functions work better after vertex have been changed
+ me.onDeath = function () { //helps collisions functions work better after vertex have been changed
for (let i = 0; i < 6; i++) {
spawn.grenade(this.position.x, this.position.y, 75 * simulation.CDScale);
const who = mob[mob.length - 1]
@@ -3757,7 +3816,7 @@ const spawn = {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
}
me.grenadeLimiter = 0
- me.onDamage = function() {
+ me.onDamage = function () {
if (this.grenadeLimiter < 240) {
this.grenadeLimiter += 60
spawn.grenade(this.position.x, this.position.y, 80 + Math.floor(60 * Math.random()));
@@ -3770,7 +3829,7 @@ const spawn = {
}
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
if (this.grenadeLimiter > 1) this.grenadeLimiter--
this.seePlayerCheck();
@@ -3798,13 +3857,13 @@ const spawn = {
x: 0,
y: 0
};
- me.onDeath = function() { //helps collisions functions work better after vertex have been changed
+ me.onDeath = function () { //helps collisions functions work better after vertex have been changed
spawn.grenade(this.position.x, this.position.y, 75 * simulation.CDScale);
// mob[mob.length - 1].collisionFilter.category = 0
mob[mob.length - 1].collisionFilter.mask = cat.player | cat.map;
}
// spawn.shield(me, x, y);
- me.do = function() {
+ me.do = function () {
this.seePlayerCheck();
this.checkStatus();
@@ -3860,7 +3919,7 @@ const spawn = {
mobs.spawn(x, y, 4, size, "rgb(215,0,190)"); //rgb(215,80,190)
let me = mob[mob.length - 1];
me.stroke = "transparent";
- me.onHit = function() {
+ me.onHit = function () {
this.explode(this.mass * 20);
};
Matter.Body.setDensity(me, 0.00004); //normal is 0.001
@@ -3874,7 +3933,7 @@ const spawn = {
me.isDropPowerUp = false;
me.isBadTarget = true;
me.isMobBullet = true;
- me.onDeath = function() {
+ me.onDeath = function () {
//damage player if in range
if (Vector.magnitude(Vector.sub(player.position, this.position)) < pulseRadius && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
@@ -3892,7 +3951,7 @@ const spawn = {
me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.map | cat.body | cat.player
// me.collisionFilter.mask = 0
- me.do = function() {
+ me.do = function () {
this.timeLimit();
ctx.beginPath(); //draw explosion outline
ctx.arc(this.position.x, this.position.y, pulseRadius * (1.01 - this.timeLeft / this.lifeSpan), 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay
@@ -3929,15 +3988,15 @@ const spawn = {
spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random())
Matter.Body.setDensity(me, 0.0045); //extra dense //normal is 0.001 //makes effective life much larger
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //helps collisions functions work better after vertex have been changed
};
- me.onDamage = function() {
+ me.onDamage = function () {
this.cycle = 0
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.checkStatus();
ctx.beginPath(); //draw cycle timer
@@ -3991,13 +4050,13 @@ const spawn = {
spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random())
Matter.Body.setDensity(me, 0.01); //extra dense //normal is 0.001 //makes effective life much larger
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //helps collisions functions work better after vertex have been changed
};
- me.onDamage = function() {};
+ me.onDamage = function () { };
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.seePlayerCheck();
this.checkStatus();
@@ -4057,7 +4116,7 @@ const spawn = {
mobs.spawn(x, y, sides, radius, "rgb(255,0,255)");
let me = mob[mob.length - 1];
me.stroke = "transparent";
- me.onHit = function() {
+ me.onHit = function () {
this.explode(this.mass * 20);
};
Matter.Body.setDensity(me, 0.000015); //normal is 0.001
@@ -4072,7 +4131,7 @@ const spawn = {
me.showHealthBar = false;
me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
- me.do = function() {
+ me.do = function () {
// this.seePlayer.yes = false;
this.alwaysSeePlayer()
this.attraction();
@@ -4085,7 +4144,7 @@ const spawn = {
me.g = 0.0004; //required if using this.gravity
me.leaveBody = false;
// me.isDropPowerUp = false;
- me.onDeath = function() { //run this function on death
+ me.onDeath = function () { //run this function on death
for (let i = 0; i < Math.ceil(this.mass * 0.15 + Math.random() * 2.5); ++i) {
spawn.spawns(this.position.x + (Math.random() - 0.5) * radius * 2.5, this.position.y + (Math.random() - 0.5) * radius * 2.5);
Matter.Body.setVelocity(mob[mob.length - 1], {
@@ -4095,7 +4154,7 @@ const spawn = {
}
};
spawn.shield(me, x, y);
- me.do = function() {
+ me.do = function () {
this.gravity();
this.seePlayerCheck();
this.checkStatus();
@@ -4105,7 +4164,7 @@ const spawn = {
spawns(x, y, radius = 15) {
mobs.spawn(x, y, 4, radius, "rgb(255,0,0)");
let me = mob[mob.length - 1];
- me.onHit = function() { //run this function on hitting player
+ me.onHit = function () { //run this function on hitting player
this.explode();
};
// me.stroke = "transparent"
@@ -4119,7 +4178,7 @@ const spawn = {
me.leaveBody = false;
me.seePlayerFreq = Math.floor((80 + 50 * Math.random()));
me.frictionAir = 0.004;
- me.do = function() {
+ me.do = function () {
this.gravity();
this.seePlayerCheck();
this.checkStatus();
@@ -4176,12 +4235,12 @@ const spawn = {
exploder(x, y, radius = 40 + Math.ceil(Math.random() * 50)) {
mobs.spawn(x, y, 4, radius, "rgb(255,0,0)");
let me = mob[mob.length - 1];
- me.onHit = function() {
+ me.onHit = function () {
//run this function on hitting player
this.explode();
};
me.g = 0.0004; //required if using this.gravity
- me.do = function() {
+ me.do = function () {
this.gravity();
this.seePlayerCheck();
this.checkStatus();
@@ -4201,7 +4260,7 @@ const spawn = {
me.memory = 250;
me.laserRange = 500;
Matter.Body.setDensity(me, 0.0022 + 0.00022 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
for (let i = 0; i < mob.length; i++) { //wake up tail mobs
if (mob[i].isSnakeTail && mob[i].alive) {
@@ -4216,7 +4275,7 @@ const spawn = {
// me.closestVertex2 = 1;
me.cycle = 0
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.seePlayerByHistory()
this.checkStatus();
@@ -4319,7 +4378,7 @@ const spawn = {
me.memory = 250;
me.laserRange = 500;
Matter.Body.setDensity(me, 0.00165 + 0.00011 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
for (let i = 0; i < mob.length; i++) { //wake up tail mobs
if (mob[i].isSnakeTail && mob[i].alive) {
@@ -4330,7 +4389,7 @@ const spawn = {
}
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.seePlayerByHistory()
this.checkStatus();
@@ -4387,7 +4446,7 @@ const spawn = {
me.frictionAir = 0.02;
me.isSnakeTail = true;
me.stroke = "transparent"
- me.onDeath = function() {
+ me.onDeath = function () {
if (this.isSnakeTail) { //wake up tail mobs
for (let i = 0; i < mob.length; i++) {
if (mob[i].isSnakeTail && mob[i].alive) {
@@ -4398,10 +4457,10 @@ const spawn = {
}
}
};
- me.do = function() {
+ me.do = function () {
this.checkStatus();
};
- me.doActive = function() {
+ me.doActive = function () {
this.checkStatus();
this.alwaysSeePlayer();
this.attraction();
@@ -4431,12 +4490,12 @@ const spawn = {
spawn.shield(me, x, y, 1);
setTimeout(() => { spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random()) }, 100); //have to wait a sec so the tether constraint doesn't attach to an orbital
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
this.removeCons(); //remove constraint
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.gravity();
this.seePlayerCheck();
@@ -4464,10 +4523,10 @@ const spawn = {
});
Composite.add(engine.world, consBB[consBB.length - 1]);
- me.onDamage = function() {
+ me.onDamage = function () {
//make sure the mob that owns the shield can tell when damage is done
this.alertNearByMobs();
- this.fill = `rgba(220,220,255,${0.3 + 0.6 *this.health})`
+ this.fill = `rgba(220,220,255,${0.3 + 0.6 * this.health})`
};
me.leaveBody = false;
me.isDropPowerUp = false;
@@ -4475,13 +4534,13 @@ const spawn = {
me.shieldTargetID = target.id
target.isShielded = true;
- me.onDeath = function() {
+ me.onDeath = function () {
//clear isShielded status from target
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].id === this.shieldTargetID) mob[i].isShielded = false;
}
};
- me.do = function() {
+ me.do = function () {
this.checkStatus();
};
@@ -4514,11 +4573,11 @@ const spawn = {
});
Composite.add(engine.world, consBB[consBB.length - 1]);
}
- me.onDamage = function() {
+ me.onDamage = function () {
this.alertNearByMobs(); //makes sure the mob that owns the shield can tell when damage is done
- this.fill = `rgba(220,220,255,${0.3 + 0.6 *this.health})`
+ this.fill = `rgba(220,220,255,${0.3 + 0.6 * this.health})`
};
- me.onDeath = function() {
+ me.onDeath = function () {
//clear isShielded status from target
for (let j = 0; j < targets.length; j++) {
for (let i = 0, len = mob.length; i < len; i++) {
@@ -4531,7 +4590,7 @@ const spawn = {
me.showHealthBar = false;
mob[mob.length - 1] = mob[mob.length - 1 - nodes];
mob[mob.length - 1 - nodes] = me;
- me.do = function() {
+ me.do = function () {
this.checkStatus();
};
},
@@ -4558,7 +4617,7 @@ const spawn = {
// me.isShielded = true
me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.bullet; //cat.player | cat.map | cat.body
- me.do = function() {
+ me.do = function () {
//if host is gone
if (!who || !who.alive) {
this.death();
@@ -4617,11 +4676,11 @@ const spawn = {
for (let j = 0; j < nodes; j++) {
for (let i = 0, len = subNodes; i < len; i++) spawn.orbital(mob[orbitalIndexes[j]], range, i / len * 2 * Math.PI, speed)
}
- me.onDeath = function() {
+ me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- me.do = function() {
+ me.do = function () {
// this.armor();
this.seePlayerCheckByDistance();
this.checkStatus();
@@ -4786,7 +4845,7 @@ const spawn = {
me.isBadTarget = true;
me.isUnblockable = true;
- me.do = function() {
+ me.do = function () {
let wireX = -50;
let wireY = -1000;
if (this.freeOfWires) {
@@ -4855,7 +4914,7 @@ const spawn = {
me.isBadTarget = true;
me.isUnblockable = true;
- me.do = function() {
+ me.do = function () {
let wireX = -50 - 20;
let wireY = -1000;
@@ -4907,7 +4966,7 @@ const spawn = {
me.isBadTarget = true;
me.isUnblockable = true;
- me.do = function() {
+ me.do = function () {
let wireX = -50 - 35;
let wireY = -1000;
@@ -4958,7 +5017,7 @@ const spawn = {
me.isBadTarget = true;
me.isUnblockable = true;
- me.do = function() {
+ me.do = function () {
let wireX = -50 + 16;
let wireY = -1000;
@@ -5009,7 +5068,7 @@ const spawn = {
me.isBadTarget = true;
me.isUnblockable = true;
- me.do = function() {
+ me.do = function () {
let wireX = -50 + 26;
let wireY = -1000;
diff --git a/js/tech.js b/js/tech.js
index 8f23f10..89aa23d 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -1,46 +1,138 @@
- const tech = {
- totalCount: null,
- setupAllTech() {
+const tech = {
+ totalCount: null,
+ setupAllTech() {
+ for (let i = 0, len = tech.tech.length; i < len; i++) {
+ tech.tech[i].count = 0
+ tech.tech[i].isLost = false
+ tech.tech[i].remove();
+ if (tech.tech[i].isJunk) {
+ tech.tech[i].frequency = 0
+ } else if (tech.tech[i].frequencyDefault) {
+ tech.tech[i].frequency = tech.tech[i].frequencyDefault
+ } else {
+ tech.tech[i].frequency = 2
+ }
+ }
+ lore.techCount = 0;
+ if (simulation.isCheating) { //simulation.isCommunityMaps ||
for (let i = 0, len = tech.tech.length; i < len; i++) {
- tech.tech[i].count = 0
- tech.tech[i].isLost = false
- tech.tech[i].remove();
- if (tech.tech[i].isJunk) {
- tech.tech[i].frequency = 0
- } else if (tech.tech[i].frequencyDefault) {
- tech.tech[i].frequency = tech.tech[i].frequencyDefault
- } else {
- tech.tech[i].frequency = 2
+ if (tech.tech[i].isLore) {
+ tech.tech[i].frequency = 0;
+ tech.tech[i].count = 0;
}
}
- lore.techCount = 0;
- if (simulation.isCheating) { //simulation.isCommunityMaps ||
- for (let i = 0, len = tech.tech.length; i < len; i++) {
- if (tech.tech[i].isLore) {
- tech.tech[i].frequency = 0;
- tech.tech[i].count = 0;
- }
+ }
+ // tech.removeJunkTechFromPool();
+ // tech.removeLoreTechFromPool();
+ // tech.addLoreTechToPool();
+ tech.extraMaxHealth = 0;
+ tech.totalCount = 0;
+ simulation.updateTechHUD();
+ },
+ removeTech(index = 'random') {
+ if (index === 'random') {
+ const have = [] //find which tech you have
+ for (let i = 0; i < tech.tech.length; i++) {
+ if (tech.tech[i].count > 0 && !tech.tech[i].isNonRefundable) have.push(i)
+ }
+ if (have.length) {
+ index = have[Math.floor(Math.random() * have.length)]
+ } else {
+ return 0 //if none found don't remove any tech
+ }
+ } else if (isNaN(index)) { //find index by name
+ let found = false;
+ for (let i = 0; i < tech.tech.length; i++) {
+ if (index === tech.tech[i].name) {
+ index = i;
+ found = true;
+ break;
}
}
- // tech.removeJunkTechFromPool();
- // tech.removeLoreTechFromPool();
- // tech.addLoreTechToPool();
- tech.extraMaxHealth = 0;
- tech.totalCount = 0;
- simulation.updateTechHUD();
- },
- removeTech(index = 'random') {
- if (index === 'random') {
- const have = [] //find which tech you have
- for (let i = 0; i < tech.tech.length; i++) {
- if (tech.tech[i].count > 0 && !tech.tech[i].isNonRefundable) have.push(i)
+ if (!found) return 0 //if name not found don't remove any tech
+ }
+ if (tech.tech[index].count === 0) return 0
+ const totalRemoved = tech.tech[index].count
+ simulation.makeTextLog(`tech.removeTech("${tech.tech[index].name}")`)
+ tech.tech[index].remove();
+ tech.tech[index].count = 0;
+ simulation.updateTechHUD();
+ tech.tech[index].isLost = true
+ simulation.updateTechHUD();
+ return totalRemoved //return the total number of tech removed
+ },
+ // onclick="tech.removeTechPaused(${i}, this)" //add this to tech elements in pause menu
+ // removeTechPaused(index, who) {
+ // tech.tech[index].remove();
+ // tech.tech[index].count = 0;
+ // simulation.updateTechHUD();
+ // who.innerHTML = "removed"
+ // // who.style.display = "none"
+ // },
+ // removeLoreTechFromPool() {
+ // for (let i = tech.tech.length - 1; i > 0; i--) {
+ // if (tech.tech[i].isLore && tech.tech[i].count === 0) tech.tech.splice(i, 1)
+ // }
+ // },
+ addJunkTechToPool(chance) { //chance is number between 0-1
+ // { //count JUNK
+ // let count = 0
+ // for (let i = 0, len = tech.tech.length; i < len; i++) {
+ // if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && tech.tech[i].isJunk && tech.tech[i].frequency > 0) count += tech.tech[i].frequency
+ // }
+ // console.log(count)
+ // }
+ // { //count not JUNK
+ // let count = 0
+ // for (let i = 0, len = tech.tech.length; i < len; i++) {
+ // if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk && tech.tech[i].frequency > 0) count++
+ // }
+ // console.log(count)
+ // }
+ // count total non junk tech
+ let count = 0
+ for (let i = 0, len = tech.tech.length; i < len; i++) {
+ if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk) count += tech.tech[i].frequency
+ }
+ //make an array for possible junk tech to add
+ let options = [];
+ for (let i = 0; i < tech.tech.length; i++) {
+ if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].isJunk) options.push(i);
+ }
+ //add random array options to tech pool
+ if (options.length) {
+ const num = chance * count //scale number added
+ for (let i = 0; i < num; i++) tech.tech[options[Math.floor(Math.random() * options.length)]].frequency++
+ simulation.makeTextLog(`tech.tech.push(${num} JUNK)`)
+ return num
+ } else {
+ return 0
+ }
+ },
+ removeJunkTechFromPool(num = 1) {
+ for (let j = 0; j < num; j++) {
+ for (let i = 0; i < tech.tech.length; i++) {
+ if (tech.tech[i].isJunk && tech.tech[i].frequency > 0 && tech.tech[i].count < tech.tech[i].maxCount) {
+ tech.tech[i].frequency--
+ break
}
- if (have.length) {
- index = have[Math.floor(Math.random() * have.length)]
- } else {
- return 0 //if none found don't remove any tech
- }
- } else if (isNaN(index)) { //find index by name
+ }
+ }
+ },
+ giveTech(index = 'random') {
+ if (index === 'random') {
+ let options = [];
+ for (let i = 0; i < tech.tech.length; i++) {
+ if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk && !tech.tech[i].isLore && !tech.tech[i].isBadRandomOption) options.push(i);
+ }
+ // give a random tech from the tech I don't have
+ if (options.length > 0) {
+ let newTech = options[Math.floor(Math.random() * options.length)]
+ tech.giveTech(newTech)
+ simulation.makeTextLog(`tech.giveTech("${tech.tech[newTech].name}") //random tech`);
+ }
+ } else {
+ if (isNaN(index)) { //find index by name
let found = false;
for (let i = 0; i < tech.tech.length; i++) {
if (index === tech.tech[i].name) {
@@ -49,7415 +141,7402 @@
break;
}
}
- if (!found) return 0 //if name not found don't remove any tech
+ if (!found) return //if name not found don't give any tech
}
- if (tech.tech[index].count === 0) return 0
- const totalRemoved = tech.tech[index].count
- simulation.makeTextLog(`tech.removeTech("${tech.tech[index].name}")`)
- tech.tech[index].remove();
- tech.tech[index].count = 0;
+ if (tech.isMetaAnalysis && tech.tech[index].isJunk) {
+ simulation.makeTextLog(`//tech: meta-analysis replaced junk tech with random tech`);
+ tech.giveTech('random')
+ for (let i = 0; i < 3; i++) powerUps.spawn(m.pos.x + 40 * Math.random(), m.pos.y + 40 * Math.random(), "research");
+ return
+ }
+
+ if (tech.tech[index].isLost) tech.tech[index].isLost = false; //give specific tech
+ tech.tech[index].effect(); //give specific tech
+ tech.tech[index].count++
+ tech.totalCount++ //used in power up randomization
simulation.updateTechHUD();
- tech.tech[index].isLost = true
- simulation.updateTechHUD();
- return totalRemoved //return the total number of tech removed
- },
- // onclick="tech.removeTechPaused(${i}, this)" //add this to tech elements in pause menu
- // removeTechPaused(index, who) {
- // tech.tech[index].remove();
- // tech.tech[index].count = 0;
- // simulation.updateTechHUD();
- // who.innerHTML = "removed"
- // // who.style.display = "none"
- // },
- // removeLoreTechFromPool() {
- // for (let i = tech.tech.length - 1; i > 0; i--) {
- // if (tech.tech[i].isLore && tech.tech[i].count === 0) tech.tech.splice(i, 1)
- // }
- // },
- addJunkTechToPool(chance) { //chance is number between 0-1
- // { //count JUNK
- // let count = 0
- // for (let i = 0, len = tech.tech.length; i < len; i++) {
- // if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && tech.tech[i].isJunk && tech.tech[i].frequency > 0) count += tech.tech[i].frequency
- // }
- // console.log(count)
- // }
- // { //count not JUNK
- // let count = 0
- // for (let i = 0, len = tech.tech.length; i < len; i++) {
- // if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk && tech.tech[i].frequency > 0) count++
- // }
- // console.log(count)
- // }
- // count total non junk tech
- let count = 0
+ }
+ },
+ // setTechoNonRefundable(name) {
+ // for (let i = 0; i < tech.tech.length; i++) {
+ // if (tech.tech.name === name) {
+ // tech.tech[i].isNonRefundable = true;
+ // return
+ // }
+ // }
+ // },
+ setCheating() {
+ if (!simulation.isCheating) {
+ simulation.isCheating = true;
+ level.levelAnnounce();
+ lore.techCount = 0;
for (let i = 0, len = tech.tech.length; i < len; i++) {
- if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk) count += tech.tech[i].frequency
+ if (tech.tech[i].isLore) {
+ tech.tech[i].frequency = 0;
+ tech.tech[i].count = 0;
+ }
}
- //make an array for possible junk tech to add
- let options = [];
+ console.log('cheating')
+ sound.tone(250)
+ sound.tone(300)
+ sound.tone(375)
+ }
+ },
+ haveGunCheck(name, needActive = true) {
+ // if (
+ // !build.isExperimentSelection &&
+ // b.inventory.length > 2 &&
+ // name !== b.guns[b.activeGun].name &&
+ // Math.random() > 2 - b.inventory.length * 0.5
+ // ) {
+ // return false
+ // }
+ // for (i = 0, len = b.inventory.length; i < len; i++) {
+ // if (b.guns[b.inventory[i]].name === name) return true
+ // }
+ // return false
+ if (build.isExperimentSelection || !needActive) {
+ for (i = 0, len = b.inventory.length; i < len; i++) {
+ if (b.guns[b.inventory[i]].name === name) return true
+ }
+ return false
+ } else { //must be holding gun, this is the standard while playing
+ return b.inventory.length > 0 && b.guns[b.activeGun].name === name
+ }
+ },
+ hasExplosiveDamageCheck() {
+ return tech.haveGunCheck("missiles") || tech.isMissileField || tech.missileBotCount > 0 || tech.boomBotCount > 1 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb)
+ },
+ damageFromTech() {
+ let dmg = 1 //m.fieldDamage
+ if (tech.isAxion && tech.isHarmMACHO) dmg *= 1 + 0.75 * (1 - m.harmReduction())
+ if (tech.OccamDamage) dmg *= tech.OccamDamage
+ if (tech.isCloakingDamage) dmg *= 1.35
+ if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.5
+ if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599
+ if (m.isSneakAttack && m.cycle > m.lastKillCycle + 240) dmg *= tech.sneakAttackDmg
+ if (tech.isTechDamage) dmg *= 1.9
+ if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
+ if (tech.isLowEnergyDamage) dmg *= 1 + Math.max(0, 1 - m.energy) * 0.5
+ if (tech.isMaxEnergyTech) dmg *= 1.5
+ if (tech.isEnergyNoAmmo) dmg *= 1.6
+ if (tech.isDamageForGuns) dmg *= 1 + 0.14 * b.inventory.length
+ if (tech.isLowHealthDmg) dmg *= 1 + Math.max(0, 1 - m.health) * 0.5
+ if (tech.isHarmDamage && m.lastHarmCycle + 600 > m.cycle) dmg *= 3;
+ if (tech.isEnergyLoss) dmg *= 1.55;
+ if (tech.isAcidDmg && m.health > 1) dmg *= 1.35;
+ if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage
+ if (tech.isEnergyDamage) dmg *= 1 + m.energy / 11;
+ if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.007
+ if (tech.isRerollDamage) dmg *= 1 + 0.037 * powerUps.research.count
+ if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.1995
+ if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2
+ if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.66, player.speed * 0.0165)
+ if (tech.isBotDamage) dmg *= 1 + 0.07 * b.totalBots()
+ if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 1.5
+ return dmg * tech.slowFire * tech.aimDamage
+ },
+ duplicationChance() {
+ return Math.max(0, (tech.isPowerUpsVanish ? 0.12 : 0) + (tech.isStimulatedEmission ? 0.15 : 0) + tech.cancelCount * 0.04 + tech.duplicateChance + m.duplicateChance + tech.wormDuplicate + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.45 : 0))
+ },
+ isScaleMobsWithDuplication: false,
+ maxDuplicationEvent() {
+ if (tech.is111Duplicate && tech.duplicationChance() > 1.11) {
+ tech.is111Duplicate = false
+ const range = 1300
+ tech.isScaleMobsWithDuplication = true
+ for (let i = 0, len = 9; i < len; i++) {
+ const angle = 2 * Math.PI * i / len
+ spawn.randomLevelBoss(m.pos.x + range * Math.cos(angle), m.pos.y + range * Math.sin(angle), spawn.nonCollideBossList);
+ }
+ spawn.historyBoss(0, 0)
+ spawn.pulsarBoss(level.exit.x, level.exit.y, 70, true)
+ spawn.blockBoss(level.enter.x, level.enter.y)
+ tech.isScaleMobsWithDuplication = false
+ }
+ },
+ setTechFrequency(name, frequency) {
+ for (let i = 0, len = tech.tech.length; i < len; i++) {
+ if (tech.tech[i].name === name) tech.tech[i].frequency = frequency
+ }
+ },
+ setBotTechFrequency(f = 0) {
+ for (let i = 0, len = tech.tech.length; i < len; i++) {
+ if (tech.tech[i].isBotTech) {
+ switch (tech.tech[i].name) {
+ case "dynamo-bot":
+ tech.tech[i].frequency = f
+ break;
+ case "orbital-bot":
+ tech.tech[i].frequency = f
+ break;
+ case "laser-bot":
+ tech.tech[i].frequency = f
+ break;
+ case "boom-bot":
+ tech.tech[i].frequency = f
+ break;
+ case "foam-bot":
+ tech.tech[i].frequency = f
+ break;
+ case "nail-bot":
+ tech.tech[i].frequency = f
+ break;
+ }
+ }
+ }
+ },
+ tech: [{
+ name: "integrated armament",
+ link: `integrated armament`,
+ description: `increase damage by 19.95%
your inventory can only hold 1 gun`,
+ maxCount: 1,
+ count: 0,
+ frequency: 1,
+ frequencyDefault: 1,
+ allowed() {
+ return b.inventory.length === 1 //&& !tech.haveGunCheck("CPT gun")
+ },
+ requires: "only 1 gun",
+ effect() {
+ tech.isOneGun = true;
for (let i = 0; i < tech.tech.length; i++) {
- if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].isJunk) options.push(i);
- }
- //add random array options to tech pool
- if (options.length) {
- const num = chance * count //scale number added
- for (let i = 0; i < num; i++) tech.tech[options[Math.floor(Math.random() * options.length)]].frequency++
- simulation.makeTextLog(`tech.tech.push(${num} JUNK)`)
- return num
- } else {
- return 0
+ if (tech.tech[i].name === "CPT gun") tech.tech[i].description = `adds the CPT gun to your inventory
it rewinds your health, velocity, and position