diff --git a/.DS_Store b/.DS_Store
index 3482c29..e089e3a 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/js/level.js b/js/level.js
index 419fbf2..7c38ccc 100644
--- a/js/level.js
+++ b/js/level.js
@@ -12,9 +12,9 @@ const level = {
start() {
if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.enableConstructMode() //used to build maps in testing mode
- // level.difficultyIncrease(30)
+ // level.difficultyIncrease(60) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true
- // m.setField("perfect diamagnetism")
+ // m.setField("wormhole")
// b.giveGuns("spores")
// tech.giveTech("CPT reversal")
// tech.giveTech("causality bombs")
@@ -640,10 +640,10 @@ const level = {
this.isUp = true;
} else {
if (this.isUp === true) {
- const list = Matter.Query.region(body, this)
+ const list = Matter.Query.region(body, this) //are any blocks colliding with this
if (list.length > 0) {
- if (list[0].bounds.max.x - list[0].bounds.min.x < 150 && list[0].bounds.max.y - list[0].bounds.min.y < 150) {
- Matter.Body.setPosition(list[0], {
+ if (list[0].bounds.max.x - list[0].bounds.min.x < 150 && list[0].bounds.max.y - list[0].bounds.min.y < 150) { //not too big of a block
+ Matter.Body.setPosition(list[0], { //teleport block to the center of the button
x: this.min.x + width / 2,
y: list[0].position.y
})
@@ -2195,7 +2195,9 @@ const level = {
spawn.mapRect(475, -25, 25, 50); //edge shelf
},
testing() {
- // const button = level.button(200, -700)
+ const button = level.button(1000, 0)
+ spawn.bodyRect(1000, -50, 50, 50);
+
// const toggle = level.toggle(200, -700)
level.custom = () => {
// button.draw();
@@ -2206,7 +2208,8 @@ const level = {
level.enter.draw();
};
level.customTopLayer = () => {
- // toggle.query();
+ button.query();
+ button.draw();
};
level.setPosToSpawn(0, -450); //normal spawn
@@ -2253,8 +2256,8 @@ const level = {
spawn.mapRect(6700, -1800, 800, 2600); //right wall
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
- spawn.starter(1900, -500, 200) //big boy
- spawn.starter(1900, -500)
+ // spawn.starter(1900, -500, 200) //big boy
+ spawn.buffBossCulture(1900, -500)
// spawn.pulsarBoss(1900, -500)
// spawn.shieldingBoss(1900, -500)
@@ -2268,7 +2271,7 @@ const level = {
// spawn.bomberBoss(1400, -500)
// spawn.hopBoss(1800, -120)
// spawn.streamBoss(1600, -500)
- // spawn.orbitalBoss(1600, -500)
+ // spawn.powerUpBoss(1600, -500)
// spawn.cellBossCulture(1600, -500)
// spawn.shieldingBoss(1600, -500)
// spawn.grenadier(1200, -500)
@@ -7056,7 +7059,7 @@ const level = {
spawn.randomGroup(2000, -5700, 0.6);
powerUps.addResearchToLevel() //needs to run after mobs are spawned
- let bosses = ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "laserBoss"];
+ let bosses = ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "laserBoss", "buffBossCulture"];
let abc = Math.random();
if (simulation.difficulty > 3) {
if (abc < 0.6) {
diff --git a/js/lore.js b/js/lore.js
index ad04aef..aaea374 100644
--- a/js/lore.js
+++ b/js/lore.js
@@ -351,7 +351,12 @@ const lore = {
lore.miriam.text("The exact coordinates are blocked.")
} else {
console.log('Locating…')
- navigator.geolocation.getCurrentPosition(success, error);
+ const options = {
+ enableHighAccuracy: true,
+ maximumAge: 30000,
+ timeout: 27000
+ };
+ navigator.geolocation.getCurrentPosition(success, error, options);
}
},
() => { lore.anand.text("This location is sending and receiving data from the satellite.") },
@@ -401,7 +406,6 @@ const lore = {
() => { lore.talkingColor = "#dff" },
],
// [ // they decided that a part of the project is out of control, but the part of it that doesn't needs to calm it down, and trust.
-
// /*
// The part of the AI controlling the player is outsourcing the player control to real humans that think they are playing a video game.
// this means the player can use console commands to change the way the game works
diff --git a/js/player.js b/js/player.js
index 39ec651..92e1c14 100644
--- a/js/player.js
+++ b/js/player.js
@@ -1135,7 +1135,7 @@ const m = {
b.pulse(50 * Math.pow(m.holdingTarget.mass, 0.25), m.angle)
} else { //normal throw
//bullet-like collisions
- m.holdingTarget.collisionFilter.category = tech.isBlockBullets ? cat.bullet : cat.body;
+ 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) {
@@ -2322,7 +2322,7 @@ const m = {
// },
{
name: "pilot wave",
- description: "use energy to push blocks with your mouse
field radius decreases out of line of sight
energy drain scales with mass",
+ description: "use energy to push blocks with your mouse
blocks can collide with intangible mobs
field radius decreases out of line of sight",
effect: () => {
m.fieldPhase = 0;
m.fieldPosition = {
@@ -2431,7 +2431,7 @@ const m = {
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.000013 // * (1 + m.energy * m.energy) //drain more energy when you have more energy
+ const DRAIN = speed * body[i].mass * 0.000015 // * (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
@@ -2442,7 +2442,7 @@ const m = {
const unit = Vector.mult(Vector.normalise(sub), body[i].mass * tech.pilotForce * Vector.magnitude(sub))
body[i].force.x += unit.x
body[i].force.y += unit.y - body[i].mass * simulation.g //remove gravity effects
- if (tech.isBlockBullets && body[i].collisionFilter.category !== cat.bullet) body[i].collisionFilter.category = cat.bullet;
+ if (body[i].collisionFilter.category !== cat.bullet) body[i].collisionFilter.category = cat.bullet;
} else {
m.fieldCDcycle = m.cycle + 120;
m.fieldOn = false
diff --git a/js/spawn.js b/js/spawn.js
index a0973dd..728669c 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -84,7 +84,8 @@ const spawn = {
}
}
},
- randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss"]) {
+ nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture", "buffBossCulture"],
+ randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "buffBossCulture"]) {
// other bosses: suckerBoss, laserBoss, tetherBoss, //these need a particular level to work so they are not included in the random pool
spawn[options[Math.floor(Math.random() * options.length)]](x, y)
},
@@ -706,7 +707,6 @@ const spawn = {
me.memory = 60;
me.seeAtDistance2 = 1400000 //1200 vision range
Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback
-
me.do = function() {
this.seePlayerByLookingAt();
this.attraction();
@@ -812,7 +812,6 @@ const spawn = {
me.frictionAir = 0.012
me.seePlayerFreq = Math.floor(11 + 7 * Math.random())
me.seeAtDistance2 = 200000 //1400000;
- me.cellMassMax = 70
me.stroke = "transparent"
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body //| cat.map //"rgba(255,60,0,0.3)"
// Matter.Body.setDensity(me, 0.0014) // normal density is 0.001
@@ -828,11 +827,6 @@ const spawn = {
this.checkStatus();
this.attraction();
- // if (this.seePlayer.recall && this.mass < this.cellMassMax) { //grow cell radius
- // const scale = 1 + 0.0002 * this.cellMassMax / this.mass;
- // Matter.Body.scale(this, scale, scale);
- // this.radius = Math.sqrt(this.mass * k / Math.PI)
- // }
if (!(simulation.cycle % this.seePlayerFreq)) { //move away from other mobs
const repelRange = 40
const attractRange = 240
@@ -887,6 +881,88 @@ const spawn = {
}
},
+ buffBossCulture(x, y, radius = 17, nodes = 12 + Math.min(10, simulation.difficulty * 0.27)) {
+ const buffID = Math.random()
+ const sideLength = 200 + 50 * Math.sqrt(nodes) // distance between each node mob
+ const targets = []
+ for (let i = 0; i < nodes; ++i) {
+ const angle = 2 * Math.PI * Math.random()
+ spawn.buffBoss(x + sideLength * Math.cos(angle) * Math.random(), y + sideLength * Math.sin(angle) * Math.random(), radius, buffID);
+ // spawn.buffBoss(x + sideLength * nodes * (Math.random() - 0.5), y + sideLength * nodes * (Math.random() - 0.5), radius, buffID);
+ targets.push(mob[mob.length - 1].id) //track who is in the group, for shields
+
+ }
+ const attachmentStiffness = 0.0001
+ spawn.constrain2AdjacentMobs(nodes, attachmentStiffness, false); //loop mobs together
+ // if (simulation.difficulty > 15) this.groupShield(targets, x, y, sideLength + radius * 2);
+ },
+ buffBoss(x, y, radius, buffID) {
+ mobs.spawn(x + Math.random(), y + Math.random(), 6, radius, "hsl(144, 15%, 50%)") //);
+ let me = mob[mob.length - 1];
+ me.isBoss = true;
+ me.damageReduction = 0.25;
+ me.isBuffBoss = true;
+ me.buffID = buffID
+ me.memory = Infinity;
+ // me.showHealthBar = false;
+ me.isVerticesChange = true
+ me.frictionAir = 0.012
+ me.seePlayerFreq = Math.floor(11 + 7 * Math.random())
+ me.seeAtDistance2 = 200000 //1400000;
+ me.stroke = "transparent"
+ me.collisionFilter.mask = cat.player | cat.bullet //| cat.body //| cat.map //"rgba(255,60,0,0.3)"
+
+ me.buffCount = 0
+ me.accelMag = 0.0001 //* simulation.accelScale;
+ me.setBuffed = function() {
+ this.buffCount++
+ this.accelMag += 0.00005 //* 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%)`
+ const scale = 1.14;
+ Matter.Body.scale(this, scale, scale);
+ this.radius *= scale;
+ // this.health += 0.03
+ // if (this.health > 1) this.health = 1
+ }
+ me.onDeath = function() {
+ this.isBuffBoss = false;
+ let count = 0 //count other cells by id
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (mob[i].isBuffBoss && mob[i].buffID === this.buffID) {
+ count++
+ mob[i].setBuffed()
+ }
+ }
+ if (count < 1) { //only drop a power up if this is the last cell
+ powerUps.spawnBossPowerUp(this.position.x, this.position.y)
+ } else {
+ this.leaveBody = false;
+ // this.isDropPowerUp = false; //these guys can still drop power ups since they are hard to kill
+ }
+ }
+ me.do = function() {
+ this.alwaysSeePlayer();
+ this.checkStatus();
+ this.attraction();
+
+ // if (!(simulation.cycle % this.seePlayerFreq)) { //move away from other mobs
+ // const repelRange = 100 + 4 * this.radius
+ // const attractRange = 240
+ // for (let i = 0, len = mob.length; i < len; i++) {
+ // if (mob[i].isBuffBoss && mob[i].id !== this.id) {
+ // const sub = Vector.sub(this.position, mob[i].position)
+ // const dist = Vector.magnitude(sub)
+ // if (dist < repelRange) {
+ // this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.002)
+ // } else if (dist > attractRange) {
+ // this.force = Vector.mult(Vector.normalise(sub), -this.mass * 0.002)
+ // }
+ // }
+ // }
+ // }
+ }
+ },
powerUpBoss(x, y, vertices = 9, radius = 130) {
mobs.spawn(x, y, vertices, radius, "transparent");
let me = mob[mob.length - 1];
@@ -1585,7 +1661,7 @@ const spawn = {
},
historyBoss(x, y, radius = 30) {
if (tech.dynamoBotCount > 0) {
- spawn.randomLevelBoss(x, y, ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture"])
+ spawn.randomLevelBoss(x, y, spawn.nonCollideBossList)
return
}
mobs.spawn(x, y, 0, radius, "transparent");
@@ -2929,7 +3005,7 @@ const spawn = {
};
Matter.Body.setDensity(me, 0.00005); //normal is 0.001
me.timeLeft = 240;
- me.g = 0.001; //required if using 'gravity'
+ me.g = 0.0005; //required if using 'gravity'
me.frictionAir = 0;
me.restitution = 0;
me.leaveBody = false;
@@ -2939,6 +3015,7 @@ const spawn = {
me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
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) {
this.isDropPowerUp = false;
diff --git a/js/tech.js b/js/tech.js
index 68dd7af..f7a8397 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -188,15 +188,14 @@
if (tech.is100Duplicate && tech.duplicationChance() > 0.99) {
tech.is100Duplicate = false
const range = 700
- const bossOptions = ["historyBoss", "cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture"]
- spawn.randomLevelBoss(m.pos.x + range, m.pos.y, bossOptions);
- spawn.randomLevelBoss(m.pos.x, m.pos.y + range, bossOptions);
- spawn.randomLevelBoss(m.pos.x - range, m.pos.y, bossOptions);
- spawn.randomLevelBoss(m.pos.x, m.pos.y - range, bossOptions);
- spawn.randomLevelBoss(m.pos.x + range, m.pos.y + range, bossOptions);
- spawn.randomLevelBoss(m.pos.x + range, m.pos.y - range, bossOptions);
- spawn.randomLevelBoss(m.pos.x - range, m.pos.y + range, bossOptions);
- spawn.randomLevelBoss(m.pos.x - range, m.pos.y - range, bossOptions);
+ spawn.randomLevelBoss(m.pos.x + range, m.pos.y, spawn.nonCollideBossList);
+ spawn.randomLevelBoss(m.pos.x, m.pos.y + range, spawn.nonCollideBossList);
+ spawn.randomLevelBoss(m.pos.x - range, m.pos.y, spawn.nonCollideBossList);
+ spawn.randomLevelBoss(m.pos.x, m.pos.y - range, spawn.nonCollideBossList);
+ spawn.randomLevelBoss(m.pos.x + range, m.pos.y + range, spawn.nonCollideBossList);
+ spawn.randomLevelBoss(m.pos.x + range, m.pos.y - range, spawn.nonCollideBossList);
+ spawn.randomLevelBoss(m.pos.x - range, m.pos.y + range, spawn.nonCollideBossList);
+ spawn.randomLevelBoss(m.pos.x - range, m.pos.y - range, spawn.nonCollideBossList);
}
},
tech: [{
@@ -1524,24 +1523,24 @@
tech.isMobBlockFling = false
}
},
- {
- name: "fermions",
- description: "blocks thrown by you or pilot wave will
collide with intangible mobs, but not you",
- maxCount: 1,
- count: 0,
- frequency: 2,
- frequencyDefault: 2,
- allowed() {
- return (tech.throwChargeRate > 1 || m.fieldUpgrades[m.fieldMode].name === "pilot wave") && !tech.isBlockExplosion
- },
- requires: "mass driver or pilot wave, not tokamak",
- effect() {
- tech.isBlockBullets = true
- },
- remove() {
- tech.isBlockBullets = false
- }
- },
+ // {
+ // name: "fermions",
+ // description: "blocks thrown by you or pilot wave will
collide with intangible mobs, but not you",
+ // maxCount: 1,
+ // count: 0,
+ // frequency: 2,
+ // frequencyDefault: 2,
+ // allowed() {
+ // return (tech.throwChargeRate > 1 || m.fieldUpgrades[m.fieldMode].name === "pilot wave") && !tech.isBlockExplosion
+ // },
+ // requires: "mass driver or pilot wave, not tokamak",
+ // effect() {
+ // tech.isBlockBullets = true
+ // },
+ // remove() {
+ // tech.isBlockBullets = false
+ // }
+ // },
{
name: "inflation",
description: "throwing a block expands it by 300%
increase throw charge rate by 200%",
@@ -1617,17 +1616,17 @@
},
{
name: "complex spin-statistics",
- description: `become immune to harm for 1 second
once every 7 seconds`,
+ description: `become immune to harm for 1.5 seconds
once every 7 seconds`,
maxCount: 3,
count: 0,
- frequency: 2,
- frequencyDefault: 2,
+ frequency: 1,
+ frequencyDefault: 1,
allowed() {
return true //tech.collisionImmuneCycles > 30
},
requires: "",
effect() {
- tech.cyclicImmunity += 60;
+ tech.cyclicImmunity += 90;
},
remove() {
tech.cyclicImmunity = 0;
@@ -7500,7 +7499,6 @@
isCollisionRealitySwitch: null,
iceIXOnDeath: null,
wimpCount: null,
- isBlockBullets: null,
isAddBlockMass: null,
isMACHO: null,
isHarmMACHO: null,
diff --git a/todo.txt b/todo.txt
index d07333c..e4587d3 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,59 +1,23 @@
******************************************************** NEXT PATCH ********************************************************
-2 more lore chapters (5 total now)
-entering testing mode makes a sound now
+buffBoss: group of mobs that buff their group after they die
+ this boss maybe unbalanced in some situations, let me know
+ (get them all low on health before you start killing them)
-reduced the requirements and frequency for many tech so that they may show up in "less optimal" situations
- I hope this will increase build variety and also give more value to making good tech choices
-countless bug fixes and wording fixes
+complex spin-statistics gives 1.5/7 harm immunity (was 1/7)
+ also tech frequency was halved
-mobs have a new trait mob[i].damageReduction
+tech fermions is now on by default: thrown blocks can collide with intangible mobs
+ pilot wave uses 5% more energy for balance
******************************************************** TODO ********************************************************
-
+try out making the player's "eye" a bigger circle
perfect diamagnetism field stays when you aren't holding field
good for perfect because it doesn't use energy
holding field moves it the player
-level with mobs that follow a genetic algorithm
- mobs have genes
- the last mob that did damage saves it's genes to local storage
- new mobs have the saved genes, but with some random mutations
- mutations need to be balanced to prevent a gene from moving towards infinity
- total genome must equal 1 (100%)
- binary genes have a flat cost
- example: phasing through walls might cost 0.2
- spectrum genes have a rate
- example: acceleration cost 0.01 per 0.001
- possible genes
- genes should only effect it's ability to touch the player
- so not damage?
- genome: spectrum
- acceleration
- top speed / air friction
- damageReduction
- duration?
- health decreases naturally?
- or they just go away like bullets?
- spawn rate
- look frequency / memory?
- genome: binary
- go through walls
- blink/teleport (like striker)
- grow when near target
- split into two
- shielded
- occurs in a specialized level
- named: gene lab, gene factory, genetic lab, genome facility
- in the level sequence after lab and before gauntlet?
- level ends after a period of time
- exit is hidden until time is up and it appears
- the level tests player durability/evasion
- this is a nice contrast to the final level that tests damage output, and the gauntlet which tests AoE damage
-
-
scrolling console history in pause menu?
also make tech, guns scrolling?
in testing mode console log the body you click on
@@ -261,7 +225,41 @@ is there a way to check if the player is stuck inside the map or block
******************************************************** LEVELS ********************************************************
-try out making the player's "eye" a bigger circle
+level with mobs that follow a genetic algorithm
+ mobs have genes
+ the last mob that did damage saves it's genes to local storage
+ new mobs have the saved genes, but with some random mutations
+ mutations need to be balanced to prevent a gene from moving towards infinity
+ total genome must equal 1 (100%)
+ binary genes have a flat cost
+ example: phasing through walls might cost 0.2
+ spectrum genes have a rate
+ example: acceleration cost 0.01 per 0.001
+ possible genes
+ genes should only effect it's ability to touch the player
+ so not damage?
+ genome: spectrum
+ acceleration
+ top speed / air friction
+ damageReduction
+ duration?
+ health decreases naturally?
+ or they just go away like bullets?
+ spawn rate
+ look frequency / memory?
+ genome: binary
+ go through walls
+ blink/teleport (like striker)
+ grow when near target
+ split into two
+ shielded
+ occurs in a specialized level
+ named: gene lab, gene factory, genetic lab, genome facility
+ in the level sequence after lab and before gauntlet?
+ level ends after a period of time
+ exit is hidden until time is up and it appears
+ the level tests player durability/evasion
+ this is a nice contrast to the final level that tests damage output, and the gauntlet which tests AoE damage
rename intro level to something lore related
@@ -315,12 +313,6 @@ map: observatory
******************************************************** MOBS ********************************************************
-mobs that buff the stats of mobs when they die
- nearby mobs
- boss is a group of mobs, they buff each other
- give the buff a ramp up time
- so there is an advantage to kill them all at once
-
mob that spawns eggs after they die
eggs don't attack but grow back into a mob after about 10s