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)

complex spin-statistics gives 1.5/7 harm immunity (was 1/7)
  also tech frequency was halved

tech fermions is now on by default: thrown blocks can collide with intangible mobs
  pilot wave uses 5% more energy for balance
This commit is contained in:
landgreen
2021-07-22 06:11:22 -07:00
parent 34d295cf48
commit 3f8517b27e
7 changed files with 184 additions and 110 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -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) {

View File

@@ -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

View File

@@ -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 <strong class='color-f'>energy</strong> to push <strong class='color-block'>blocks</strong> with your mouse<br>field <strong>radius</strong> decreases out of <strong>line of sight</strong><br><strong class='color-f'>energy</strong> drain scales with <strong>mass</strong>",
description: "use <strong class='color-f'>energy</strong> to push <strong class='color-block'>blocks</strong> with your mouse<br><strong class='color-block'>blocks</strong> can <strong>collide</strong> with <strong>intangible</strong> mobs<br>field <strong>radius</strong> decreases out of <strong>line of sight</strong>",
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

View File

@@ -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;

View File

@@ -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: "<strong class='color-block'>blocks</strong> thrown by you or <strong>pilot wave</strong> will<br><strong>collide</strong> with <strong>intangible</strong> 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: "<strong class='color-block'>blocks</strong> thrown by you or <strong>pilot wave</strong> will<br><strong>collide</strong> with <strong>intangible</strong> 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: "<strong>throwing</strong> a <strong class='color-block'>block</strong> expands it by <strong>300%</strong><br>increase <strong>throw</strong> charge rate by <strong>200%</strong>",
@@ -1617,17 +1616,17 @@
},
{
name: "complex spin-statistics",
description: `become <strong>immune</strong> to <strong class='color-harm'>harm</strong> for <strong>1</strong> second<br>once every <strong>7</strong> seconds`,
description: `become <strong>immune</strong> to <strong class='color-harm'>harm</strong> for <strong>1.5</strong> seconds<br>once every <strong>7</strong> 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,

View File

@@ -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