diff --git a/js/bullets.js b/js/bullets.js
index 8ecf456..c1441db 100644
--- a/js/bullets.js
+++ b/js/bullets.js
@@ -87,6 +87,7 @@ const b = {
modNailsDeathMob: null,
isModSlowFPS: null,
isModNeutronStun: null,
+ manyWorlds: null,
modOnHealthChange() { //used with acid mod
if (b.isModAcidDmg && mech.health > 0.8) {
b.modAcidDmg = 0.5
@@ -762,7 +763,7 @@ const b = {
},
{
name: "pair production",
- description: "power ups overfill your energy
temporarily gain twice your maximum",
+ description: "power ups overfill your energy
temporarily gain twice your max energy",
maxCount: 1,
count: 0,
allowed() {
@@ -850,31 +851,23 @@ const b = {
}
},
{
- name: "reallocation",
- description: "convert 1 random mod into 2 new guns
recursive mods lose all stacks",
+ name: "many worlds",
+ description: "spawn a reroll after choosing a power up",
maxCount: 1,
count: 0,
allowed() {
- return (b.modCount > 0) && !build.isCustomSelection
+ return true
},
- requires: "at least 1 mod",
+ requires: "",
effect: () => {
- const have = [] //find which mods you have
- for (let i = 0; i < b.mods.length; i++) {
- if (b.mods[i].count > 0) have.push(i)
- }
- const choose = have[Math.floor(Math.random() * have.length)]
- b.mods[choose].remove(); // remove a random mod form the list of mods you have
- b.mods[choose].count = 0;
- game.updateModHUD();
-
- for (let i = 0; i < 2; i++) {
- powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
- if (Math.random() < b.modBayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
- }
+ b.manyWorlds = true;
+ // for (let i = 0; i < 9; i++) {
+ // powerUps.spawn(mech.pos.x, mech.pos.y, "reroll");
+ // if (Math.random() < b.modBayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "reroll");
+ // }
},
remove() {
- //nothing to remove
+ b.manyWorlds = false;
}
},
{
@@ -903,6 +896,34 @@ const b = {
//nothing to undo
}
},
+ {
+ name: "reallocation",
+ description: "convert 1 random mod into 2 new guns
recursive mods lose all stacks",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return (b.modCount > 0) && !build.isCustomSelection
+ },
+ requires: "at least 1 mod",
+ effect: () => {
+ const have = [] //find which mods you have
+ for (let i = 0; i < b.mods.length; i++) {
+ if (b.mods[i].count > 0) have.push(i)
+ }
+ const choose = have[Math.floor(Math.random() * have.length)]
+ b.mods[choose].remove(); // remove a random mod form the list of mods you have
+ b.mods[choose].count = 0;
+ game.updateModHUD();
+
+ for (let i = 0; i < 2; i++) {
+ powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
+ if (Math.random() < b.modBayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
+ }
+ },
+ remove() {
+ //nothing to remove
+ }
+ },
{
name: "Lorentzian topology",
description: "your bullets last +33% longer",
@@ -1973,6 +1994,7 @@ const b = {
dist = Vector.magnitude(sub) - mob[i].radius;
if (dist < radius) {
if (mob[i].shield) dmg *= 3 //balancing explosion dmg to shields
+ if (Matter.Query.ray(map, mob[i].position, where).length > 0) dmg *= 0.5 //reduce damage if a wall is in the way
mob[i].damage(dmg * damageScale);
mob[i].locatePlayer();
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) / 50);
@@ -2353,7 +2375,7 @@ const b = {
friction: 0.05,
frictionAir: 0.0005,
restitution: 1,
- dmg: 0.17, //damage done in addition to the damage from momentum
+ dmg: 0.23, //damage done in addition to the damage from momentum
lookFrequency: 107 + Math.floor(47 * Math.random()),
endCycle: game.cycle + Math.floor((1200 + 420 * Math.random()) * b.isModBulletsLastLonger),
classType: "bullet",
@@ -2365,7 +2387,14 @@ const b = {
lockedOn: null,
isFollowMouse: true,
deathCycles: 110 + RADIUS * 5,
- onDmg() {
+ onDmg(who) {
+ //move away from target after hitting
+ const unit = Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), -20)
+ Matter.Body.setVelocity(this, {
+ x: unit.x,
+ y: unit.y
+ });
+
this.lockedOn = null
if (this.endCycle > game.cycle + this.deathCycles && b.isModDroneCollide) {
this.endCycle -= 60
@@ -3119,7 +3148,7 @@ const b = {
// check if inside a mob
q = Matter.Query.point(mob, this.position)
for (let i = 0; i < q.length; i++) {
- let dmg = b.dmgScale * 0.43 / Math.sqrt(q[i].mass) * (b.modWaveHelix === 1 ? 1 : 0.6) //1 - 0.4 = 0.6 for helix mod 40% damage reduction
+ let dmg = b.dmgScale * 0.40 / Math.sqrt(q[i].mass) * (b.modWaveHelix === 1 ? 1 : 0.6) //1 - 0.4 = 0.6 for helix mod 40% damage reduction
q[i].damage(dmg);
q[i].foundPlayer();
game.drawList.push({ //add dmg to draw queue
@@ -3631,11 +3660,10 @@ const b = {
//aoe damage to mobs
for (let i = 0, len = mob.length; i < len; i++) {
if (Vector.magnitude(Vector.sub(mob[i].position, this.position)) < this.damageRadius) {
- if (mob[i].shield) {
- mob[i].damage(5 * b.dmgScale * 0.023);
- } else {
- mob[i].damage(b.dmgScale * 0.023);
- }
+ let dmg = b.dmgScale * 0.023
+ if (Matter.Query.ray(map, mob[i].position, this.position).length > 0) dmg *= 0.5 //reduce damage if a wall is in the way
+ if (mob[i].shield) dmg *= 5 //x5 to make up for the /5 that shields normally take
+ mob[i].damage(dmg);
mob[i].locatePlayer();
}
}
@@ -3859,6 +3887,7 @@ const b = {
//frictionAir: 0.01, //restitution: 0,
// angle: 0,
// friction: 0.5,
+ restitution: 0,
frictionAir: 0,
dmg: 0, //damage done in addition to the damage from momentum
classType: "bullet",
diff --git a/js/game.js b/js/game.js
index 608c0c1..dc65ec2 100644
--- a/js/game.js
+++ b/js/game.js
@@ -56,6 +56,7 @@ const game = {
b.bulletDraw();
b.bulletDo();
game.drawCircle();
+ game.clip();
ctx.restore();
game.drawCursor();
},
@@ -132,6 +133,9 @@ const game = {
// };
// requestAnimationFrame(normalFPS);
// },
+ clip() {
+
+ },
drawCursor() {
const size = 10;
ctx.beginPath();
@@ -481,6 +485,7 @@ const game = {
b.setupAllMods(); //sets mods to default values
game.updateModHUD();
+ powerUps.reroll.rerolls = 0;
mech.maxHealth = 1
mech.maxEnergy = 1
game.paused = false;
diff --git a/js/index.js b/js/index.js
index f64b893..f510696 100644
--- a/js/index.js
+++ b/js/index.js
@@ -87,8 +87,6 @@ const build = {
global damage increase: ${((b.damageFromMods()-1)*100).toFixed(0)}%
global harm reduction: ${((1-mech.harmReduction())*100).toFixed(0)}%
`;
-
-
let countGuns = 0
let countMods = 0
for (let i = 0, len = b.guns.length; i < len; i++) {
@@ -269,10 +267,6 @@ const build = {
document.getElementById("build-grid").style.display = "grid"
},
shareURL() {
- game.copyToClipBoard(build.generateURL())
- alert('n-gon build URL copied to clipboard.\nPaste into browser address bar.')
- },
- generateURL() {
let url = "https://landgreen.github.io/sidescroller/index.html?"
let count = 0;
for (let i = 0; i < b.guns.length; i++) {
@@ -292,7 +286,8 @@ const build = {
url += `&difficulty=${game.difficultyMode}`
url += `&level=${Number(document.getElementById("starting-level").value)}`
console.log(url)
- return url
+ game.copyToClipBoard(url)
+ alert('n-gon build URL copied to clipboard.\nPaste into browser address bar.')
},
startBuildRun() {
build.isCustomSelection = false;
diff --git a/js/level.js b/js/level.js
index d6e73a5..79126b2 100644
--- a/js/level.js
+++ b/js/level.js
@@ -16,11 +16,8 @@ const level = {
if (level.levelsCleared === 0) { //this code only runs on the first level
// game.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(9)
- // b.giveGuns("foam")
// mech.setField("time dilation field")
- // b.giveMod("necrophoresis");
- // b.giveMod("impact shear");
- // b.giveMod("foam-bot");
+ // b.giveMod("many worlds");
// b.giveGuns("neutron bomb")
// b.giveGuns("foam")
// mech.setField("pilot wave")
@@ -162,10 +159,11 @@ const level = {
// spawn.bomberBoss(2900, -500)
// spawn.shooterBoss(1200, -500)
- spawn.spinner(1200, -500, 40)
+ // spawn.starter(2500, -40, 40)
// spawn.stabber(1600, -500)
// spawn.cellBossCulture(1600, -500)
// spawn.shooter(1600, -500)
+ spawn.focuser(1600, -500)
// spawn.shield(mob[mob.length - 1], 1200, -500, 1);
// spawn.nodeBoss(1200, -500, "spiker")
diff --git a/js/mobs.js b/js/mobs.js
index b0a89ef..9c1736b 100644
--- a/js/mobs.js
+++ b/js/mobs.js
@@ -507,7 +507,7 @@ const mobs = {
},
springAttack() {
// set new values of the ends of the spring constraints
- if (this.seePlayer.recall) {
+ if (this.seePlayer.recall && Matter.Query.ray(map, this.position, player.position).length === 0) {
if (!(game.cycle % (this.seePlayerFreq * 2))) {
this.springTarget.x = this.seePlayer.position.x;
this.springTarget.y = this.seePlayer.position.y;
@@ -850,7 +850,6 @@ const mobs = {
if (!(game.cycle % this.seePlayerFreq)) {
this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position));
this.fireDir.y -= Math.abs(this.seePlayer.position.x - this.position.x) / 1600; //gives the bullet an arc
- this.fireAngle = Math.atan2(this.fireDir.y, this.fireDir.x);
}
//rotate towards fireAngle
const angle = this.angle + Math.PI / 2;
@@ -885,6 +884,52 @@ const mobs = {
// }
}
},
+ launch() {
+ if (!mech.isBodiesAsleep) {
+ const setNoseShape = () => {
+ const mag = this.radius + this.radius * this.noseLength;
+ this.vertices[1].x = this.position.x + Math.cos(this.angle) * mag;
+ this.vertices[1].y = this.position.y + Math.sin(this.angle) * mag;
+ };
+ //throw a mob/bullet at player
+ if (this.seePlayer.recall) {
+ //set direction to turn to fire
+ if (!(game.cycle % this.seePlayerFreq)) {
+ this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position));
+ }
+ //rotate towards fireAngle
+ const angle = this.angle + Math.PI / 2;
+ c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
+ const threshold = 0.1;
+ if (c > threshold) {
+ this.torque += 0.0000045 * this.inertia;
+ } else if (c < -threshold) {
+ this.torque -= 0.0000045 * this.inertia;
+ } else if (this.noseLength > 1.5) {
+ //fire
+ spawn.seeker(this.vertices[1].x, this.vertices[1].y, 5 + Math.ceil(this.radius / 15), 5);
+ const v = 15;
+ Matter.Body.setVelocity(mob[mob.length - 1], {
+ x: this.velocity.x + this.fireDir.x * v + Math.random(),
+ y: this.velocity.y + this.fireDir.y * v + Math.random()
+ });
+ this.noseLength = 0;
+ // recoil
+ this.force.x -= 0.005 * this.fireDir.x * this.mass;
+ this.force.y -= 0.005 * this.fireDir.y * this.mass;
+ }
+ if (this.noseLength < 1.5) this.noseLength += this.fireFreq;
+ setNoseShape();
+ } else if (this.noseLength > 0.1) {
+ this.noseLength -= this.fireFreq / 2;
+ setNoseShape();
+ }
+ // else if (this.noseLength < -0.1) {
+ // this.noseLength += this.fireFreq / 4;
+ // setNoseShape();
+ // }
+ }
+ },
turnToFacePlayer() {
//turn to face player
const dx = player.position.x - this.position.x;
diff --git a/js/player.js b/js/player.js
index 9f8088c..60a195d 100644
--- a/js/player.js
+++ b/js/player.js
@@ -363,6 +363,7 @@ const mech = {
if (b.isModImmortal) { //if player has the immortality buff, spawn on the same level with randomized stats
spawn.setSpawnList(); //new mob types
game.clearNow = true; //triggers a map reset
+ powerUps.reroll.rerolls = Math.floor(Math.random() * Math.random() * 8)
//count mods
let totalMods = 0;
@@ -380,6 +381,7 @@ const mech = {
b.mods[i].name !== "Born rule" &&
b.mods[i].name !== "determinism" &&
b.mods[i].name !== "reallocation" &&
+ b.mods[i].name !== "many worlds" &&
b.mods[i].allowed()
) options.push(i);
}
@@ -1045,7 +1047,7 @@ const mech = {
}
if (mech.energy > mech.maxEnergy) mech.energy = mech.maxEnergy;
- if (b.modBlockDmg) {
+ if (b.modBlockDmg && mech.fieldUpgrades[mech.fieldMode].name === "standing wave harmonics") {
who.damage(b.modBlockDmg)
//draw electricity
const step = 40
@@ -1087,7 +1089,7 @@ const mech = {
});
}
} else {
- if (b.isModStunField) mobs.statusStun(who, b.isModStunField)
+ if (b.isModStunField && mech.fieldUpgrades[mech.fieldMode].name === "perfect diamagnetism") mobs.statusStun(who, b.isModStunField)
// mobs.statusSlow(who, b.isModStunField)
const massRoot = Math.sqrt(Math.max(0.15, who.mass)); // masses above 12 can start to overcome the push back
Matter.Body.setVelocity(who, {
@@ -1434,7 +1436,7 @@ const mech = {
},
{
name: "negative mass field",
- description: "use energy to nullify gravity
reduce harm by 80% while field is active", //
launch larger blocks at much higher speeds
+ description: "use energy to nullify gravity
reduce harm by 80% while field is active",
fieldDrawRadius: 0,
isEasyToAim: true,
effect: () => {
@@ -1569,10 +1571,11 @@ const mech = {
},
{
name: "plasma torch",
- description: "use energy to emit damaging plasma
effective at close range",
+ description: "use energy to emit damaging plasma
reduce harm by 33%",
isEasyToAim: false,
effect: () => {
mech.fieldMeterColor = "#f0f"
+ mech.fieldDamageResistance = 0.67; //reduce harm by 33%
mech.hold = function () {
if (mech.isHolding) {
@@ -1582,7 +1585,7 @@ const mech = {
} else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed
mech.grabPowerUp();
mech.lookForPickUp();
- const DRAIN = 0.00065
+ const DRAIN = 0.0006
if (mech.energy > DRAIN) {
mech.energy -= DRAIN;
if (mech.energy < 0) {
@@ -1666,8 +1669,12 @@ const mech = {
best.who.locatePlayer();
//push mobs away
- const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.02 * Math.sqrt(best.who.mass))
+ const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.01 * Math.min(5, best.who.mass))
Matter.Body.applyForce(best.who, path[1], force)
+ Matter.Body.setVelocity(best.who, { //friction
+ x: best.who.velocity.x * 0.6,
+ y: best.who.velocity.y * 0.6
+ });
// const angle = Math.atan2(player.position.y - best.who.position.y, player.position.x - best.who.position.x);
// const mass = Math.min(Math.sqrt(best.who.mass), 6);
// Matter.Body.setVelocity(best.who, {
@@ -1685,7 +1692,7 @@ const mech = {
});
} else if (!best.who.isStatic) {
//push blocks away
- const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.006 * Math.sqrt(Math.sqrt(best.who.mass)))
+ const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.007 * Math.sqrt(Math.sqrt(best.who.mass)))
Matter.Body.applyForce(best.who, path[1], force)
}
}
diff --git a/js/powerups.js b/js/powerups.js
index d7623c4..e0b0b9e 100644
--- a/js/powerups.js
+++ b/js/powerups.js
@@ -21,6 +21,10 @@ const powerUps = {
powerUps.endDraft();
},
endDraft() {
+ if (b.manyWorlds) {
+ powerUps.spawn(mech.pos.x, mech.pos.y, "reroll");
+ if (Math.random() < b.modBayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "reroll");
+ }
document.body.style.cursor = "none";
document.getElementById("choose-grid").style.display = "none"
document.getElementById("choose-background").style.display = "none"
@@ -162,7 +166,7 @@ const powerUps = {
let choice2 = -1
let choice3 = -1
if (choice1 > -1) {
- let text = `