blockBoss

blockBoss: new boss based on work by TheShwarma
  (3x chance to randomly see blockBoss until next patch)
  it's over powered, I'll probably nerf it next patch, but I want to get some feedback first on how to nerf it
  hint: if you kill the boss all the mobBlocks turn back into blocks

very very small blocks are slightly limited in how fast they can be thrown
  they were moving so fast they would miss their target sometimes

tech: energy conservation gives 5% energy back (was 6%)
tech: arsenal requires at least 3 guns in your inventory
tech: active cooling requires at least 2 guns in your inventory

several bug fixes
This commit is contained in:
landgreen
2021-08-31 05:54:37 -07:00
parent 1f471cf941
commit 13cc190211
11 changed files with 271 additions and 132 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -106,7 +106,7 @@
<option value="6">why?</option>
</select>
<br>
<label for="community-maps" title="adds in maps written by n-gon player: Francois">include community maps:</label>
<label for="community-maps" title="">include community maps:</label>
<input type="checkbox" id="community-maps" name="community-maps" style="width:17px; height:17px;">
<!-- <br>
<label for="body-damage" title="allow damage from the ground and large fast moving blocks">collision damage from blocks:</label>
@@ -114,14 +114,15 @@
<br>
<label for="classic-select" title="play older versions of n-gon">classic n-gon:</label>
<select name="classic-select" id="classic-select" onChange="window.location.href=this.value">
<option value="https://scratch.mit.edu/projects/14005697/fullscreen/" selected>scratch: 2014</option>
<option value="https://scratch.mit.edu/projects/22573757/fullscreen/" selected>scratch: 2015</option>
<option value="https://codepen.io/lilgreenland/full/ozXNWZ" selected>codepen: 2016</option>
<option value="https://scratch.mit.edu/projects/14005697/fullscreen/">scratch: 2014</option>
<option value="https://scratch.mit.edu/projects/22573757/fullscreen/">scratch: 2015</option>
<option value="https://codepen.io/lilgreenland/full/ozXNWZ">codepen: 2016</option>
<option value="https://codepen.io/lilgreenland/full/wzARJY">codepen: 2016</option>
<option value="classic/7-1-2017/">n-gon: 2017</option>
<option value="classic/4-15-2018/">n-gon: 2018</option>
<option value="classic/7-11-2019/">n-gon: summer-2019</option>
<option value="classic/9-8-2019/">n-gon: fall-2019</option>
<option value="" selected>current version</option>
</select>
<br>
<label for="fps-select" title="use this to slow the game down">limit frames per second:</label>

View File

