propagator
tech: propagator - 67% damage, lose 1/2 second of time when a mob dies timeSkipBoss is back, maybe it will not cause bugs this time immune to harm unless player is inside horizon player loses time when inside horizon snake bosses are immune to harm until your remove their tail mob shields are 30% stronger time dilation: retrocausality automatically grabs power ups eternalism 50->40% damage paradigm shift 10->16% chance to get a research when ejecting tech reaction inhibitor 11->13% mob health reduction recycling 1->0.5% health for 5 seconds up to 2.5% per mob kill at normal max health bug fixes
This commit is contained in:
14
js/bullet.js
14
js/bullet.js
@@ -2109,10 +2109,10 @@ const b = {
|
||||
onEnd() {},
|
||||
do() {
|
||||
if (this.endCycle < simulation.cycle + 1) this.isWave = false
|
||||
if (Matter.Query.point(map, this.position).length) { //check if inside map
|
||||
if (Matter.Query.point(map, this.position).length) { //check if inside map //|| Matter.Query.point(body, this.position).length
|
||||
this.isBranch = true;
|
||||
this.do = () => { if (this.endCycle < simulation.cycle + 1) this.isWave = false }
|
||||
} else { //check if inside a body
|
||||
} else { //check if inside a mob
|
||||
for (let i = 0, len = mob.length; i < len; i++) {
|
||||
const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position))
|
||||
const radius = mob[i].radius + tech.extruderRange / 2
|
||||
@@ -2387,14 +2387,14 @@ const b = {
|
||||
}
|
||||
if (tech.isLaserPush) { //push mobs away
|
||||
const index = path.length - 1
|
||||
Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.94, y: best.who.velocity.y * 0.94 });
|
||||
const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.006 * push * Math.min(6, best.who.mass))
|
||||
Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.95, y: best.who.velocity.y * 0.95 });
|
||||
const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.005 * push * Math.min(6, best.who.mass))
|
||||
Matter.Body.applyForce(best.who, path[index], force)
|
||||
}
|
||||
} else if (tech.isLaserPush && best.who.classType === "body") {
|
||||
const index = path.length - 1
|
||||
Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.94, y: best.who.velocity.y * 0.94 });
|
||||
const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.006 * push * Math.min(6, best.who.mass))
|
||||
Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.95, y: best.who.velocity.y * 0.95 });
|
||||
const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.005 * push * Math.min(6, best.who.mass))
|
||||
Matter.Body.applyForce(best.who, path[index], force)
|
||||
}
|
||||
};
|
||||
@@ -6996,7 +6996,7 @@ const b = {
|
||||
x: 7.5 * Math.cos(m.angle - Math.PI / 2),
|
||||
y: 7.5 * Math.sin(m.angle - Math.PI / 2)
|
||||
}
|
||||
const dmg = 0.66 * tech.laserDamage // 3.5 * 0.55 = 200% more damage
|
||||
const dmg = 0.70 * tech.laserDamage // 3.5 * 0.55 = 200% more damage
|
||||
const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
|
||||
const eye = {
|
||||
x: m.pos.x + 15 * Math.cos(m.angle),
|
||||
|
||||
@@ -198,7 +198,7 @@ function collisionChecks(event) {
|
||||
const v = Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity));
|
||||
if (v > 9) {
|
||||
if (tech.blockDmg) { //electricity
|
||||
console.log("hi")
|
||||
// console.log("hi")
|
||||
Matter.Body.setVelocity(mob[k], { x: 0.5 * mob[k].velocity.x, y: 0.5 * mob[k].velocity.y });
|
||||
if (tech.isBlockRadiation && !mob[k].isShielded && !mob[k].isMobBullet) {
|
||||
mobs.statusDoT(mob[k], tech.blockDmg * m.dmgScale * 4 / 12, 360) //200% increase -> x (1+2) //over 7s -> 360/30 = 12 half seconds -> 3/12
|
||||
|
||||
@@ -187,7 +187,7 @@ window.addEventListener('load', () => {
|
||||
const canvas = document.getElementById("canvas");
|
||||
//using "const" causes problems in safari when an ID shares the same name.
|
||||
const ctx = canvas.getContext("2d");
|
||||
// const ctx = canvas.getContext('2d', { alpha: false }); //optimization, but doesn't work
|
||||
// const ctx = canvas.getContext('2d', { alpha: false }); //optimization, this works if you wipe with the background color of each level
|
||||
|
||||
document.body.style.backgroundColor = "#fff";
|
||||
|
||||
@@ -278,7 +278,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
|
||||
if (tech.tech[i].count > 0) {
|
||||
const techCountText = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
|
||||
if (tech.tech[i].isNonRefundable) {
|
||||
text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" style = "border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; padding-top: 6px; padding-bottom: 6px;"><div class="grid-title">${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
|
||||
text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" style = "border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; margin: 1px; padding-top: 6px; padding-bottom: 6px;"><div class="grid-title">${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
|
||||
} else if (tech.tech[i].isFieldTech) {
|
||||
text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" ${style}><div class="grid-title">
|
||||
<span style="position:relative;">
|
||||
|
||||
18
js/level.js
18
js/level.js
@@ -17,10 +17,10 @@ const level = {
|
||||
if (level.levelsCleared === 0) { //this code only runs on the first level
|
||||
// // simulation.isHorizontalFlipped = true
|
||||
// m.addHealth(Infinity)
|
||||
// m.setField("standing wave")
|
||||
// m.setField("time dilation")
|
||||
// b.giveGuns("nail gun")
|
||||
// tech.giveTech("closed timelike curve")
|
||||
// tech.giveTech("irradiated nails")
|
||||
// tech.giveTech("retrocausality")
|
||||
// tech.giveTech("pneumatic actuator")
|
||||
// tech.giveTech("6s half-life")
|
||||
// for (let i = 0; i < 10; i++) tech.giveTech("replication")
|
||||
@@ -36,8 +36,8 @@ const level = {
|
||||
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
|
||||
// simulation.enableConstructMode() //used to build maps in testing mode
|
||||
// level.testing();
|
||||
// level.reactor(); //not in rotation, used for testing
|
||||
// spawn.timeBoss(1900, -500)
|
||||
// spawn.snakeSpitBoss(1900, -500)
|
||||
// level.reservoir(); //not in rotation, used for testing
|
||||
|
||||
if (simulation.isTraining) { level.walk(); } else { level.intro(); } //normal starting level ************************************************
|
||||
// powerUps.research.changeRerolls(3000)
|
||||
@@ -2681,7 +2681,7 @@ const level = {
|
||||
// spawn.shieldingBoss(1700, -500)
|
||||
|
||||
// for (let i = 0; i < 10; ++i) spawn.bodyRect(1600 + 5, -500, 30, 40);
|
||||
// for (let i = 0; i < 4; i++) spawn.starter(1900, -500)
|
||||
for (let i = 0; i < 4; i++) spawn.starter(1900, -500)
|
||||
// spawn.pulsar(1900, -500)
|
||||
// spawn.shield(mob[mob.length - 1], 1900, -500, 1);
|
||||
// mob[mob.length - 1].isShielded = true
|
||||
@@ -3294,8 +3294,8 @@ const level = {
|
||||
}
|
||||
|
||||
//2nd floor
|
||||
spawn.mapVertex(855, -1936, "-612 50 0 100 612 50 612 -50 -612 -50");
|
||||
spawn.mapVertex(-687, -1936, "-612 50 0 100 612 50 612 -50 -612 -50");
|
||||
spawn.mapVertex(-687, -1936, "-625 50 0 100 625 50 625 -50 -625 -50");
|
||||
spawn.mapVertex(855, -1936, "-625 50 0 100 625 50 625 -50 -625 -50");
|
||||
|
||||
//2nd floor right building
|
||||
// spawn.mapRect(550, -3050, 600, 175);
|
||||
@@ -3328,11 +3328,11 @@ const level = {
|
||||
spawn.randomMob(950, -1725, 0.1);
|
||||
spawn.randomMob(-725, -1775, 0.1);
|
||||
spawn.randomMob(-200, -2075, 0);
|
||||
spawn.randomMob(-550, -3500, -0.2);
|
||||
spawn.randomMob(375, -2125, 0);
|
||||
spawn.randomMob(1025, -3200, 0);
|
||||
spawn.randomMob(-550, -3500, 0);
|
||||
spawn.randomMob(-700, -2450, -0.1);
|
||||
spawn.randomMob(-1175, -2775, -0.1);
|
||||
spawn.randomMob(1025, -3200, -0.2);
|
||||
spawn.randomMob(-525, -3750, -0.2);
|
||||
spawn.randomMob(1350, -2075, -0.3);
|
||||
spawn.randomMob(1775, 1000, -0.4);
|
||||
|
||||
18
js/mob.js
18
js/mob.js
@@ -1119,7 +1119,7 @@ const mobs = {
|
||||
if (tech.iceIXOnDeath && this.isSlowed) {
|
||||
for (let i = 0, len = 2 * Math.sqrt(Math.min(this.mass, 25)) * tech.iceIXOnDeath; i < len; i++) b.iceIX(3, Math.random() * 2 * Math.PI, this.position)
|
||||
}
|
||||
if (tech.deathSpawnsFromBoss || (tech.deathSpawns && this.isDropPowerUp)) {
|
||||
if (tech.deathSpawnsFromBoss || tech.deathSpawns) {
|
||||
const spawns = tech.deathSpawns + tech.deathSpawnsFromBoss
|
||||
const len = Math.min(12, spawns * Math.ceil(Math.random() * simulation.difficulty * spawns))
|
||||
for (let i = 0; i < len; i++) {
|
||||
@@ -1130,6 +1130,22 @@ const mobs = {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (tech.isDeathSkipTime && !m.isBodiesAsleep) {
|
||||
requestAnimationFrame(() => {
|
||||
simulation.timePlayerSkip(this.isBoss ? 45 : 25)
|
||||
simulation.loop(); //ending with a wipe and normal loop fixes some very minor graphical issues where things are draw in the wrong locations
|
||||
}); //wrapping in animation frame prevents errors, probably
|
||||
|
||||
// if (tech.isFlipFlopOn) {
|
||||
// m.rewind(this.isBoss ? 45 : 25)
|
||||
// } else {
|
||||
// requestAnimationFrame(() => {
|
||||
// simulation.timePlayerSkip(this.isBoss ? 45 : 25)
|
||||
// simulation.loop(); //ending with a wipe and normal loop fixes some very minor graphical issues where things are draw in the wrong locations
|
||||
// }); //wrapping in animation frame prevents errors, probably
|
||||
// }
|
||||
}
|
||||
if (tech.isEnergyLoss) m.energy *= 0.75;
|
||||
powerUps.spawnRandomPowerUp(this.position.x, this.position.y);
|
||||
m.lastKillCycle = m.cycle; //tracks the last time a kill was made, mostly used in simulation.checks()
|
||||
|
||||
37
js/player.js
37
js/player.js
@@ -2529,6 +2529,25 @@ const m = {
|
||||
this.rewindCount = 0
|
||||
m.grabPowerUpRange2 = 300000
|
||||
m.hold = function() {
|
||||
|
||||
m.grabPowerUp();
|
||||
|
||||
// //grab power ups
|
||||
// for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||
// if (
|
||||
// Vector.magnitudeSquared(Vector.sub(m.pos, powerUp[i].position)) < 100000 &&
|
||||
// !simulation.isChoosing &&
|
||||
// (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal)
|
||||
// ) {
|
||||
// powerUps.onPickUp(powerUp[i]);
|
||||
// powerUp[i].effect();
|
||||
// Matter.Composite.remove(engine.world, powerUp[i]);
|
||||
// powerUp.splice(i, 1);
|
||||
// break; //because the array order is messed up after splice
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
if (m.isHolding) {
|
||||
m.drawHold(m.holdingTarget);
|
||||
m.holding();
|
||||
@@ -2568,20 +2587,6 @@ const m = {
|
||||
} else {
|
||||
m.undoCrouch()
|
||||
}
|
||||
//grab power ups
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||
if (
|
||||
Vector.magnitudeSquared(Vector.sub(m.pos, powerUp[i].position)) < 100000 &&
|
||||
!simulation.isChoosing &&
|
||||
(powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal)
|
||||
) {
|
||||
powerUps.onPickUp(powerUp[i]);
|
||||
powerUp[i].effect();
|
||||
Matter.Composite.remove(engine.world, powerUp[i]);
|
||||
powerUp.splice(i, 1);
|
||||
break; //because the array order is messed up after splice
|
||||
}
|
||||
}
|
||||
if (!(this.rewindCount % 30)) {
|
||||
if (tech.isRewindBot) {
|
||||
for (let i = 0; i < tech.isRewindBot; i++) {
|
||||
@@ -2594,8 +2599,6 @@ const m = {
|
||||
const who = bullet[bullet.length - 1]
|
||||
who.endCycle = simulation.cycle + 60
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2612,7 +2615,7 @@ const m = {
|
||||
} else {
|
||||
m.fieldFire = true;
|
||||
m.isBodiesAsleep = false;
|
||||
m.drain = 0.003
|
||||
m.drain = 0.0025
|
||||
m.hold = function() {
|
||||
if (m.isHolding) {
|
||||
m.wakeCheck();
|
||||
|
||||
@@ -137,7 +137,7 @@ const powerUps = {
|
||||
},
|
||||
doDefault() {
|
||||
//draw power ups
|
||||
ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6;
|
||||
ctx.globalAlpha = 0.4 * Math.sin(simulation.cycle * 0.15) + 0.6;
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI);
|
||||
@@ -237,7 +237,6 @@ const powerUps = {
|
||||
}
|
||||
},
|
||||
choose(type, index) {
|
||||
console.log('choose')
|
||||
if (type === "gun") {
|
||||
b.giveGuns(index)
|
||||
let text = `b.giveGuns("<span class='color-text'>${b.guns[index].name}</span>")`
|
||||
@@ -356,7 +355,7 @@ const powerUps = {
|
||||
// document.body.style.overflow = "hidden"
|
||||
// if (m.alive){}
|
||||
if (simulation.paused) requestAnimationFrame(cycle);
|
||||
simulation.paused = false;
|
||||
if (m.alive) simulation.paused = false;
|
||||
simulation.isChoosing = false; //stops p from un pausing on key down
|
||||
build.unPauseGrid()
|
||||
if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 15; //player is immune to damage for 30 cycles
|
||||
@@ -1080,7 +1079,7 @@ const powerUps = {
|
||||
},
|
||||
pauseEjectTech(index) {
|
||||
if ((tech.isPauseEjectTech || simulation.testing) && !simulation.isChoosing && !tech.tech[index].isNonRefundable) {
|
||||
if (Math.random() < 0.1 || tech.tech[index].isFromAppliedScience || (tech.tech[index].bonusResearch !== undefined && tech.tech[index].bonusResearch > powerUps.research.count)) {
|
||||
if (Math.random() < 0.16 || tech.tech[index].isFromAppliedScience || (tech.tech[index].bonusResearch !== undefined && tech.tech[index].bonusResearch > powerUps.research.count)) {
|
||||
tech.removeTech(index)
|
||||
powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false);
|
||||
} else {
|
||||
|
||||
@@ -521,9 +521,7 @@ const simulation = {
|
||||
}
|
||||
}, len * swapPeriod);
|
||||
},
|
||||
wipe() {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
},
|
||||
wipe() {}, //set in simulation.startGame
|
||||
gravity() {
|
||||
function addGravity(bodies, magnitude) {
|
||||
for (var i = 0; i < bodies.length; i++) {
|
||||
@@ -1049,7 +1047,7 @@ const simulation = {
|
||||
|
||||
if (m.lastKillCycle + 300 > m.cycle) { //effects active for 5 seconds after killing a mob
|
||||
if (tech.isEnergyRecovery && m.immuneCycle < m.cycle) m.energy += m.maxEnergy * 0.05
|
||||
if (tech.isHealthRecovery) m.addHealth(0.01 * m.maxHealth)
|
||||
if (tech.isHealthRecovery) m.addHealth(0.005 * m.maxHealth)
|
||||
}
|
||||
|
||||
if (!(m.cycle % 420)) { //once every 7 seconds
|
||||
|
||||
330
js/spawn.js
330
js/spawn.js
@@ -1,10 +1,11 @@
|
||||
//main object for spawning things in a level
|
||||
const spawn = {
|
||||
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "growBossCulture"],
|
||||
// other bosses: suckerBoss, laserBoss, tetherBoss, mantisBoss, bounceBoss, sprayBoss //these need a particular level to work so they are not included in the random pool
|
||||
randomBossList: ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
|
||||
"powerUpBoss", "powerUpBossBaby", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss",
|
||||
"snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss"
|
||||
// other bosses: suckerBoss, laserBoss, tetherBoss, bounceBoss, sprayBoss //these need a particular level to work so they are not included in the random pool
|
||||
randomBossList: [
|
||||
"orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
|
||||
"powerUpBoss", "powerUpBossBaby", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss",
|
||||
"snakeBoss", "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss", "shieldingBoss", "timeSkipBoss"
|
||||
],
|
||||
bossTypeSpawnOrder: [], //preset list of boss names calculated at the start of a run by the randomSeed
|
||||
bossTypeSpawnIndex: 0, //increases as the boss type cycles
|
||||
@@ -19,7 +20,7 @@ const spawn = {
|
||||
pickList: ["starter", "starter"],
|
||||
fullPickList: [
|
||||
"hopper", "hopper", "hopper",
|
||||
"slasher", "slasher", "hopper",
|
||||
"slasher", "slasher", "slasher",
|
||||
"stabber", "stabber", "stabber",
|
||||
"springer", "springer", "springer",
|
||||
"shooter", "shooter",
|
||||
@@ -2028,7 +2029,6 @@ const spawn = {
|
||||
me.seePlayerFreq = 300;
|
||||
const springStiffness = 0.00008; //simulation.difficulty
|
||||
const springDampening = 0.01;
|
||||
|
||||
me.springTarget = {
|
||||
x: me.position.x,
|
||||
y: me.position.y
|
||||
@@ -2055,11 +2055,9 @@ const spawn = {
|
||||
Composite.add(engine.world, cons[cons.length - 1]);
|
||||
cons[len2].length = 100 + 1.5 * radius;
|
||||
me.cons2 = cons[len2];
|
||||
|
||||
me.startingDamageReduction = me.damageReduction
|
||||
me.isInvulnerable = false
|
||||
me.invulnerabilityCountDown = 0
|
||||
|
||||
me.do = function() {
|
||||
this.checkStatus();
|
||||
this.gravity();
|
||||
@@ -2069,7 +2067,6 @@ const spawn = {
|
||||
ctx.arc(this.cons2.pointA.x, this.cons2.pointA.y, 6, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = "#222";
|
||||
ctx.fill();
|
||||
|
||||
this.seePlayerCheck()
|
||||
// this.seePlayerByHistory()
|
||||
if (this.isInvulnerable) {
|
||||
@@ -2202,7 +2199,6 @@ const spawn = {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
me.onDeath = function() {
|
||||
this.removeCons();
|
||||
if (isSpawnBossPowerUp) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
||||
@@ -2215,7 +2211,6 @@ const spawn = {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const sideLength = 80 // distance between each node mob
|
||||
const nodes = 3
|
||||
const angle = 2 * Math.PI / nodes
|
||||
@@ -2255,7 +2250,6 @@ const spawn = {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const stiffness = 0.01
|
||||
const damping = 0.1
|
||||
for (let i = 1; i < nodes; ++i) { //attach to center mob
|
||||
@@ -2287,88 +2281,86 @@ const spawn = {
|
||||
}
|
||||
spawn.allowShields = true;
|
||||
},
|
||||
timeSkipBoss(x, y, radius = 55) {
|
||||
mobs.spawn(x, y, 6, radius, '#000');
|
||||
let me = mob[mob.length - 1];
|
||||
me.isBoss = true;
|
||||
// me.stroke = "transparent"; //used for drawSneaker
|
||||
me.timeSkipLastCycle = 0
|
||||
me.eventHorizon = 1800; //required for black hole
|
||||
me.seeAtDistance2 = (me.eventHorizon + 2000) * (me.eventHorizon + 2000); //vision limit is event horizon + 2000
|
||||
me.accelMag = 0.0004 * simulation.accelScale;
|
||||
// me.frictionAir = 0.005;
|
||||
// me.memory = 1600;
|
||||
// Matter.Body.setDensity(me, 0.02); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
Matter.Body.setDensity(me, 0.0005 + 0.00018 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
spawn.shield(me, x, y, 1);
|
||||
// timeSkipBoss(x, y, radius = 55) {
|
||||
// mobs.spawn(x, y, 6, radius, '#000');
|
||||
// let me = mob[mob.length - 1];
|
||||
// me.isBoss = true;
|
||||
// // me.stroke = "transparent"; //used for drawSneaker
|
||||
// me.timeSkipLastCycle = 0
|
||||
// me.eventHorizon = 1800; //required for black hole
|
||||
// me.seeAtDistance2 = (me.eventHorizon + 2000) * (me.eventHorizon + 2000); //vision limit is event horizon + 2000
|
||||
// me.accelMag = 0.0004 * simulation.accelScale;
|
||||
// // me.frictionAir = 0.005;
|
||||
// // me.memory = 1600;
|
||||
// // Matter.Body.setDensity(me, 0.02); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
// Matter.Body.setDensity(me, 0.0005 + 0.00018 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
// spawn.shield(me, x, y, 1);
|
||||
// me.onDeath = function() {
|
||||
// //applying forces to player doesn't seem to work inside this method, not sure why
|
||||
// powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
||||
// };
|
||||
// me.do = function() {
|
||||
// //keep it slow, to stop issues from explosion knock backs
|
||||
// if (this.speed > 8) {
|
||||
// Matter.Body.setVelocity(this, {
|
||||
// x: this.velocity.x * 0.99,
|
||||
// y: this.velocity.y * 0.99
|
||||
// });
|
||||
// }
|
||||
// this.seePlayerCheck();
|
||||
// this.checkStatus();
|
||||
// this.attraction()
|
||||
// if (!simulation.isTimeSkipping) {
|
||||
// const compress = 1
|
||||
// if (this.timeSkipLastCycle < simulation.cycle - compress &&
|
||||
// Vector.magnitude(Vector.sub(this.position, player.position)) < this.eventHorizon) {
|
||||
// this.timeSkipLastCycle = simulation.cycle
|
||||
// simulation.timeSkip(compress)
|
||||
|
||||
// this.fill = `rgba(0,0,0,${0.4+0.6*Math.random()})`
|
||||
// this.stroke = "#014"
|
||||
// this.isShielded = false;
|
||||
// this.isDropPowerUp = true;
|
||||
// this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob; //can't touch bullets
|
||||
|
||||
me.onDeath = function() {
|
||||
//applying forces to player doesn't seem to work inside this method, not sure why
|
||||
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
||||
};
|
||||
me.do = function() {
|
||||
//keep it slow, to stop issues from explosion knock backs
|
||||
if (this.speed > 8) {
|
||||
Matter.Body.setVelocity(this, {
|
||||
x: this.velocity.x * 0.99,
|
||||
y: this.velocity.y * 0.99
|
||||
});
|
||||
}
|
||||
this.seePlayerCheck();
|
||||
this.checkStatus();
|
||||
this.attraction()
|
||||
if (!simulation.isTimeSkipping) {
|
||||
const compress = 1
|
||||
if (this.timeSkipLastCycle < simulation.cycle - compress &&
|
||||
Vector.magnitude(Vector.sub(this.position, player.position)) < this.eventHorizon) {
|
||||
this.timeSkipLastCycle = simulation.cycle
|
||||
simulation.timeSkip(compress)
|
||||
// ctx.beginPath();
|
||||
// ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||
// ctx.fillStyle = "#fff";
|
||||
// ctx.globalCompositeOperation = "destination-in"; //in or atop
|
||||
// ctx.fill();
|
||||
// ctx.globalCompositeOperation = "source-over";
|
||||
// ctx.beginPath();
|
||||
// ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||
// ctx.clip();
|
||||
|
||||
this.fill = `rgba(0,0,0,${0.4+0.6*Math.random()})`
|
||||
this.stroke = "#014"
|
||||
this.isShielded = false;
|
||||
this.isDropPowerUp = true;
|
||||
this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob; //can't touch bullets
|
||||
// // ctx.beginPath();
|
||||
// // ctx.arc(this.position.x, this.position.y, 9999, 0, 2 * Math.PI);
|
||||
// // ctx.fillStyle = "#000";
|
||||
// // ctx.fill();
|
||||
// // ctx.strokeStyle = "#000";
|
||||
// // ctx.stroke();
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = "#fff";
|
||||
ctx.globalCompositeOperation = "destination-in"; //in or atop
|
||||
ctx.fill();
|
||||
ctx.globalCompositeOperation = "source-over";
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||
ctx.clip();
|
||||
|
||||
// ctx.beginPath();
|
||||
// ctx.arc(this.position.x, this.position.y, 9999, 0, 2 * Math.PI);
|
||||
// ctx.fillStyle = "#000";
|
||||
// ctx.fill();
|
||||
// ctx.strokeStyle = "#000";
|
||||
// ctx.stroke();
|
||||
|
||||
// ctx.beginPath();
|
||||
// ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||
// ctx.fillStyle = `rgba(0,0,0,${0.05*Math.random()})`;
|
||||
// ctx.fill();
|
||||
// ctx.strokeStyle = "#000";
|
||||
// ctx.stroke();
|
||||
} else {
|
||||
this.isShielded = true;
|
||||
this.isDropPowerUp = false;
|
||||
this.seePlayer.recall = false
|
||||
this.fill = "transparent"
|
||||
this.stroke = "transparent"
|
||||
this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.mob; //can't touch bullets
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = `rgba(0,0,0,${0.05*Math.random()})`;
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// // ctx.beginPath();
|
||||
// // ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||
// // ctx.fillStyle = `rgba(0,0,0,${0.05*Math.random()})`;
|
||||
// // ctx.fill();
|
||||
// // ctx.strokeStyle = "#000";
|
||||
// // ctx.stroke();
|
||||
// } else {
|
||||
// this.isShielded = true;
|
||||
// this.isDropPowerUp = false;
|
||||
// this.seePlayer.recall = false
|
||||
// this.fill = "transparent"
|
||||
// this.stroke = "transparent"
|
||||
// this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.mob; //can't touch bullets
|
||||
// ctx.beginPath();
|
||||
// ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||
// ctx.fillStyle = `rgba(0,0,0,${0.05*Math.random()})`;
|
||||
// ctx.fill();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
beamer(x, y, radius = 15 + Math.ceil(Math.random() * 15)) {
|
||||
mobs.spawn(x, y, 4, radius, "rgb(255,0,190)");
|
||||
let me = mob[mob.length - 1];
|
||||
@@ -3931,7 +3923,7 @@ const spawn = {
|
||||
me.isBoss = true;
|
||||
Matter.Body.setDensity(me, 0.001); //normal is 0.001
|
||||
me.inertia = Infinity;
|
||||
me.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||
me.damageReduction = 0.06 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||
me.startingDamageReduction = me.damageReduction
|
||||
me.isInvulnerable = false
|
||||
me.frictionAir = 0.01
|
||||
@@ -3974,8 +3966,8 @@ const spawn = {
|
||||
const unit = Vector.sub(player.position, this.position)
|
||||
Matter.Body.setVelocity(this, Vector.mult(Vector.normalise(unit), 0.1));
|
||||
} else {
|
||||
if (Math.abs(this.velocity.y) < 9) Matter.Body.setVelocity(this, { x: this.velocity.x, y: this.velocity.y * 1.02 });
|
||||
if (Math.abs(this.velocity.x) < 6.5) Matter.Body.setVelocity(this, { x: this.velocity.x * 1.02, y: this.velocity.y });
|
||||
if (Math.abs(this.velocity.y) < 10) Matter.Body.setVelocity(this, { x: this.velocity.x, y: this.velocity.y * 1.02 });
|
||||
if (Math.abs(this.velocity.x) < 7) Matter.Body.setVelocity(this, { x: this.velocity.x * 1.02, y: this.velocity.y });
|
||||
}
|
||||
|
||||
if (this.isInvulnerable) {
|
||||
@@ -5138,7 +5130,7 @@ const spawn = {
|
||||
me.maxCycles = 110;
|
||||
me.frictionStatic = 0;
|
||||
me.friction = 0;
|
||||
me.frictionAir = 0.5;
|
||||
me.frictionAir = 1;
|
||||
// me.homePosition = { x: x, y: y };
|
||||
spawn.shield(me, x, y, 1);
|
||||
spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random())
|
||||
@@ -5153,7 +5145,7 @@ const spawn = {
|
||||
};
|
||||
me.damageReduction = 0.35 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||
me.do = function() {
|
||||
// this.armor();
|
||||
Matter.Body.rotate(this, 0.003) //gently spin around
|
||||
this.checkStatus();
|
||||
ctx.beginPath(); //draw cycle timer
|
||||
ctx.moveTo(this.vertices[this.vertices.length - 1].x, this.vertices[this.vertices.length - 1].y)
|
||||
@@ -5186,6 +5178,73 @@ const spawn = {
|
||||
}
|
||||
};
|
||||
},
|
||||
timeSkipBoss(x, y, radius = 50) {
|
||||
mobs.spawn(x, y, 15, radius, "rgb(150, 150, 255)");
|
||||
let me = mob[mob.length - 1];
|
||||
me.isBoss = true;
|
||||
me.eventHorizon = 0; //set in mob loop
|
||||
me.frictionStatic = 0;
|
||||
me.friction = 0;
|
||||
me.frictionAir = 0.004;
|
||||
me.accelMag = 0.0001 + 0.00003 * simulation.accelScale
|
||||
spawn.shield(me, x, y, 1);
|
||||
spawn.spawnOrbitals(me, radius + 50 + 100 * Math.random(), true)
|
||||
|
||||
Matter.Body.setDensity(me, 0.003); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
me.damageReduction = 0.07 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||
me.startingDamageReduction = me.damageReduction
|
||||
me.isInvulnerable = false
|
||||
me.onDeath = function() {
|
||||
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
||||
// requestAnimationFrame(() => { simulation.timePlayerSkip(120) }); //wrapping in animation frame prevents errors, probably
|
||||
};
|
||||
me.onDamage = function() {
|
||||
//find side of mob closest to player
|
||||
//causes lag for foam,laser too many seekers //maybe scale chance with dmg
|
||||
// const where = Vector.add(this.position, Vector.mult(Vector.normalise(Vector.sub(m.pos, this.position)), this.radius + 10))
|
||||
// spawn.seeker(where.x, where.y); //give the bullet a rotational velocity as if they were attached to a vertex
|
||||
};
|
||||
me.do = function() {
|
||||
this.seePlayerByHistory();
|
||||
this.attraction();
|
||||
this.checkStatus();
|
||||
this.eventHorizon = 950 + 170 * Math.sin(simulation.cycle * 0.005)
|
||||
if (!simulation.isTimeSkipping) {
|
||||
if (Vector.magnitude(Vector.sub(this.position, m.pos)) < this.eventHorizon) {
|
||||
this.attraction();
|
||||
this.damageReduction = this.startingDamageReduction
|
||||
this.isInvulnerable = false
|
||||
if (!(simulation.cycle % 15)) requestAnimationFrame(() => {
|
||||
simulation.timePlayerSkip(8)
|
||||
simulation.loop(); //ending with a wipe and normal loop fixes some very minor graphical issues where things are draw in the wrong locations
|
||||
}); //wrapping in animation frame prevents errors, probably
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = "#fff";
|
||||
ctx.globalCompositeOperation = "destination-in"; //in or atop
|
||||
ctx.fill();
|
||||
ctx.globalCompositeOperation = "source-over";
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||
// ctx.stroke();
|
||||
ctx.clip();
|
||||
} else {
|
||||
this.damageReduction = 0
|
||||
this.isInvulnerable = true
|
||||
//prevents other things from being drawn later on in the draw cycle
|
||||
requestAnimationFrame(() => {
|
||||
simulation.camera();
|
||||
ctx.beginPath(); //gets rid of already draw shapes
|
||||
ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI, false); //part you can't see
|
||||
ctx.fillStyle = color.background;
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
streamBoss(x, y, radius = 110) {
|
||||
mobs.spawn(x, y, 5, radius, "rgb(245,180,255)");
|
||||
let me = mob[mob.length - 1];
|
||||
@@ -5412,10 +5471,14 @@ const spawn = {
|
||||
mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, color1); //"rgb(55,170,170)"
|
||||
let me = mob[mob.length - 1];
|
||||
me.isBoss = true;
|
||||
me.accelMag = 0.0001 + 0.0002 * Math.sqrt(simulation.accelScale)
|
||||
me.accelMag = 0.0003 + 0.0002 * Math.sqrt(simulation.accelScale)
|
||||
me.memory = 250;
|
||||
me.laserRange = 500;
|
||||
Matter.Body.setDensity(me, 0.0022 + 0.00022 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
me.startingDamageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||
me.damageReduction = 0
|
||||
me.isInvulnerable = true
|
||||
|
||||
me.onDeath = function() {
|
||||
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
||||
for (let i = 0; i < mob.length; i++) { //wake up tail mobs
|
||||
@@ -5428,9 +5491,7 @@ const spawn = {
|
||||
};
|
||||
me.canFire = false;
|
||||
me.closestVertex1 = 0;
|
||||
// me.closestVertex2 = 1;
|
||||
me.cycle = 0
|
||||
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||
me.do = function() {
|
||||
// this.armor();
|
||||
this.seePlayerByHistory()
|
||||
@@ -5439,7 +5500,7 @@ const spawn = {
|
||||
this.cycle++
|
||||
if (this.seePlayer.recall && ((this.cycle % 10) === 0)) {
|
||||
if (this.canFire) {
|
||||
if (this.cycle > 120) {
|
||||
if (this.cycle > 100) {
|
||||
this.cycle = 0
|
||||
this.canFire = false
|
||||
// Matter.Body.setAngularVelocity(this, 0.1)
|
||||
@@ -5450,7 +5511,7 @@ const spawn = {
|
||||
}
|
||||
spawn.seeker(this.vertices[this.closestVertex1].x, this.vertices[this.closestVertex1].y, 6)
|
||||
Matter.Body.setDensity(mob[mob.length - 1], 0.000001); //normal is 0.001
|
||||
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[this.closestVertex1])), -10)
|
||||
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[this.closestVertex1])), -13)
|
||||
Matter.Body.setVelocity(mob[mob.length - 1], {
|
||||
x: this.velocity.x + velocity.x,
|
||||
y: this.velocity.y + velocity.y
|
||||
@@ -5482,14 +5543,29 @@ const spawn = {
|
||||
// }
|
||||
}
|
||||
}
|
||||
if (this.isInvulnerable) {
|
||||
ctx.beginPath();
|
||||
let vertices = this.vertices;
|
||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
|
||||
ctx.lineTo(vertices[0].x, vertices[0].y);
|
||||
ctx.lineWidth = 20;
|
||||
ctx.strokeStyle = "rgba(255,255,255,0.7)";
|
||||
ctx.stroke();
|
||||
}
|
||||
};
|
||||
//extra space to give head room
|
||||
angle -= 0.1
|
||||
mag -= 10
|
||||
let previousTailID = 0
|
||||
|
||||
for (let i = 0; i < nodes; ++i) {
|
||||
angle -= 0.15 + i * 0.008
|
||||
mag -= 5
|
||||
spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 20);
|
||||
if (i === 0) mob[mob.length - 1].snakeHeadID = me.id
|
||||
mob[mob.length - 1].previousTailID = previousTailID
|
||||
previousTailID = mob[mob.length - 1].id
|
||||
}
|
||||
this.constrain2AdjacentMobs(nodes, Math.random() * 0.06 + 0.01);
|
||||
|
||||
@@ -5530,36 +5606,46 @@ const spawn = {
|
||||
mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, color1); //"rgb(55,170,170)"
|
||||
let me = mob[mob.length - 1];
|
||||
me.isBoss = true;
|
||||
me.accelMag = 0.00077 * simulation.accelScale;
|
||||
me.accelMag = 0.0004 + 0.0003 * Math.sqrt(simulation.accelScale)
|
||||
me.memory = 250;
|
||||
me.laserRange = 500;
|
||||
Matter.Body.setDensity(me, 0.00165 + 0.00011 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
me.startingDamageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||
me.damageReduction = 0
|
||||
me.isInvulnerable = true
|
||||
|
||||
me.onDeath = function() {
|
||||
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
||||
for (let i = 0; i < mob.length; i++) { //wake up tail mobs
|
||||
if (mob[i].isSnakeTail && mob[i].alive) {
|
||||
mob[i].isSnakeTail = false;
|
||||
mob[i].do = mob[i].doActive
|
||||
// mob[i].removeConsBB();
|
||||
}
|
||||
}
|
||||
};
|
||||
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||
me.do = function() {
|
||||
// this.armor();
|
||||
this.seePlayerByHistory()
|
||||
this.checkStatus();
|
||||
this.attraction();
|
||||
this.harmZone();
|
||||
if (this.isInvulnerable) {
|
||||
ctx.beginPath();
|
||||
let vertices = this.vertices;
|
||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
|
||||
ctx.lineTo(vertices[0].x, vertices[0].y);
|
||||
ctx.lineWidth = 20;
|
||||
ctx.strokeStyle = "rgba(255,255,255,0.7)";
|
||||
ctx.stroke();
|
||||
}
|
||||
};
|
||||
//extra space to give head room
|
||||
angle -= 0.1
|
||||
mag -= 10
|
||||
let previousTailID = 0
|
||||
for (let i = 0; i < nodes; ++i) {
|
||||
angle -= 0.15 + i * 0.008
|
||||
mag -= 5
|
||||
spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 20);
|
||||
if (i === 0) mob[mob.length - 1].snakeHeadID = me.id
|
||||
mob[mob.length - 1].previousTailID = previousTailID
|
||||
previousTailID = mob[mob.length - 1].id
|
||||
}
|
||||
|
||||
this.constrain2AdjacentMobs(nodes, Math.random() * 0.06 + 0.01);
|
||||
|
||||
for (let i = mob.length - 1, len = i - nodes; i > len; i--) { //set alternating colors
|
||||
@@ -5595,23 +5681,23 @@ const spawn = {
|
||||
let me = mob[mob.length - 1];
|
||||
me.collisionFilter.mask = cat.bullet | cat.player | cat.mob //| cat.body
|
||||
me.accelMag = 0.0006 * simulation.accelScale;
|
||||
me.leaveBody = false;
|
||||
me.leaveBody = Math.random() < 0.33 ? true : false;
|
||||
me.showHealthBar = false;
|
||||
me.isDropPowerUp = false;
|
||||
// Matter.Body.setDensity(me, 0.00004); //normal is 0.001
|
||||
Matter.Body.setDensity(me, 0.003); //normal is 0.001
|
||||
me.frictionAir = 0.015;
|
||||
me.isSnakeTail = true;
|
||||
me.stroke = "transparent"
|
||||
me.onDeath = function() {
|
||||
// if (this.isSnakeTail) { //wake up tail mobs
|
||||
// for (let i = 0; i < mob.length; i++) {
|
||||
// if (mob[i].isSnakeTail && mob[i].alive) {
|
||||
// mob[i].isSnakeTail = false;
|
||||
// mob[i].do = mob[i].doActive
|
||||
// mob[i].removeConsBB();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
setTimeout(() => {
|
||||
for (let i = 0, len = mob.length; i < len; i++) {
|
||||
if (this.id === mob[i].previousTailID && mob[i].alive) mob[i].death()
|
||||
if (this.snakeHeadID === mob[i].id) {
|
||||
mob[i].isInvulnerable = false
|
||||
mob[i].damageReduction = mob[i].startingDamageReduction
|
||||
}
|
||||
}
|
||||
}, 150);
|
||||
};
|
||||
me.do = function() {
|
||||
this.checkStatus();
|
||||
@@ -5666,7 +5752,7 @@ const spawn = {
|
||||
me.stroke = "rgb(220,220,255)";
|
||||
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
|
||||
me.shield = true;
|
||||
me.damageReduction = 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||
me.isUnblockable = true
|
||||
me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
|
||||
me.collisionFilter.category = cat.mobShield
|
||||
|
||||
121
js/tech.js
121
js/tech.js
@@ -221,7 +221,8 @@ const tech = {
|
||||
},
|
||||
damageFromTech() {
|
||||
let dmg = 1 //m.fieldDamage
|
||||
if (tech.isNoDraftPause) dmg *= 1.5
|
||||
if (tech.isDeathSkipTime) dmg *= 1.67
|
||||
if (tech.isNoDraftPause) dmg *= 1.4
|
||||
if (tech.isTechDebt) dmg *= Math.max(41 / (tech.totalCount + 21), 4 - 0.15 * tech.totalCount)
|
||||
if (tech.isAxion && tech.isHarmMACHO) dmg *= 1 + 0.75 * (1 - m.harmReduction())
|
||||
if (tech.OccamDamage) dmg *= tech.OccamDamage
|
||||
@@ -556,7 +557,7 @@ const tech = {
|
||||
{
|
||||
name: "cache",
|
||||
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Cache_(computing)' class="link">cache</a>`,
|
||||
description: `${powerUps.orb.ammo()} give <strong>16x</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`,
|
||||
description: `${powerUps.orb.ammo()} give <strong>1600%</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`,
|
||||
// ammo powerups always max out your gun,
|
||||
// but the maximum ammo ti limited
|
||||
// description: `${powerUps.orb.ammo()} give <strong>13x</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`,
|
||||
@@ -936,7 +937,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "reaction inhibitor",
|
||||
description: "mobs spawn with <strong>11%</strong> less <strong>health</strong>",
|
||||
description: "mobs spawn with <strong>13%</strong> less <strong>health</strong>",
|
||||
maxCount: 3,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -946,7 +947,7 @@ const tech = {
|
||||
},
|
||||
requires: "", //"any mob death tech",
|
||||
effect: () => {
|
||||
tech.mobSpawnWithHealth *= 0.89
|
||||
tech.mobSpawnWithHealth *= 0.87
|
||||
|
||||
//set all mobs at full health to 0.85
|
||||
for (let i = 0; i < mob.length; i++) {
|
||||
@@ -957,6 +958,24 @@ const tech = {
|
||||
tech.mobSpawnWithHealth = 1;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "propagator",
|
||||
description: "increase <strong class='color-d'>damage</strong> by <strong>67%</strong>, but after<br>mobs <strong>die</strong> lose <strong>0.5</strong> seconds of <strong>time</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
frequencyDefault: 1,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
effect() {
|
||||
tech.isDeathSkipTime = true
|
||||
},
|
||||
remove() {
|
||||
tech.isDeathSkipTime = false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "decorrelation",
|
||||
description: "reduce <strong class='color-harm'>harm</strong> by <strong>70%</strong> after not <strong>activating</strong><br>your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> for <strong>2</strong> seconds",
|
||||
@@ -1772,6 +1791,24 @@ const tech = {
|
||||
m.eyeFillColor = 'transparent'
|
||||
}
|
||||
},
|
||||
// {
|
||||
// name: "spacetime interval",
|
||||
// description: "increase <strong class='color-d'>damage</strong> by <strong>93%</strong>, but after mobs <strong>die</strong><br>move into the <strong>past</strong> / <strong>future</strong> while <strong class='color-flop'>ON</strong> / <strong class='color-flop'>OFF</strong>",
|
||||
// maxCount: 1,
|
||||
// count: 0,
|
||||
// frequency: 4,
|
||||
// frequencyDefault: 4,
|
||||
// allowed() {
|
||||
// return tech.isFlipFlop || tech.isRelay
|
||||
// },
|
||||
// requires: "ON/OFF tech",
|
||||
// effect() {
|
||||
// tech.isDeathSkipTime = true
|
||||
// },
|
||||
// remove() {
|
||||
// tech.isDeathSkipTime = false
|
||||
// }
|
||||
// },
|
||||
{
|
||||
name: "NAND gate",
|
||||
description: "if in the <strong class='color-flop'>ON</strong> state<br>do <strong>55.5%</strong> more <strong class='color-d'>damage</strong>",
|
||||
@@ -2479,7 +2516,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "recycling",
|
||||
description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br>regain <strong>1%</strong> of max <strong class='color-h'>health</strong> every second",
|
||||
description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br>regain <strong>0.5%</strong> of max <strong class='color-h'>health</strong> every second",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -3172,7 +3209,7 @@ const tech = {
|
||||
|
||||
{
|
||||
name: "paradigm shift",
|
||||
description: `<strong>clicking</strong> <strong class='color-m'>tech</strong> while paused <strong>ejects</strong> them<br><strong>10%</strong> chance to convert that <strong class='color-m'>tech</strong> into ${powerUps.orb.research(1)}`,
|
||||
description: `<strong>clicking</strong> <strong class='color-m'>tech</strong> while paused <strong>ejects</strong> them<br><strong>16%</strong> chance to convert that <strong class='color-m'>tech</strong> into ${powerUps.orb.research(1)}`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -3191,7 +3228,7 @@ const tech = {
|
||||
{
|
||||
name: "eternalism",
|
||||
// description: `increase <strong class='color-d'>damage</strong> by <strong>60%</strong>, but <strong>time</strong> doesn't <strong>pause</strong><br>while choosing a choosing a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong>`, //${powerUps.orb.heal()} or
|
||||
description: "increase <strong class='color-d'>damage</strong> by <strong>50%</strong>, but<br><strong>time</strong> can't be <strong>paused</strong> <em>(time dilation still works)</em>",
|
||||
description: "increase <strong class='color-d'>damage</strong> by <strong>40%</strong>, but<br><strong>time</strong> can't be <strong>paused</strong> <em>(time dilation still works)</em>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -3556,19 +3593,19 @@ const tech = {
|
||||
// return `randomly remove <strong>${this.removePercent * 100}%</strong> of your <strong class='color-m'>tech</strong><br>for each removed gain <strong>${this.damagePerRemoved * 100}%</strong> <strong class='color-d'>damage</strong>`
|
||||
// },
|
||||
descriptionFunction() {
|
||||
return `randomly remove <strong>half</strong> your <strong class='color-m'>tech</strong><br>for each removed gain <strong>${this.damagePerRemoved * 100}%</strong> <strong class='color-d'>damage</strong> <em>(~${this.damagePerRemoved * 50 * tech.totalCount}%)</em>`
|
||||
return `randomly remove <strong>half</strong> your <strong class='color-m'>tech</strong><br>for each removed gain <strong>${this.damagePerRemoved * 100 }%</strong> <strong class='color-d'>damage</strong> <em>(~${(this.count === 0) ? this.damagePerRemoved * 50 * tech.totalCount : tech.OccamDamage*100}%)</em>`
|
||||
},
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
frequency: 199,
|
||||
frequencyDefault: 1,
|
||||
isNonRefundable: true,
|
||||
isBadRandomOption: true,
|
||||
allowed() {
|
||||
return (tech.totalCount > 6)
|
||||
},
|
||||
requires: "NOT EXPERIMENT MODE, more than 6 tech",
|
||||
removePercent: 0.5,
|
||||
requires: "more than 6 tech",
|
||||
// removePercent: 0.5,
|
||||
damagePerRemoved: 0.5,
|
||||
effect() {
|
||||
let pool = []
|
||||
@@ -3577,7 +3614,7 @@ const tech = {
|
||||
}
|
||||
pool = shuffle(pool); //shuffles order of maps
|
||||
let removeCount = 0
|
||||
for (let i = 0, len = pool.length * this.removePercent; i < len; i++) removeCount += tech.removeTech(pool[i])
|
||||
for (let i = 0, len = pool.length * this.damagePerRemoved; i < len; i++) removeCount += tech.removeTech(pool[i])
|
||||
tech.OccamDamage = 1 + this.damagePerRemoved * removeCount
|
||||
// tech.OccamDamage = Math.pow(1.25, removeCount)
|
||||
},
|
||||
@@ -5713,8 +5750,8 @@ const tech = {
|
||||
simulation.updateGunHUD()
|
||||
},
|
||||
remove() {
|
||||
b.guns[8].ammoPack = 24
|
||||
if (this.count) {
|
||||
b.guns[8].ammoPack = 24
|
||||
b.guns[8].ammo += this.ammoLost
|
||||
simulation.updateGunHUD()
|
||||
}
|
||||
@@ -6110,7 +6147,7 @@ const tech = {
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return (tech.haveGunCheck("laser") || tech.isLaserBotUpgrade || tech.isLaserMine) && tech.laserDamage === 0.17
|
||||
return (tech.haveGunCheck("laser") || tech.isLaserBotUpgrade || tech.isLaserMine) && tech.laserDamage === 0.18
|
||||
},
|
||||
requires: "laser, not free-electron",
|
||||
effect() {
|
||||
@@ -6138,13 +6175,13 @@ const tech = {
|
||||
requires: "laser, not pulse, diodes",
|
||||
effect() {
|
||||
tech.laserFieldDrain = 0.007 //base is 0.002
|
||||
tech.laserDamage = 0.51; //base is 0.16
|
||||
tech.laserDamage = 0.54; //base is 0.18
|
||||
tech.laserColor = "#83f"
|
||||
tech.laserColorAlpha = "rgba(136, 51, 255,0.5)"
|
||||
},
|
||||
remove() {
|
||||
tech.laserFieldDrain = 0.002;
|
||||
tech.laserDamage = 0.17; //used in check on pulse and diode: tech.laserDamage === 0.16
|
||||
tech.laserDamage = 0.18; //used in check on pulse and diode: tech.laserDamage === 0.16
|
||||
tech.laserColor = "#f00"
|
||||
tech.laserColorAlpha = "rgba(255, 0, 0, 0.5)"
|
||||
}
|
||||
@@ -6217,7 +6254,7 @@ const tech = {
|
||||
{
|
||||
name: "diffuse beam",
|
||||
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Diffuser_(optics)' class="link">diffuse beam</a>`,
|
||||
description: "<strong class='color-laser'>laser</strong> beam is <strong>wider</strong> and doesn't <strong>reflect</strong><br>increase full beam <strong class='color-d'>damage</strong> by <strong>200%</strong>",
|
||||
description: "<strong class='color-laser'>laser</strong> beam is <strong>wider</strong> and doesn't <strong>reflect</strong><br>increase full beam <strong class='color-d'>damage</strong> by <strong>220%</strong>",
|
||||
isGunTech: true,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -6311,7 +6348,7 @@ const tech = {
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDamage === 0.17 && !tech.isStuckOn
|
||||
return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDamage === 0.18 && !tech.isStuckOn
|
||||
},
|
||||
requires: "laser gun, not specular reflection, diffuse, free-electron laser, optical amplifier",
|
||||
effect() {
|
||||
@@ -7049,7 +7086,7 @@ const tech = {
|
||||
},
|
||||
requires: "extruder",
|
||||
effect() {
|
||||
tech.extruderRange += 60
|
||||
tech.extruderRange += 55
|
||||
},
|
||||
remove() {
|
||||
tech.extruderRange = 15
|
||||
@@ -7895,6 +7932,51 @@ const tech = {
|
||||
},
|
||||
remove() {}
|
||||
},
|
||||
{
|
||||
name: "translate",
|
||||
description: "translate n-gon into a random language",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 0,
|
||||
isJunk: true,
|
||||
isNonRefundable: true,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
effect() {
|
||||
// generate a container
|
||||
const gtElem = document.createElement('div')
|
||||
gtElem.id = "gtElem"
|
||||
gtElem.style.visibility = 'hidden' // make it invisible
|
||||
document.body.append(gtElem)
|
||||
|
||||
// generate a script to run after creation
|
||||
function initGT() {
|
||||
// create a new translate element
|
||||
new google.translate.TranslateElement({ pageLanguage: 'en', layout: google.translate.TranslateElement.InlineLayout.HORIZONTAL }, 'gtElem')
|
||||
// ok now since it's loaded perform a funny hack to make it work
|
||||
const langSelect = document.getElementsByClassName("goog-te-combo")[0]
|
||||
// select a random language. It takes a second for all langauges to load, so wait a second.
|
||||
setTimeout(() => {
|
||||
langSelect.selectedIndex = Math.round(langSelect.options.length * Math.random())
|
||||
// simulate a click
|
||||
langSelect.dispatchEvent(new Event('change'))
|
||||
// now make it go away
|
||||
const bar = document.getElementById(':1.container')
|
||||
bar.style.display = 'none'
|
||||
bar.style.visibility = 'hidden'
|
||||
}, 1000)
|
||||
|
||||
}
|
||||
|
||||
// add the google translate script
|
||||
const translateScript = document.createElement('script')
|
||||
translateScript.src = '//translate.google.com/translate_a/element.js?cb=initGT'
|
||||
document.body.append(translateScript)
|
||||
},
|
||||
remove() {}
|
||||
},
|
||||
{
|
||||
name: "discount",
|
||||
description: "get 3 random <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> for the price of 1!",
|
||||
@@ -10223,4 +10305,5 @@ const tech = {
|
||||
isClusterExplode: null,
|
||||
isCircleExplode: null,
|
||||
isPetalsExplode: null,
|
||||
isDeathSkipTime: null
|
||||
}
|
||||
70
todo.txt
70
todo.txt
@@ -1,14 +1,43 @@
|
||||
******************************************************** NEXT PATCH **************************************************
|
||||
|
||||
new reactor boss: timeBoss - after taking some damage it speeds up the passage of time
|
||||
reactor level has big doors
|
||||
tech: propagator - 67% damage, lose 1/2 second of time when a mob dies
|
||||
|
||||
nonrefundable tech show up in the pause menu
|
||||
time dilation field - move, jump, and fire 25% faster
|
||||
JUNK tech: closed timelike curve - spawn 5 field power ups, but every 12 seconds teleport a second into your future
|
||||
timeSkipBoss is back, maybe it will not cause bugs this time
|
||||
immune to harm unless player is inside horizon
|
||||
player loses time when inside horizon
|
||||
|
||||
snake bosses are immune to harm until your remove their tail
|
||||
|
||||
mob shields are 30% stronger
|
||||
time dilation: retrocausality automatically grabs power ups
|
||||
eternalism 50->40% damage
|
||||
paradigm shift 10->16% chance to get a research when ejecting tech
|
||||
reaction inhibitor 11->13% mob health reduction
|
||||
recycling 1->0.5% health for 5 seconds
|
||||
up to 2.5% per mob kill at normal max health
|
||||
|
||||
bug fixes
|
||||
|
||||
******************************************************** TODO ********************************************************
|
||||
|
||||
make targeting skip invulnerable mobs
|
||||
drones, spores, harpoon, missiles?, mines, nail on death
|
||||
this helps beat snake boss
|
||||
spores are biggest issue
|
||||
|
||||
let blocking instantly destroy the red orbitals? since they can't be deflected
|
||||
also mines on reactor level?
|
||||
also any bullet?
|
||||
|
||||
BUG time skip probably led to player being able to move, and game not being paused for a few seconds while the death screen faded in
|
||||
also small chance it happened with rewind instead, but unlikely
|
||||
|
||||
make one value to track all the +dmg effects that don't need dynamic calculations
|
||||
update it with a set damage function
|
||||
|
||||
block manufacturing - molecular assembler tech
|
||||
Holding r-click will create a slowly increasing in size block, which will be thrown on release
|
||||
|
||||
if a mob dies in skiptime it doesn't register?
|
||||
is this only for the ondeath event?
|
||||
so far, but needs more tests
|
||||
@@ -19,23 +48,9 @@ make MEE work with harm reduction
|
||||
how to nerf MEE
|
||||
maybe harm reduction could also reduce energy regen
|
||||
|
||||
timeSkipBoss
|
||||
sends out waves of 60s time skip every 5 seconds?
|
||||
or 1 cycle skip every other cycle
|
||||
only active when player is inside range
|
||||
immune to harm outside range?
|
||||
|
||||
simulation.timeSkip(60)
|
||||
skip every other cycle inside black holes?
|
||||
maybe run simulation.timeSkip(60) in a map
|
||||
in labs?
|
||||
reactor boss
|
||||
maybe run simulation.timeSkip(60) in a room in labs
|
||||
mob fires laser/bullets that timeSkip player
|
||||
maybe an effect when in range of the historyBoss
|
||||
JUNK tech simulation.timeSkip(60)
|
||||
add CPT graphics to simulation.timeSkip(60)
|
||||
for player
|
||||
tech requires eternalism - 2x time while choosing, gain more damage
|
||||
|
||||
Currently, the mob just deals higher damage on impact, which is annoying although not hard to compete with nor unique
|
||||
By "redesign" I mean replacing instances of the regular mob, since the same code is used for the tiny red projectiles (I think) just add a new mob and remove the old one from the rotation
|
||||
@@ -51,7 +66,6 @@ About to explode: animation to dark red
|
||||
Exploding: several shockwaves from the explosion points and tiny trails given to the shrapnel for a second or two until they deaccelerate
|
||||
|
||||
|
||||
|
||||
make laser gain damage and energy drain from fire delay tech
|
||||
wording? put it in the gun description
|
||||
|
||||
@@ -62,8 +76,6 @@ pause time like invariant for other things...
|
||||
charging railgun
|
||||
charging anything?
|
||||
|
||||
give retrocausality a short delay before it rewinds, so you can pick up powerups without going back
|
||||
|
||||
tech expansion: should also make other fields do things
|
||||
how to make the description work
|
||||
change description based on your current field?
|
||||
@@ -733,23 +745,13 @@ possible names for tech
|
||||
nuclear pasta - hard matter in neutron star
|
||||
nonlocal
|
||||
fine-tuned universe
|
||||
eternalism https://en.wikipedia.org/wiki/Eternalism_(philosophy_of_time)
|
||||
axial motor
|
||||
hall effect thrusters
|
||||
spaghettification
|
||||
particle accelerator
|
||||
superluminal signalling
|
||||
NP-complete
|
||||
lenticular lens: is an array of lenses, designed so that when viewed from slightly different angles, different parts of the image underneath are shown.
|
||||
|
||||
a tutorial / lore intro
|
||||
needs to be optional so it doesn't slow experienced players
|
||||
put something on the intro map
|
||||
maybe a button triggers something
|
||||
|
||||
rename ?
|
||||
health -> integrity, unity
|
||||
heal -> also integrity, unity
|
||||
p-zombie
|
||||
|
||||
|
||||
plot script:
|
||||
|
||||
Reference in New Issue
Block a user