metastability

tech: metastability - 20% dup chance, but duplicated powers up eventually explode
nerfed tech: electric reactive armor 6% (was 7%) explosion damage reduction for every 10 energy you currently have
This commit is contained in:
landgreen
2021-05-10 06:20:19 -07:00
parent ce169ba860
commit 0019143124
12 changed files with 253 additions and 128 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -319,11 +319,8 @@ const b = {
time: simulation.drawTime * 2 time: simulation.drawTime * 2
}); });
//player damage and knock back //player damage
sub = Vector.sub(where, player.position); if (Vector.magnitude(Vector.sub(where, player.position)) < radius) {
dist = Vector.magnitude(sub);
if (dist < radius) {
const drain = (tech.isExplosionHarm ? 0.5 : 0.25) * (tech.isImmuneExplosion ? Math.min(1, Math.max(1 - m.energy * 0.7, 0)) : 1) const drain = (tech.isExplosionHarm ? 0.5 : 0.25) * (tech.isImmuneExplosion ? Math.min(1, Math.max(1 - m.energy * 0.7, 0)) : 1)
m.energy -= drain m.energy -= drain
if (m.energy < 0) { if (m.energy < 0) {
@@ -389,6 +386,7 @@ const b = {
//body knock backs //body knock backs
for (let i = 0, len = body.length; i < len; ++i) { for (let i = 0, len = body.length; i < len; ++i) {
if (body[i].isNotHoldable) continue
sub = Vector.sub(where, body[i].position); sub = Vector.sub(where, body[i].position);
dist = Vector.magnitude(sub); dist = Vector.magnitude(sub);
if (dist < radius) { if (dist < radius) {
@@ -560,11 +558,11 @@ const b = {
for (let i = 0, len = Math.floor(mag * 0.0005 * charge); i < len; i++) { for (let i = 0, len = Math.floor(mag * 0.0005 * charge); i < len; i++) {
const dist = Math.random() const dist = Math.random()
simulation.drawList.push({ simulation.drawList.push({
x: path[0].x + sub.x * dist + 13 * (Math.random() - 0.5), x: path[0].x + sub.x * dist + 10 * (Math.random() - 0.5),
y: path[0].y + sub.y * dist + 13 * (Math.random() - 0.5), y: path[0].y + sub.y * dist + 10 * (Math.random() - 0.5),
radius: 1 + 4 * Math.random(), radius: 1.5 + 5 * Math.random(),
color: "rgba(255,0,0,0.5)", color: "rgba(255,0,0,0.5)",
time: Math.floor(2 + 33 * Math.random() * Math.random()) time: Math.floor(9 + 25 * Math.random() * Math.random())
}); });
} }
}, },
@@ -3625,7 +3623,6 @@ const b = {
damage: 1, damage: 1,
fire() { fire() {
totalCycles = Math.floor(4.3 * tech.wavePacketLength * tech.waveReflections * tech.isBulletsLastLonger) totalCycles = Math.floor(4.3 * tech.wavePacketLength * tech.waveReflections * tech.isBulletsLastLonger)
// for (let i = 0; i < 2; i++) {
const me = bullet.length; const me = bullet.length;
bullet[me] = Bodies.polygon(m.pos.x + 25 * Math.cos(m.angle), m.pos.y + 25 * Math.sin(m.angle), 5, 4, { bullet[me] = Bodies.polygon(m.pos.x + 25 * Math.cos(m.angle), m.pos.y + 25 * Math.sin(m.angle), 5, 4, {
angle: m.angle, angle: m.angle,
@@ -3634,7 +3631,7 @@ const b = {
inertia: Infinity, inertia: Infinity,
frictionAir: 0, frictionAir: 0,
slow: 0, slow: 0,
amplitude: (m.crouch ? 5 : 10) * Math.sin(this.wavePacketCycle * tech.wavePacketFrequency) * ((this.wavePacketCycle % 2) ? -1 : 1), amplitude: (m.crouch ? 5 : 10) * ((this.wavePacketCycle % 2) ? -1 : 1) * Math.sin((this.wavePacketCycle + 1) * tech.wavePacketFrequency), //
minDmgSpeed: 0, minDmgSpeed: 0,
dmg: b.dmgScale * tech.waveBeamDamage * tech.wavePacketDamage, //also control damage when you divide by mob.mass dmg: b.dmgScale * tech.waveBeamDamage * tech.wavePacketDamage, //also control damage when you divide by mob.mass
classType: "bullet", classType: "bullet",
@@ -3716,8 +3713,7 @@ const b = {
y: tech.waveBeamSpeed * Math.sin(m.angle) y: tech.waveBeamSpeed * Math.sin(m.angle)
}); });
const transverse = Vector.normalise(Vector.perp(bullet[me].velocity)) const transverse = Vector.normalise(Vector.perp(bullet[me].velocity))
// } //fire a packet of bullets then delay for a while
//fire some of bullets then delay for a while
this.wavePacketCycle++ this.wavePacketCycle++
if (this.wavePacketCycle > tech.wavePacketLength) { if (this.wavePacketCycle > tech.wavePacketLength) {
m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCD); // cool down
@@ -4487,28 +4483,30 @@ const b = {
} }
} }
if (tech.historyLaser) { if (tech.historyLaser) {
const len = 1 + tech.historyLaser
const spacing = Math.ceil(30 - 2 * tech.historyLaser)
this.do = () => { this.do = () => {
const len = 1 + 2 * tech.historyLaser
const spacing = Math.ceil(40 - 9 * tech.historyLaser)
if (this.charge > 0) { if (this.charge > 0) {
//draw charge level //draw charge level
ctx.fillStyle = `rgba(255,0,0,${0.09 * Math.sqrt(this.charge)})`; const mag = 4.1 * Math.sqrt(this.charge)
ctx.beginPath(); ctx.beginPath();
const mag = 4.5 * Math.sqrt(this.charge)
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
const history = m.history[(m.cycle - i * spacing) % 600] const history = m.history[(m.cycle - i * spacing) % 600]
const off = history.yOff - 24.2859 const off = history.yOff - 24.2859
ctx.moveTo(history.position.x, history.position.y - off); ctx.moveTo(history.position.x, history.position.y - off);
ctx.ellipse(history.position.x, history.position.y - off, mag, mag * 0.5, history.angle, 0, 2 * Math.PI) ctx.ellipse(history.position.x, history.position.y - off, mag, mag * 0.65, history.angle, 0, 2 * Math.PI)
} }
ctx.fillStyle = `rgba(255,0,0,${0.09 * Math.sqrt(this.charge)})`;
ctx.fill(); ctx.fill();
//fire //fire
if (!input.fire) { if (!input.fire) {
m.fireCDcycle = m.cycle + 10; // cool down if (this.charge > 5) {
for (let i = 1; i < len; i++) { m.fireCDcycle = m.cycle + 40; // cool down
for (let i = 0; i < len; i++) {
const history = m.history[(m.cycle - i * spacing) % 600] const history = m.history[(m.cycle - i * spacing) % 600]
const off = history.yOff - 24.2859 const off = history.yOff - 24.2859
b.pulse(1.4 * this.charge, history.angle, { x: history.position.x, y: history.position.y - off }) b.pulse(1.65 * this.charge, history.angle, { x: history.position.x, y: history.position.y - off })
}
} }
this.charge = 0; this.charge = 0;
} }
@@ -4518,19 +4516,21 @@ const b = {
this.do = () => { this.do = () => {
if (this.charge > 0) { if (this.charge > 0) {
//draw charge level //draw charge level
ctx.fillStyle = `rgba(255,0,0,${0.09 * Math.sqrt(this.charge)})`;
ctx.beginPath(); ctx.beginPath();
ctx.arc(m.pos.x, m.pos.y, 4.2 * Math.sqrt(this.charge), 0, 2 * Math.PI); ctx.arc(m.pos.x, m.pos.y, 4.2 * Math.sqrt(this.charge), 0, 2 * Math.PI);
ctx.fillStyle = `rgba(255,0,0,${0.09 * Math.sqrt(this.charge)})`;
ctx.fill(); ctx.fill();
//fire //fire
if (!input.fire) { if (!input.fire) {
m.fireCDcycle = m.cycle + 10; // cool down if (this.charge > 5) {
m.fireCDcycle = m.cycle + 35; // cool down
if (tech.beamSplitter) { if (tech.beamSplitter) {
const divergence = m.crouch ? 0.2 : 0.5 const divergence = m.crouch ? 0.2 : 0.5
const angle = m.angle - tech.beamSplitter * divergence / 2 const angle = m.angle - tech.beamSplitter * divergence / 2
for (let i = 0; i < 1 + tech.beamSplitter; i++) b.pulse(this.charge, angle + i * divergence) for (let i = 0; i < 1 + tech.beamSplitter; i++) b.pulse(this.charge, angle + i * divergence)
} else { } else {
b.pulse(1.75 * this.charge, m.angle) b.pulse(1.8 * this.charge, m.angle)
}
} }
this.charge = 0; this.charge = 0;
} }

View File

@@ -130,7 +130,7 @@ function collisionChecks(event) {
simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`); simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`);
} }
if (tech.isPiezo) m.energy += 20.48; if (tech.isPiezo) m.energy += 20.48;
if (tech.isBayesian) powerUps.ejectTech() if (tech.isStimulatedEmission) powerUps.ejectTech()
if (mob[k].onHit) mob[k].onHit(k); if (mob[k].onHit) mob[k].onHit(k);
m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles
//extra kick between player and mob //this section would be better with forces but they don't work... //extra kick between player and mob //this section would be better with forces but they don't work...

View File

@@ -117,7 +117,7 @@ window.addEventListener('load', () => {
//********************************************************************** //**********************************************************************
//set up canvas //set up canvas
//********************************************************************** //**********************************************************************
var canvas = document.getElementById("canvas"); const canvas = document.getElementById("canvas");
//using "const" causes problems in safari when an ID shares the same name. //using "const" causes problems in safari when an ID shares the same name.
const ctx = canvas.getContext("2d"); const ctx = canvas.getContext("2d");
document.body.style.backgroundColor = "#fff"; document.body.style.backgroundColor = "#fff";

View File

@@ -16,15 +16,16 @@ const level = {
// simulation.zoomScale = 1000; // simulation.zoomScale = 1000;
// simulation.setZoom(); // simulation.setZoom();
// m.setField("metamaterial cloaking") // m.setField("metamaterial cloaking")
// b.giveGuns("wave beam") b.giveGuns("wave beam")
// b.giveGuns("laser") // b.giveGuns("laser")
// tech.isExplodeRadio = true // tech.isExplodeRadio = true
// tech.giveTech("pulse") // tech.giveTech("pulse")
// for (let i = 0; i < 1; i++) tech.giveTech("crystallizer") // for (let i = 0; i < 1; i++) tech.giveTech("crystallizer")
// for (let i = 0; i < 3; i++) tech.giveTech("packet length") // for (let i = 0; i < 3; i++) tech.giveTech("packet length")
// for (let i = 0; i < 3; i++) tech.giveTech("bound state")
// for (let i = 0; i < 3; i++) tech.giveTech("propagation") // for (let i = 0; i < 3; i++) tech.giveTech("propagation")
// for (let i = 0; i < 3; i++) tech.giveTech("bound state")
// for (let i = 0; i < 9; i++) tech.giveTech("slow light") // for (let i = 0; i < 9; i++) tech.giveTech("slow light")
tech.giveTech("metastability")
level.intro(); //starting level level.intro(); //starting level
// level.testing(); //not in rotation // level.testing(); //not in rotation

View File

@@ -155,10 +155,10 @@ const mobs = {
} }
}, },
statusDoT(who, tickDamage, cycles = 180) { statusDoT(who, tickDamage, cycles = 180) {
if (!who.isShielded && !m.isBodiesAsleep && who.alive) { if (!who.isShielded && who.alive) {
who.status.push({ who.status.push({
effect() { effect() {
if ((simulation.cycle - this.startCycle) % 30 === 0) { if ((simulation.cycle - this.startCycle) % 30 === 0 && !m.isBodiesAsleep) {
let dmg = b.dmgScale * this.dmg let dmg = b.dmgScale * this.dmg
who.damage(dmg); who.damage(dmg);
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
@@ -169,10 +169,6 @@ const mobs = {
time: simulation.drawTime time: simulation.drawTime
}); });
} }
// if (true) {
// //check for nearby mobs
// }
}, },
endEffect() {}, endEffect() {},
dmg: tickDamage, dmg: tickDamage,
@@ -1090,7 +1086,7 @@ const mobs = {
bullet[bullet.length - 1].endCycle = simulation.cycle + 660 //10 seconds and 1 extra second for fun bullet[bullet.length - 1].endCycle = simulation.cycle + 660 //10 seconds and 1 extra second for fun
this.leaveBody = false; // no body since it turned into the bot this.leaveBody = false; // no body since it turned into the bot
} }
} else if (tech.isShieldAmmo && this.shield && !this.isBonusShield) { } else if (tech.isShieldAmmo && this.shield && !this.isExtraShield) {
let type = tech.isEnergyNoAmmo ? "heal" : "ammo" let type = tech.isEnergyNoAmmo ? "heal" : "ammo"
if (Math.random() < 0.4) { if (Math.random() < 0.4) {
type = "heal" type = "heal"

View File

@@ -976,7 +976,7 @@ const m = {
m.fieldHarmReduction = 1; m.fieldHarmReduction = 1;
m.fieldDamage = 1 m.fieldDamage = 1
m.duplicateChance = 0 m.duplicateChance = 0
if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal powerUps.setDo();
m.grabPowerUpRange2 = 156000; m.grabPowerUpRange2 = 156000;
m.fieldRange = 155; m.fieldRange = 155;
m.fieldFire = false; m.fieldFire = false;
@@ -2370,7 +2370,7 @@ const m = {
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract blocks and power ups<br><strong>7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong> description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract blocks and power ups<br><strong>7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
effect: function() { effect: function() {
m.duplicateChance = 0.07 m.duplicateChance = 0.07
simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw powerUps.setDo(); //needed after adjusting duplication chance
m.hold = function() { m.hold = function() {
// m.hole = { //this is reset with each new field, but I'm leaving it here for reference // m.hole = { //this is reset with each new field, but I'm leaving it here for reference
@@ -2922,7 +2922,7 @@ const m = {
} }
m.damage(dmg); m.damage(dmg);
if (tech.isPiezo) m.energy += 20.48; if (tech.isPiezo) m.energy += 20.48;
if (tech.isBayesian) powerUps.ejectTech() if (tech.isStimulatedEmission) powerUps.ejectTech()
if (mob[k].onHit) mob[k].onHit(k); if (mob[k].onHit) mob[k].onHit(k);
if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles
//extra kick between player and mob //this section would be better with forces but they don't work... //extra kick between player and mob //this section would be better with forces but they don't work...

View File

@@ -3,6 +3,107 @@ let powerUp = [];
const powerUps = { const powerUps = {
totalPowerUps: 0, //used for tech that count power ups at the end of a level totalPowerUps: 0, //used for tech that count power ups at the end of a level
lastTechIndex: null, lastTechIndex: null,
do() {},
setDo() {
if (tech.duplicationChance() > 0) {
if (tech.isPowerUpsVanish) {
powerUps.do = powerUps.doDuplicatesVanish
} else {
powerUps.do = powerUps.doDuplicates
}
tech.maxDuplicationEvent() //check to see if hitting 100% duplication
} else {
powerUps.do = powerUps.doDefault
}
},
doDefault() { //draw power ups
ctx.globalAlpha = 0.4 * Math.sin(m.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);
ctx.fillStyle = powerUp[i].color;
ctx.fill();
}
ctx.globalAlpha = 1;
},
doDuplicates() { //draw power ups but give duplicates some electricity
ctx.globalAlpha = 0.4 * Math.sin(m.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);
ctx.fillStyle = powerUp[i].color;
ctx.fill();
}
ctx.globalAlpha = 1;
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (powerUp[i].isDuplicated && Math.random() < 0.1) {
//draw electricity
const mag = 5 + powerUp[i].size / 5
let unit = Vector.rotate({
x: mag,
y: mag
}, 2 * Math.PI * Math.random())
let path = {
x: powerUp[i].position.x + unit.x,
y: powerUp[i].position.y + unit.y
}
ctx.beginPath();
ctx.moveTo(path.x, path.y);
for (let i = 0; i < 6; i++) {
unit = Vector.rotate(unit, 3 * (Math.random() - 0.5))
path = Vector.add(path, unit)
ctx.lineTo(path.x, path.y);
}
ctx.lineWidth = 0.5 + 2 * Math.random();
ctx.strokeStyle = "#000"
ctx.stroke();
}
}
},
doDuplicatesVanish() { //draw power ups but give duplicates some electricity
//remove power ups after 3 seconds
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (powerUp[i].isDuplicated && Math.random() < 0.004) { // (1-0.004)^150 = chance to be removed after 3 seconds
b.explosion(powerUp[i].position, (10 + 3 * Math.random()) * powerUp[i].size);
Matter.World.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1);
break
}
}
ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.25) + 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);
ctx.fillStyle = powerUp[i].color;
ctx.fill();
}
ctx.globalAlpha = 1;
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (powerUp[i].isDuplicated && Math.random() < 0.3) {
//draw electricity
const mag = 5 + powerUp[i].size / 5
let unit = Vector.rotate({
x: mag,
y: mag
}, 2 * Math.PI * Math.random())
let path = {
x: powerUp[i].position.x + unit.x,
y: powerUp[i].position.y + unit.y
}
ctx.beginPath();
ctx.moveTo(path.x, path.y);
for (let i = 0; i < 6; i++) {
unit = Vector.rotate(unit, 3 * (Math.random() - 0.5))
path = Vector.add(path, unit)
ctx.lineTo(path.x, path.y);
}
ctx.lineWidth = 0.5 + 2 * Math.random();
ctx.strokeStyle = "#000"
ctx.stroke();
}
}
},
choose(type, index) { choose(type, index) {
if (type === "gun") { if (type === "gun") {
b.giveGuns(index) b.giveGuns(index)
@@ -175,7 +276,7 @@ const powerUps = {
powerUps.directSpawn(x, y, "heal", false, null, size) powerUps.directSpawn(x, y, "heal", false, null, size)
if (Math.random() < tech.duplicationChance()) { if (Math.random() < tech.duplicationChance()) {
powerUps.directSpawn(x, y, "heal", false, null, size) powerUps.directSpawn(x, y, "heal", false, null, size)
powerUp[powerUp.length - 1].isBonus = true powerUp[powerUp.length - 1].isDuplicated = true
} }
} }
}, },
@@ -640,7 +741,7 @@ const powerUps = {
for (let i = 0; i < tech.tech[choose].count; i++) { for (let i = 0; i < tech.tech[choose].count; i++) {
powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
powerUp[powerUp.length - 1].isBonus = true powerUp[powerUp.length - 1].isDuplicated = true
} }
// remove a random tech from the list of tech you have // remove a random tech from the list of tech you have
tech.tech[choose].remove(); tech.tech[choose].remove();
@@ -655,7 +756,7 @@ const powerUps = {
for (let i = 0; i < tech.tech[choose].count; i++) { for (let i = 0; i < tech.tech[choose].count; i++) {
powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
powerUp[powerUp.length - 1].isBonus = true powerUp[powerUp.length - 1].isDuplicated = true
} }
// remove a random tech from the list of tech you have // remove a random tech from the list of tech you have
tech.tech[choose].remove(); tech.tech[choose].remove();
@@ -720,7 +821,8 @@ const powerUps = {
powerUps.directSpawn(x, y, target, moving, mode, size) powerUps.directSpawn(x, y, target, moving, mode, size)
if (Math.random() < tech.duplicationChance()) { if (Math.random() < tech.duplicationChance()) {
powerUps.directSpawn(x, y, target, moving, mode, size) powerUps.directSpawn(x, y, target, moving, mode, size)
powerUp[powerUp.length - 1].isBonus = true powerUp[powerUp.length - 1].isDuplicated = true
// if (tech.isPowerUpsVanish) powerUp[powerUp.length - 1].endCycle = simulation.cycle + 300
} }
} }
}, },

View File

@@ -20,7 +20,7 @@ const simulation = {
ctx.save(); ctx.save();
simulation.camera(); simulation.camera();
level.custom(); level.custom();
simulation.draw.powerUp(); powerUps.do();
mobs.draw(); mobs.draw();
simulation.draw.cons(); simulation.draw.cons();
simulation.draw.body(); simulation.draw.body();
@@ -900,7 +900,17 @@ const simulation = {
ctx.fillText(`(${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)})`, simulation.mouse.x, simulation.mouse.y - 20); ctx.fillText(`(${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)})`, simulation.mouse.x, simulation.mouse.y - 20);
}, },
draw: { draw: {
powerUp() { //is set by Bayesian tech // powerUp() { //is set by Bayesian tech
// // ctx.globalAlpha = 0.4 * Math.sin(m.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);
// // ctx.fillStyle = powerUp[i].color;
// // ctx.fill();
// // }
// // ctx.globalAlpha = 1;
// },
// powerUpNormal() { //back up in case power up draw gets changed
// ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6; // ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6;
// for (let i = 0, len = powerUp.length; i < len; ++i) { // for (let i = 0, len = powerUp.length; i < len; ++i) {
// ctx.beginPath(); // ctx.beginPath();
@@ -909,52 +919,41 @@ const simulation = {
// ctx.fill(); // ctx.fill();
// } // }
// ctx.globalAlpha = 1; // ctx.globalAlpha = 1;
}, // },
powerUpNormal() { //back up in case power up draw gets changed // powerUpBonus() { //draws crackle effect for bonus power ups
ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6; // ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6;
for (let i = 0, len = powerUp.length; i < len; ++i) { // for (let i = 0, len = powerUp.length; i < len; ++i) {
ctx.beginPath(); // ctx.beginPath();
ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI); // ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI);
ctx.fillStyle = powerUp[i].color; // ctx.fillStyle = powerUp[i].color;
ctx.fill(); // ctx.fill();
} // }
ctx.globalAlpha = 1;
},
powerUpBonus() { //draws crackle effect for bonus power ups
ctx.globalAlpha = 0.4 * Math.sin(m.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);
ctx.fillStyle = powerUp[i].color;
ctx.fill();
}
ctx.globalAlpha = 1;
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (powerUp[i].isBonus && Math.random() < 0.1) {
//draw electricity
const mag = 5 + powerUp[i].size / 5
let unit = Vector.rotate({
x: mag,
y: mag
}, 2 * Math.PI * Math.random())
let path = {
x: powerUp[i].position.x + unit.x,
y: powerUp[i].position.y + unit.y
}
ctx.beginPath();
ctx.moveTo(path.x, path.y);
for (let i = 0; i < 6; i++) {
unit = Vector.rotate(unit, 3 * (Math.random() - 0.5))
path = Vector.add(path, unit)
ctx.lineTo(path.x, path.y);
}
ctx.lineWidth = 0.5 + 2 * Math.random();
ctx.strokeStyle = "#000"
ctx.stroke();
}
}
// ctx.globalAlpha = 1; // ctx.globalAlpha = 1;
}, // for (let i = 0, len = powerUp.length; i < len; ++i) {
// if (powerUp[i].isDuplicated && Math.random() < 0.1) {
// //draw electricity
// const mag = 5 + powerUp[i].size / 5
// let unit = Vector.rotate({
// x: mag,
// y: mag
// }, 2 * Math.PI * Math.random())
// let path = {
// x: powerUp[i].position.x + unit.x,
// y: powerUp[i].position.y + unit.y
// }
// ctx.beginPath();
// ctx.moveTo(path.x, path.y);
// for (let i = 0; i < 6; i++) {
// unit = Vector.rotate(unit, 3 * (Math.random() - 0.5))
// path = Vector.add(path, unit)
// ctx.lineTo(path.x, path.y);
// }
// ctx.lineWidth = 0.5 + 2 * Math.random();
// ctx.strokeStyle = "#000"
// ctx.stroke();
// }
// }
// },
// map: function() { // map: function() {
// ctx.beginPath(); // ctx.beginPath();

View File

@@ -3025,14 +3025,14 @@ const spawn = {
this.attraction(); this.attraction();
}; };
}, },
shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2), isBonusShield = false) { shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2), isExtraShield = false) {
if (this.allowShields && Math.random() < chance) { if (this.allowShields && Math.random() < chance) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)"); mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.stroke = "rgb(220,220,255)"; me.stroke = "rgb(220,220,255)";
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.shield = true; me.shield = true;
me.isBonusShield = isBonusShield //this prevents spamming with tech.isShieldAmmo me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
consBB[consBB.length] = Constraint.create({ consBB[consBB.length] = Constraint.create({

View File

@@ -170,7 +170,7 @@
return dmg * tech.slowFire * tech.aimDamage return dmg * tech.slowFire * tech.aimDamage
}, },
duplicationChance() { duplicationChance() {
return (tech.isBayesian ? 0.2 : 0) + tech.cancelCount * 0.043 + tech.duplicateChance + m.duplicateChance return (tech.isPowerUpsVanish ? 0.2 : 0) + (tech.isStimulatedEmission ? 0.2 : 0) + tech.cancelCount * 0.043 + tech.duplicateChance + m.duplicateChance
}, },
maxDuplicationEvent() { maxDuplicationEvent() {
if (tech.is100Duplicate && tech.duplicationChance() > 0.99) { if (tech.is100Duplicate && tech.duplicationChance() > 0.99) {
@@ -821,7 +821,7 @@
{ {
name: "electric reactive armor", name: "electric reactive armor",
// description: "<strong class='color-e'>explosions</strong> do no <strong class='color-harm'>harm</strong><br> while your <strong class='color-f'>energy</strong> is above <strong>98%</strong>", // description: "<strong class='color-e'>explosions</strong> do no <strong class='color-harm'>harm</strong><br> while your <strong class='color-f'>energy</strong> is above <strong>98%</strong>",
description: "<strong class='color-harm'>harm</strong> from <strong class='color-e'>explosions</strong> is passively reduced<br>by <strong>7%</strong> for every <strong>10</strong> stored <strong class='color-f'>energy</strong>", description: "<strong class='color-harm'>harm</strong> from <strong class='color-e'>explosions</strong> is passively reduced<br>by <strong>6%</strong> for every <strong>10</strong> stored <strong class='color-f'>energy</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
@@ -1790,7 +1790,7 @@
count: 0, count: 0,
frequency: 2, frequency: 2,
allowed() { allowed() {
return tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField || tech.relayIce || tech.blockingIce > 1 return tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField || tech.relayIce || tech.blockingIce > 1 || tech.iceIXOnDeath
}, },
requires: "a localized freeze effect", requires: "a localized freeze effect",
effect() { effect() {
@@ -1807,7 +1807,7 @@
count: 0, count: 0,
frequency: 2, frequency: 2,
allowed() { allowed() {
return tech.isStunField || tech.isExplosionStun || tech.oneSuperBall || tech.isHarmFreeze || tech.isIceField || tech.relayIce || tech.isIceCrystals || tech.isSporeFreeze || tech.isAoESlow || tech.isFreezeMobs || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isWormholeDamage || tech.blockingIce > 1 return tech.isStunField || tech.isExplosionStun || tech.oneSuperBall || tech.isHarmFreeze || tech.isIceField || tech.relayIce || tech.isIceCrystals || tech.isSporeFreeze || tech.isAoESlow || tech.isFreezeMobs || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isWormholeDamage || tech.blockingIce > 1 || tech.iceIXOnDeath
}, },
requires: "a freezing or stunning effect", requires: "a freezing or stunning effect",
effect() { effect() {
@@ -2762,13 +2762,12 @@
requires: "below 100% duplication chance", requires: "below 100% duplication chance",
effect() { effect() {
tech.duplicateChance += 0.075 tech.duplicateChance += 0.075
tech.maxDuplicationEvent() powerUps.setDo(); //needed after adjusting duplication chance
simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw
tech.addJunkTechToPool(12) tech.addJunkTechToPool(12)
}, },
remove() { remove() {
tech.duplicateChance = 0 tech.duplicateChance = 0
if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal powerUps.setDo(); //needed after adjusting duplication chance
if (this.count > 1) tech.removeJunkTechFromPool(12) if (this.count > 1) tech.removeJunkTechFromPool(12)
} }
}, },
@@ -2780,17 +2779,36 @@
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return tech.duplicationChance() < 1 && level.levelsCleared < 6 return tech.duplicationChance() < 1
}, },
requires: "below 100% duplication chance", requires: "below 100% duplication chance",
effect: () => { effect: () => {
tech.isBayesian = true tech.isStimulatedEmission = true
simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw powerUps.setDo(); //needed after adjusting duplication chance
tech.maxDuplicationEvent()
}, },
remove() { remove() {
tech.isBayesian = false tech.isStimulatedEmission = false
if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal powerUps.setDo(); //needed after adjusting duplication chance
}
},
{
name: "metastability",
description: "<strong>20%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong class='color-dup'>duplicates</strong> <strong class='color-e'>explode</strong> with a <strong>3</strong> second half-life",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return tech.duplicationChance() < 1
},
requires: "below 100% duplication chance",
effect: () => {
tech.isPowerUpsVanish = true
powerUps.setDo(); //needed after adjusting duplication chance
},
remove() {
tech.isPowerUpsVanish = false
powerUps.setDo(); //needed after adjusting duplication chance
} }
}, },
{ {
@@ -2801,18 +2819,18 @@
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return tech.duplicationChance() < 1 && !tech.isDeterminism && level.levelsCleared < 4 return tech.duplicationChance() < 1 && !tech.isDeterminism
}, },
requires: "below 100% duplication chance, below level 5, not determinism", requires: "below 100% duplication chance, below level 5, not determinism",
effect() { effect() {
// tech.cancelCount = 0 // tech.cancelCount = 0
tech.isCancelDuplication = true tech.isCancelDuplication = true
simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw powerUps.setDo(); //needed after adjusting duplication chance
}, },
remove() { remove() {
// tech.cancelCount = 0 // tech.cancelCount = 0
tech.isCancelDuplication = false tech.isCancelDuplication = false
if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal powerUps.setDo(); //needed after adjusting duplication chance
} }
}, },
{ {
@@ -2953,7 +2971,7 @@
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span> <span class='color-symbol'>-=</span> 2 simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span> <span class='color-symbol'>-=</span> 2
<br>${powerUps.research.count}`) <br>${powerUps.research.count}`)
const chanceStore = tech.duplicateChance const chanceStore = tech.duplicateChance
tech.duplicateChance = (tech.isBayesian ? 0.2 : 0) + tech.cancelCount * 0.045 + m.duplicateChance + tech.duplicateChance * 2 //increase duplication chance to simulate doubling all 3 sources of duplication chance tech.duplicateChance = (tech.isStimulatedEmission ? 0.2 : 0) + tech.cancelCount * 0.045 + m.duplicateChance + tech.duplicateChance * 2 //increase duplication chance to simulate doubling all 3 sources of duplication chance
powerUps.spawn(m.pos.x, m.pos.y, "tech"); powerUps.spawn(m.pos.x, m.pos.y, "tech");
tech.duplicateChance = chanceStore tech.duplicateChance = chanceStore
}, },
@@ -3703,7 +3721,7 @@
}, },
remove() { remove() {
tech.wavePacketFrequency = 0.088 //0.0968 //0.1012 //0.11 //0.088 //shorten wave packet tech.wavePacketFrequency = 0.088 //0.0968 //0.1012 //0.11 //0.088 //shorten wave packet
tech.wavePacketLength = 36 //32.7 //31.3 //28.8 //36 //how many wave packets are released // double this to emit 2 packets tech.wavePacketLength = 34 //32.7 //31.3 //28.8 //36 //how many wave packets are released // double this to emit 2 packets
tech.waveLengthRange = 130; tech.waveLengthRange = 130;
} }
}, },
@@ -4818,7 +4836,7 @@
count: 0, count: 0,
frequency: 2, frequency: 2,
allowed() { allowed() {
return tech.isIceField || tech.relayIce || tech.blockingIce return tech.isIceField || tech.relayIce || tech.blockingIce || tech.iceIXOnDeath
}, },
requires: "ice IX", requires: "ice IX",
effect() { effect() {
@@ -6528,7 +6546,7 @@
isGunCycle: null, isGunCycle: null,
isFastFoam: null, isFastFoam: null,
isSporeGrowth: null, isSporeGrowth: null,
isBayesian: null, isStimulatedEmission: null,
nailGun: null, nailGun: null,
nailInstantFireRate: null, nailInstantFireRate: null,
isCapacitor: null, isCapacitor: null,

View File

@@ -1,6 +1,7 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** NEXT PATCH ********************************************************
tech: metastability - 20% dup chance, but duplicated powers up eventually explode
nerfed tech: electric reactive armor 6% (was 7%) explosion damage reduction for every 10 energy you currently have
******************************************************** BUGS ******************************************************** ******************************************************** BUGS ********************************************************
@@ -38,6 +39,14 @@ is there a way to check if the player is stuck inside the map or block
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
make wave packets a tech
use the tech that makes the wave packets longer?
default wave can be two oscillating waves
make beating the final boss without undefined feel like winning, not like dieing
try making more things const to change the color to purple in simulation loop
power ups disappear after 3-5 seconds power ups disappear after 3-5 seconds
only apply to drops from killing mobs only apply to drops from killing mobs
+duplication 20% +duplication 20%