@@ -3080,13 +3080,13 @@ const b = {
minDmgSpeed: 2,
lookFrequency: 27 + Math.ceil(6 * Math.random()),
cd: 0,
delay: 80,
delay: 70,
range: 70 + 3 * b.totalBots(),
endCycle: Infinity,
classType: "bullet",
collisionFilter: {
category: cat.bullet,
mask: b.totalBots() < 50 ? cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield : cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield //if over 50 bots, they no longer collide with each other
mask: b.totalBots() < 50 ? (cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield) : (cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield) //if over 50 bots, they no longer collide with each other
},
beforeDmg() {},
onEnd() {},
@@ -5055,7 +5055,7 @@ const b = {
m.fireCDcycle = Infinity //can't fire until mouse is released
const previousCharge = this.charge
let smoothRate = (m.crouch ? 0.98 : 0.985) * (0.98 + 0.02 * b.fireCDscale) //small b.fireCDscale = faster shots, b.fireCDscale=1 = normal shot, big b.fireCDscale = slower chot
let smoothRate = Math.min(0.998, (m.crouch ? 0.98 : 0.985) * (0.98 + 0.02 * b.fireCDscale)) //small b.fireCDscale = faster shots, b.fireCDscale=1 = normal shot, big b.fireCDscale = slower chot
this.charge = this.charge * smoothRate + 1 - smoothRate
m.energy += (this.charge - previousCharge) * (tech.isRailEnergyGain ? 1 : -0.33) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen
//draw targeting

View File

@@ -109,12 +109,19 @@ const level = {
},
custom() {},
customTopLayer() {},
setDifficulty() {
simulation.difficulty = 0
b.dmgScale = 1; //damage done by player decreases each level
simulation.accelScale = 1 //mob acceleration increases each level
simulation.CDScale = 1 //mob CD time decreases each level
simulation.dmgScale = 0.41 * simulation.difficulty //damage done by mobs increases each level
simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale;
},
difficultyIncrease(num = 1) {
for (let i = 0; i < num; i++) {
simulation.difficulty++
b.dmgScale *= 0.914; //damage done by player decreases each level
if (simulation.accelScale < 5) simulation.accelScale *= 1.02 //mob acceleration increases each level
if (simulation.lookFreqScale > 0.2) simulation.lookFreqScale *= 0.98 //mob cycles between looks decreases each level
if (simulation.CDScale > 0.2) simulation.CDScale *= 0.97 //mob CD time decreases each level
}
simulation.dmgScale = 0.41 * simulation.difficulty //damage done by mobs increases each level
@@ -125,7 +132,6 @@ const level = {
simulation.difficulty--
b.dmgScale /= 0.914; //damage done by player decreases each level
if (simulation.accelScale > 0.2) simulation.accelScale /= 1.02 //mob acceleration increases each level
if (simulation.lookFreqScale < 5) simulation.lookFreqScale /= 0.98 //mob cycles between looks decreases each level
if (simulation.CDScale < 5) simulation.CDScale /= 0.97 //mob CD time decreases each level
}
if (simulation.difficulty < 1) simulation.difficulty = 0;
@@ -2266,12 +2272,13 @@ const level = {
spawn.mapRect(5050, -100, 50, 150);
spawn.mapRect(4850, -275, 50, 175);
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
spawn.starter(1900, -500, 200) //big boy
// spawn.spiderBoss(1900, -500)
// spawn.starter(1900, -500, 200) //big boy
spawn.necroBoss(1900, -500)
// for (let i = 0; i < 10; ++i) spawn.bodyRect(1600 + 5, -500, 30, 40);
// spawn.laserBombingBoss(1900, -500)
// for (let i = 0; i < 5; i++) spawn.focuser(1900, -500)
// spawn.sniper(1900, -500)
// spawn.blockGroup(1900, -500)
// spawn.grenadier(1900, -500)
// spawn.sneaker(1900, -500)
// spawn.shield(mob[mob.length - 1], 1900, -500, 1);
@@ -2286,7 +2293,7 @@ const level = {
// spawn.powerUpBoss(1600, -500)
// spawn.cellBossCulture(1600, -500)
// spawn.laserTargetingBoss(1600, -500)
// spawn.grenadierBoss(1200, -500)
// spawn.striker(1200, -500)
// spawn.nodeGroup(1200, -500, "grenadier")
// spawn.snakeBoss(1200, -500)

View File

@@ -268,7 +268,7 @@ const mobs = {
gravity() {
this.force.y += this.mass * this.g;
},
seePlayerFreq: Math.floor((30 + 30 * Math.random()) * simulation.lookFreqScale), //how often NPC checks to see where player is, lower numbers have better vision
seePlayerFreq: Math.floor(30 + 30 * Math.random()), //how often NPC checks to see where player is, lower numbers have better vision
foundPlayer() {
this.locatePlayer();
if (!this.seePlayer.yes) {
@@ -759,11 +759,6 @@ const mobs = {
attraction() {
//accelerate towards the player
if (this.seePlayer.recall) {
// && dx * dx + dy * dy < 2000000) {
// const forceMag = this.accelMag * this.mass;
// const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
// this.force.x += forceMag * Math.cos(angle);
// this.force.y += forceMag * Math.sin(angle);
const force = Vector.mult(Vector.normalise(Vector.sub(this.seePlayer.position, this.position)), this.accelMag * this.mass)
this.force.x += force.x;
this.force.y += force.y;

View File

@@ -389,12 +389,10 @@ const m = {
},
death() {
if (tech.isImmortal) { //if player has the immortality buff, spawn on the same level with randomized damage
//remove immortality tech
// for (let i = 0; i < tech.tech.length; i++) {
// if (tech.tech[i].name === "quantum immortality") tech.removeTech(i)
// }
simulation.wipe = function() { //set wipe to have trails
ctx.fillStyle = "rgba(255,255,255,0)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
@@ -480,7 +478,7 @@ const m = {
setMaxHealth() {
m.maxHealth = m.baseHealth + tech.extraMaxHealth + tech.isFallingDamage //+ tech.bonusHealth
document.getElementById("health-bg").style.width = `${Math.floor(300*m.maxHealth)}px`
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-h'>maxHealth</span> <span class='color-symbol'>=</span> ${m.maxHealth.toFixed(3)}`)
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-h'>maxHealth</span> <span class='color-symbol'>=</span> ${m.maxHealth.toFixed(2)}`)
if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth();
},
@@ -655,13 +653,12 @@ const m = {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
}, 3000);
return;
} else { //death
m.health = 0;
m.energy = 0;
m.death();
return;
}
return;
}
} else {
dmg *= m.harmReduction()
@@ -1161,7 +1158,7 @@ const m = {
const charge = Math.min(m.throwCharge / 5, 1)
//***** scale throw speed with the first number, 80 *****
let speed = 80 * charge * Math.min(1, 0.8 / Math.pow(m.holdingTarget.mass, 0.25));
let speed = 80 * charge * Math.min(0.85, 0.8 / Math.pow(m.holdingTarget.mass, 0.25));
if (Matter.Query.collides(m.holdingTarget, map).length !== 0) {
speed *= 0.7 //drop speed by 30% if touching map

View File

@@ -130,7 +130,6 @@ const simulation = {
healScale: 1,
accelScale: null, //set in levels.setDifficulty
CDScale: null, //set in levels.setDifficulty
lookFreqScale: null, //set in levels.setDifficulty
isNoPowerUps: false,
// dropFPS(cap = 40, time = 15) {
// simulation.fpsCap = cap
@@ -541,10 +540,6 @@ const simulation = {
if (simulation.onTitlePage) requestAnimationFrame(cycle);
}
requestAnimationFrame(cycle)
}, 1000);
},
startGame(isBuildRun = false) {
@@ -617,6 +612,7 @@ const simulation = {
tech.plasmaBotCount = 0;
tech.missileBotCount = 0;
simulation.isChoosing = false;
b.setFireMethod()
b.setFireCD();
// simulation.updateTechHUD();
@@ -641,20 +637,25 @@ const simulation = {
level.onLevel = 0;
level.levelsCleared = 0;
//resetting difficulty
simulation.dmgScale = 0; //increases in level.difficultyIncrease
b.dmgScale = 1; //decreases in level.difficultyIncrease
simulation.accelScale = 1;
simulation.lookFreqScale = 1;
simulation.CDScale = 1;
simulation.difficulty = 0;
simulation.difficultyMode = Number(document.getElementById("difficulty-select").value)
build.isExperimentSelection = false;
//resetting difficulty
// simulation.difficulty = 0;
level.setDifficulty()
simulation.difficultyMode = Number(document.getElementById("difficulty-select").value)
build.isExperimentSelection = false;
simulation.clearNow = true;
document.getElementById("text-log").style.opacity = 0;
document.getElementById("fade-out").style.opacity = 0;
document.title = "n-gon";
// simulation.makeTextLog(`input.key.up<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.up}</span>", "<span class='color-text'>ArrowUp</span>"]`);
// simulation.makeTextLog(`input.key.left<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.left}</span>", "<span class='color-text'>ArrowLeft</span>"]`);
// simulation.makeTextLog(`input.key.down<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.down}</span>", "<span class='color-text'>ArrowDown</span>"]`);
// simulation.makeTextLog(`input.key.right<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.right}</span>", "<span class='color-text'>ArrowRight</span>"]`);
simulation.makeTextLog(`<span class='color-var'>const</span> engine <span class='color-symbol'>=</span> Engine.create(); <em>//simulation begin</em>`);
simulation.makeTextLog(`engine.timing.timeScale <span class='color-symbol'>=</span> 1`);
simulation.makeTextLog(`<span class='color-var'>m</span>.setField("<span class='color-text'>${m.fieldUpgrades[m.fieldMode].name}</span>")`);
// simulation.makeTextLog(`input.key.field<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.field}</span>", "<span class='color-text'>MouseRight</span>"]`);
document.getElementById("health").style.display = "inline"
document.getElementById("health-bg").style.display = "inline"
@@ -668,6 +669,7 @@ const simulation = {
//set to default field
tech.healMaxEnergyBonus = 0
m.setMaxEnergy();
m.energy = 0
m.fieldMode = 0;
// simulation.makeTextLog(`${simulation.SVGrightMouse}<strong style='font-size:30px;'> ${m.fieldUpgrades[m.fieldMode].name}</strong><br><span class='faded'></span><br>${m.fieldUpgrades[m.fieldMode].description}`, 600);
// simulation.makeTextLog(`
@@ -681,28 +683,6 @@ const simulation = {
// <br><span class='color-var'>m</span>.field.description <span class='color-symbol'>=</span> "<span class='color-text'>${m.fieldUpgrades[m.fieldMode].description}</span>"
// `, 800);
let delay = 500
const step = 150
setTimeout(function() {
simulation.makeTextLog(`input.key.up<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.up}</span>", "<span class='color-text'>ArrowUp</span>"]`);
}, delay += step);
setTimeout(function() {
simulation.makeTextLog(`input.key.left<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.left}</span>", "<span class='color-text'>ArrowLeft</span>"]`);
}, delay += step);
setTimeout(function() {
simulation.makeTextLog(`input.key.down<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.down}</span>", "<span class='color-text'>ArrowDown</span>"]`);
}, delay += step);
setTimeout(function() {
simulation.makeTextLog(`input.key.right<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.right}</span>", "<span class='color-text'>ArrowRight</span>"]`);
}, delay += step);
setTimeout(function() {
simulation.makeTextLog(`<br><span class='color-var'>m</span>.fieldMode <span class='color-symbol'>=</span> "<span class='color-text'>${m.fieldUpgrades[m.fieldMode].name}</span>"`);
}, delay += step);
setTimeout(function() {
simulation.makeTextLog(`input.key.field<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.field}</span>", "<span class='color-text'>MouseRight</span>"]`);
}, delay += step);
m.setField(m.fieldMode)
// m.energy = 0;
//exit testing
@@ -718,7 +698,6 @@ const simulation = {
simulation.fpsInterval = 1000 / simulation.fpsCap;
simulation.then = Date.now();
requestAnimationFrame(cycle); //starts game loop
},
clearTimeouts() {
let id = window.setTimeout(function() {}, 0);

View File

@@ -1,7 +1,7 @@
//main object for spawning things in a level
const spawn = {
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture", "growBossCulture"],
randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", "snakeSpitBoss", "laserBombingBoss"]) {
randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", "snakeSpitBoss", "laserBombingBoss", "blockBoss", "blockBoss", "blockBoss"]) {
// 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)
},
@@ -54,7 +54,7 @@ const spawn = {
}
},
randomGroup(x, y, chance = 1) {
if (spawn.spawnChance(chance) && simulation.difficulty > 2 || chance == Infinity) {
if (spawn.spawnChance(chance) && simulation.difficulty > 2 || chance === Infinity) {
//choose from the possible picklist
let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
//is the pick able to be a group?
@@ -664,23 +664,38 @@ const spawn = {
}
}
},
starter(x, y, radius = Math.floor(15 + 20 * Math.random())) { //easy mob for on level 1
mobs.spawn(x, y, 8, radius, "#9ccdc6");
let me = mob[mob.length - 1];
// console.log(`mass=${me.mass}, radius = ${radius}`)
me.accelMag = 0.0002
me.repulsionRange = 100000 + radius * radius; //squared
// 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() {
this.seePlayerByLookingAt();
this.attraction();
this.repulsion();
this.checkStatus();
};
},
blockGroup(x, y, num = 3 + Math.random() * 8) {
for (let i = 0; i < num; i++) {
const radius = 25 + Math.floor(Math.random() * 20)
spawn.grouper(x + Math.random() * radius, y + Math.random() * radius, radius);
spawn.blockGroupMob(x + Math.random() * radius, y + Math.random() * radius, radius);
}
},
grouper(x, y, radius = 25 + Math.floor(Math.random() * 20)) {
mobs.spawn(x, y, 4, radius, "#777");
blockGroupMob(x, y, radius = 25 + Math.floor(Math.random() * 20)) {
mobs.spawn(x, y, 4, radius, "#999");
let me = mob[mob.length - 1];
me.g = 0.00015; //required if using 'gravity'
me.g = 0.00015; //required if using this.gravity
me.accelMag = 0.0008 * simulation.accelScale;
me.groupingRangeMax = 250000 + Math.random() * 100000;
me.groupingRangeMin = (radius * 8) * (radius * 8);
me.groupingStrength = 0.0005
me.memory = 200;
me.isGrouper = true;
me.do = function() {
this.gravity();
this.checkStatus();
@@ -705,28 +720,159 @@ const spawn = {
}
}
}
ctx.strokeStyle = "#000";
ctx.strokeStyle = "#0ff";
ctx.lineWidth = 1;
ctx.stroke();
}
}
},
starter(x, y, radius = Math.floor(15 + 20 * Math.random())) {
//easy mob for on level 1
mobs.spawn(x, y, 8, radius, "#9ccdc6");
let me = mob[mob.length - 1];
// console.log(`mass=${me.mass}, radius = ${radius}`)
me.accelMag = 0.0002
me.repulsionRange = 100000 + radius * radius; //squared
// 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
blockBoss(x, y, radius = 30) {
const activeBeams = []; // used to draw beams when converting
const beamTotalDuration = 60
mobs.spawn(x, y, 4, radius, "#999"); //#54291d
const me = mob[mob.length - 1];
me.isBoss = true;
// Matter.Body.setDensity(me, 0.001); //normal density even though its a boss
me.damageReduction = 0.06; //extra reduction for a boss, because normal density
me.frictionAir = 0.01;
me.accelMag = 0.0002;
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
who.leaveBody = true
who.damage(Infinity)
}
}
}
me.target = player; // the target to lock on. Usually a block, but will be the player under certain conditions
me.do = function() {
this.seePlayerByLookingAt();
this.attraction();
this.repulsion();
this.checkStatus();
};
this.seePlayerCheck();
if (this.target) { //(this.target === player && this.seePlayer.yes) || this.target !== player
const force = Vector.mult(Vector.normalise(Vector.sub(this.target.position, this.position)), this.accelMag * this.mass)
this.force.x += force.x;
this.force.y += force.y;
}
if (!(simulation.cycle % 30) && !m.isBodiesAsleep) {
//find blocks to turn into mobs
for (let i = 0; i < body.length; i++) {
if (Vector.magnitude(Vector.sub(this.position, body[i].position)) < 700 && !body[i].isNotHoldable) { // check distance for each block
Matter.Composite.remove(engine.world, body[i]);
this.target = null //player;
spawn.blockMob(body[i].position.x, body[i].position.y, body[i], 0);
body.splice(i, 1);
activeBeams.push([beamTotalDuration, mob[mob.length - 1]]);
}
}
// generally, the boss will tend to stay in the player's area but focus on blocks.
if (this.distanceToPlayer() > 1500 && this.target === null) {
this.target = player; // too far, attract to the player
} else {
if (body.length) { // look for a new target by finding the closest block
let min = Infinity;
let closestBlock = null;
for (const block of body) {
const dist = Vector.magnitudeSquared(Vector.sub(this.position, block.position))
if (dist < min && Matter.Query.ray(map, this.position, block.position).length === 0) {
min = dist;
closestBlock = block;
}
}
this.target = closestBlock;
}
}
//randomly spawn new mobs from nothing
if (!(simulation.cycle % 120)) {
let count = 0
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].isNecroMob) count++
}
if (count < 12 * Math.random() * Math.random()) { //limit number of spawns if there are already too many blockMobs
const unit = Vector.normalise(Vector.sub(player.position, this.position))
for (let i = 0, len = 3 * Math.random(); i < len; i++) {
const where = Vector.add(Vector.mult(unit, radius + 200 * Math.random()), this.position)
spawn.blockMob(where.x + 100 * (Math.random() - 0.5), where.y + 100 * (Math.random() - 0.5), null);
this.torque += 0.000035 * this.inertia; //spin after spawning
activeBeams.push([beamTotalDuration, mob[mob.length - 1]]);
}
}
}
}
for (let i = 0; i < activeBeams.length; i++) { // draw beams on new mobs
const [duration, newBlockMob] = activeBeams[i];
if (duration === 0) {
activeBeams.splice(i, 1);
continue;
}
if (newBlockMob.alive) {
const vertexIndex = Math.floor((newBlockMob.vertices.length - 1) * duration / beamTotalDuration)
ctx.beginPath();
ctx.moveTo(this.position.x, this.position.y);
ctx.lineTo(newBlockMob.vertices[vertexIndex].x, newBlockMob.vertices[vertexIndex].y);
//outline mob
ctx.moveTo(newBlockMob.vertices[0].x, newBlockMob.vertices[0].y);
for (let j = 1; j < newBlockMob.vertices.length; j++) {
ctx.lineTo(newBlockMob.vertices[j].x, newBlockMob.vertices[j].y);
}
ctx.lineTo(newBlockMob.vertices[0].x, newBlockMob.vertices[0].y);
ctx.strokeStyle = "#0ff";
ctx.lineWidth = 3;
ctx.stroke();
}
activeBeams[i][0]--; // shorten duration
}
}
},
blockMob(x, y, host, growCycles = 60) {
if (host === null) {
mobs.spawn(x, y, 4, 1.25 + 3.5 * Math.random(), "#999");
} else {
const sideLength = Vector.magnitude(Vector.sub(host.vertices[0], host.vertices[1])) + Vector.magnitude(Vector.sub(host.vertices[1], host.vertices[2])) / 2 //average of first 2 sides
mobs.spawn(x, y, 4, Math.min(70, sideLength), "#999");
if (host.bounds.max.x - host.bounds.min.x < 150 && host.bounds.max.y - host.bounds.min.y < 150) {
Matter.Body.setVertices(mob[mob.length - 1], host.vertices) //if not too big match vertices of host exactly
// mob[mob.length - 1].radius =
}
}
const me = mob[mob.length - 1];
me.damageReduction = 0.5; //only until done growing
me.isNecroMob = true
me.g = 0.00012; //required if using this.gravity
me.accelMag = 0.0003 * Math.sqrt(simulation.accelScale);
me.memory = 120;
me.leaveBody = false;
me.isDropPowerUp = false;
// me.showHealthBar = false;
me.cycle = 0
me.do = function() { //grow phase only occurs for growCycles
this.checkStatus();
this.seePlayerCheck();
if (!m.isBodiesAsleep) {
this.cycle++
if (this.cycle > growCycles) {
this.damageReduction = 1.8 //take extra damage
this.do = this.normalDo
} else {
const scale = 1.04; //if 120 use 1.02
Matter.Body.scale(this, scale, scale);
this.radius *= scale;
}
}
}
me.normalDo = function() {
this.gravity();
this.checkStatus();
this.seePlayerCheck();
this.attraction();
}
},
cellBossCulture(x, y, radius = 20, num = 5) {
const cellID = Math.random()
@@ -1043,7 +1189,7 @@ const spawn = {
// me.friction = 0.1;
// me.frictionAir = 0;
// me.accelMag = 0.001 * Math.sqrt(simulation.accelScale);
// me.g = me.accelMag * 0.6; //required if using 'gravity'
// me.g = me.accelMag * 0.6; //required if using this.gravity
// me.memory = 180;
// spawn.shield(me, x, y);
// me.do = function() {
@@ -1076,8 +1222,8 @@ const spawn = {
me.friction = 0;
me.frictionAir = 0.006;
me.lookTorque = 0.0000008; //controls spin while looking for player
me.g = 0.0002; //required if using 'gravity'
me.seePlayerFreq = Math.round((40 + 25 * Math.random()) * simulation.lookFreqScale);
me.g = 0.0002; //required if using this.gravity
me.seePlayerFreq = Math.floor((40 + 25 * Math.random()));
const springStiffness = 0.00014;
const springDampening = 0.0005;
@@ -1127,7 +1273,7 @@ const spawn = {
mobs.spawn(x, y, 5, radius, "rgb(0,200,180)");
let me = mob[mob.length - 1];
me.accelMag = 0.04;
me.g = 0.0017; //required if using 'gravity'
me.g = 0.0017; //required if using this.gravity
me.frictionAir = 0.01;
me.friction = 1
me.frictionStatic = 1
@@ -1167,7 +1313,7 @@ const spawn = {
let me = mob[mob.length - 1];
me.isBoss = true;
me.g = 0.005; //required if using 'gravity'
me.g = 0.005; //required if using this.gravity
me.frictionAir = 0.01;
me.friction = 1
me.frictionStatic = 1
@@ -1505,8 +1651,8 @@ const spawn = {
me.friction = 0;
me.frictionAir = 0.0067;
me.lookTorque = 0.0000008; //controls spin while looking for player
me.g = 0.0002; //required if using 'gravity'
me.seePlayerFreq = Math.round((30 + 20 * Math.random()) * simulation.lookFreqScale);
me.g = 0.0002; //required if using this.gravity
me.seePlayerFreq = Math.floor((30 + 20 * Math.random()));
const springStiffness = 0.00014;
const springDampening = 0.0005;
@@ -1865,7 +2011,7 @@ 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.00018 * Math.sqrt(simulation.accelScale);
me.seePlayerFreq = Math.floor(30 * simulation.lookFreqScale);
me.seePlayerFreq = 30
me.memory = 420;
me.restitution = 1;
me.frictionAir = 0.01;
@@ -2006,7 +2152,7 @@ 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.00055 * Math.sqrt(simulation.accelScale);
me.seePlayerFreq = Math.floor(30 * simulation.lookFreqScale);
me.seePlayerFreq = 30;
me.memory = 420;
me.restitution = 1;
me.frictionAir = 0.05;
@@ -2634,7 +2780,7 @@ const spawn = {
let me = mob[mob.length - 1];
me.isVerticesChange = true
me.accelMag = 0.0006 * simulation.accelScale;
// me.g = 0.0002; //required if using 'gravity'
// me.g = 0.0002; //required if using this.gravity
me.delay = 360 * simulation.CDScale;
me.spikeVertex = 0;
me.spikeLength = 0;
@@ -2712,7 +2858,7 @@ const spawn = {
mobs.spawn(x, y, 5, radius, "rgb(221,102,119)");
let me = mob[mob.length - 1];
me.accelMag = 0.00034 * simulation.accelScale;
me.g = 0.00015; //required if using 'gravity'
me.g = 0.00015; //required if using this.gravity
me.frictionStatic = 0;
me.friction = 0;
me.delay = 90 * simulation.CDScale;
@@ -2768,7 +2914,7 @@ const spawn = {
Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
me.accelMag = 0.001 * Math.sqrt(simulation.accelScale);
me.frictionAir = 0.01;
me.g = 0.0002; //required if using 'gravity'
me.g = 0.0002; //required if using this.gravity
me.stroke = "transparent"; //used for drawSneaker
me.alpha = 1; //used in drawSneaker
// me.leaveBody = false;
@@ -2882,7 +3028,7 @@ const spawn = {
// me.blinkLength = 150 + Math.round(Math.random() * 200); //required for blink
// me.isStatic = true;
// me.memory = 360;
// me.seePlayerFreq = Math.round((40 + 30 * Math.random()) * simulation.lookFreqScale);
// me.seePlayerFreq = Math.round((40 + 30 * Math.random()));
// // me.isBig = false;
// // me.scaleMag = Math.max(5 - me.mass, 1.75);
// me.onDeath = function () {
@@ -2931,7 +3077,7 @@ const spawn = {
me.hoverElevation = 460 + (Math.random() - 0.5) * 200; //squared
me.hoverXOff = (Math.random() - 0.5) * 100;
me.accelMag = Math.floor(10 * (Math.random() + 4.5)) * 0.00001 * simulation.accelScale;
me.g = 0.0002; //required if using 'gravity' // gravity called in hoverOverPlayer
me.g = 0.0002; //required if using this.gravity // gravity called in hoverOverPlayer
me.frictionStatic = 0;
me.friction = 0;
me.frictionAir = 0.01;
@@ -3062,7 +3208,7 @@ const spawn = {
};
Matter.Body.setDensity(me, 0.00004); //normal is 0.001
me.timeLeft = 200;
me.g = 0.001; //required if using 'gravity'
me.g = 0.001; //required if using this.gravity
me.frictionAir = 0;
me.restitution = 0.8;
me.leaveBody = false;
@@ -3114,7 +3260,7 @@ const spawn = {
}
Matter.Body.setDensity(me, 0.00005); //normal is 0.001
me.timeLeft = 140 + Math.floor(Math.random() * 30);
me.g = 0.001; //required if using 'gravity'
me.g = 0.001; //required if using this.gravity
me.frictionAir = 0;
me.restitution = 1;
me.leaveBody = false;
@@ -3254,7 +3400,7 @@ const spawn = {
};
Matter.Body.setDensity(me, 0.00005); //normal is 0.001
me.timeLeft = 120;
// me.g = 0.0005; //required if using 'gravity'
// me.g = 0.0005; //required if using this.gravity
me.frictionAir = 0;
me.restitution = 0;
me.leaveBody = false;
@@ -3486,7 +3632,7 @@ const spawn = {
me.lifeSpan = lifeSpan;
me.timeLeft = me.lifeSpan;
// me.g = 0.0002; //required if using 'gravity'
// me.g = 0.0002; //required if using this.gravity
me.frictionAir = 0;
me.restitution = 0.8;
me.leaveBody = false;
@@ -3701,7 +3847,7 @@ const spawn = {
spawner(x, y, radius = 55 + Math.ceil(Math.random() * 50)) {
mobs.spawn(x, y, 4, radius, "rgb(255,150,0)");
let me = mob[mob.length - 1];
me.g = 0.0004; //required if using 'gravity'
me.g = 0.0004; //required if using this.gravity
me.leaveBody = false;
// me.isDropPowerUp = false;
me.onDeath = function() { //run this function on death
@@ -3731,12 +3877,12 @@ const spawn = {
me.collisionFilter.mask = cat.player | cat.bullet | cat.body | cat.map | cat.mob
me.showHealthBar = false;
Matter.Body.setDensity(me, 0.0001); //normal is 0.001
me.g = 0.00002; //required if using 'gravity'
me.g = 0.00002; //required if using this.gravity
me.accelMag = 0.00012 * simulation.accelScale;
// me.memory = 30;
me.isDropPowerUp = false
me.leaveBody = false;
me.seePlayerFreq = Math.round((80 + 50 * Math.random()) * simulation.lookFreqScale);
me.seePlayerFreq = Math.floor((80 + 50 * Math.random()));
me.frictionAir = 0.004;
me.do = function() {
this.gravity();
@@ -3755,7 +3901,7 @@ const spawn = {
// me.onHit = function() { //run this function on hitting player
// this.explode();
// };
// me.g = 0.0003; //required if using 'gravity'
// me.g = 0.0003; //required if using this.gravity
// me.seePlayerFreq = 50 + Math.floor(Math.random() * 20)
// me.do = function() {
// this.gravity();
@@ -3799,7 +3945,7 @@ const spawn = {
//run this function on hitting player
this.explode();
};
me.g = 0.0004; //required if using 'gravity'
me.g = 0.0004; //required if using this.gravity
me.do = function() {
this.gravity();
this.seePlayerCheck();
@@ -3807,7 +3953,7 @@ const spawn = {
this.attraction();
};
},
snakeSpitBoss(x, y, radius = 50) { //snake boss with a laser head
snakeSpitBoss(x, y, radius = 50) {
const nodes = Math.min(8 + Math.ceil(0.5 * simulation.difficulty), 40)
let angle = Math.PI
let mag = 300
@@ -3834,14 +3980,14 @@ const spawn = {
me.closestVertex1 = 0;
// me.closestVertex2 = 1;
me.cycle = 0
me.damageReduction = 0.25
me.damageReduction = 0.2
me.do = function() {
// this.armor();
this.seePlayerByHistory()
this.checkStatus();
this.attraction();
this.cycle++
if (this.seePlayer.recall && ((this.cycle % 15) === 0) && !m.isBodiesAsleep) {
if (this.seePlayer.recall && ((this.cycle % 10) === 0) && !m.isBodiesAsleep) {
if (this.canFire) {
if (this.cycle > 120) {
this.cycle = 0
@@ -4032,7 +4178,7 @@ const spawn = {
let me = mob[mob.length - 1];
me.isBoss = true;
me.g = 0.0001; //required if using 'gravity'
me.g = 0.0001; //required if using this.gravity
me.accelMag = 0.002 * simulation.accelScale;
me.memory = 20;
Matter.Body.setDensity(me, 0.0005 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger

View File

@@ -306,9 +306,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
return b.inventory.length > 0
return b.inventory.length > 2
},
requires: "at least 1 gun",
requires: "at least 3 guns",
effect() {
tech.isDamageForGuns = true;
},
@@ -324,9 +324,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
return b.inventory.length > 0
return b.inventory.length > 1
},
requires: "at least 1 gun",
requires: "at least 2 guns",
effect() {
tech.isFireRateForGuns = true;
b.setFireCD();
@@ -2405,7 +2405,7 @@
},
{
name: "energy conservation",
description: "<strong>6%</strong> of <strong class='color-d'>damage</strong> done recovered as <strong class='color-f'>energy</strong>",
description: "<strong>5%</strong> of <strong class='color-d'>damage</strong> done recovered as <strong class='color-f'>energy</strong>",
maxCount: 9,
count: 0,
frequency: 1,
@@ -2415,7 +2415,7 @@
},
requires: "",
effect() {
tech.energySiphon += 0.06;
tech.energySiphon += 0.05;
},
remove() {
tech.energySiphon = 0;
@@ -5053,7 +5053,7 @@
},
remove() {
tech.laserFieldDrain = 0.002;
tech.laserDamage = 0.16; //used in check on pulse: tech.laserDamage === 0.15
tech.laserDamage = 0.16; //used in check on pulse: tech.laserDamage === 0.16
tech.laserColor = "#f00"
tech.laserColorAlpha = "rgba(255, 0, 0, 0.5)"
}
@@ -5219,7 +5219,7 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDamage === 0.15
return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDamage === 0.16
},
requires: "laser gun, not specular reflection, diffuse, free-electron laser",
effect() {

View File

@@ -725,7 +725,7 @@ summary {
height: 11px;
border-radius: 50%;
display: inline-block;
background-color: #578;
background-color: #467;
border: 0.5px #fff solid;
opacity: 0.95;
margin-bottom: -2px;

View File

@@ -1,26 +1,40 @@
******************************************************** NEXT PATCH **************************************************
orbs replaces some power up text descriptions
blockBoss: new boss based on work by TheShwarma
(3x chance to randomly see blockBoss until next patch)
it's over powered, I'll probably nerf it next patch, but I want to get some feedback first on how to nerf it
hint: if you kill the boss all the mobBlocks turn back into blocks
player damage taken is increased by 1%
finalBoss ramps up the mob spawns more slowly, making lower damage high survival builds more effective on the finalBoss
5% laser damage increase
15% mine fire rate reduction
very very small blocks are slightly limited in how fast they can be thrown
they were moving so fast they would miss their target sometimes
ctx.clip() is back for metamaterial cloaking field
it wasn't the source of the lag, firefox is just slow on my work computer
tech: buckling was disallowed, but I fixed it so you can get the tech again
tech: energy conservation gives 5% energy back (was 6%)
tech: arsenal requires at least 3 guns in your inventory
tech: active cooling requires at least 2 guns in your inventory
several bug fixes
******************************************************** TODO ********************************************************
fix simulation.CDScale // it's always zero so it does nothing
some mobs can't see player...
3 laser boss isn't rotating...
it's always null
you shouldn't of removes lookFrequency scale var...
tech remove all JUNK tech
but you can't research
maybe spend research
tech missiles - move faster and more accurately, turn sharper
also some other bonus:
damage? or size which is basically damage
experiment and understand vibe more obvious
mostly in early game or first time players
slow down throw speed for very small blocks a bit
necrophage isn't working.....
work on necroBoss from TheShwarma
work on blockBoss from TheShwarma
make spawned blocks in the direction of the player
make it search the level for blocks, but also kinda avoid the player