fault tolerance

tech: fault tolerance - spawn 9 drones that last forever, remove your drone gun

fade in after death is more gradual
This commit is contained in:
landgreen
2021-10-17 09:00:11 -07:00
parent dbe33239fb
commit 19c008fec1
12 changed files with 264 additions and 71 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -88,12 +88,12 @@
<div style="position: absolute; top:0;right:0;"> <div style="position: absolute; top:0;right:0;">
<div id="pause-grid-right" class="pause-grid"></div> <div id="pause-grid-right" class="pause-grid"></div>
</div> </div>
<svg class="SVG-button" id="experiment-button" width="155" height="40" style="border: 2px #333 solid;"> <svg class="SVG-button ui" id="experiment-button" width="155" height="40" style="border: 2px #333 solid;">
<g stroke='none' fill='#333' stroke-width="2" font-size="28px" font-family="Arial, sans-serif"> <g stroke='none' fill='#333' stroke-width="2" font-size="28px" font-family="Arial, sans-serif">
<text x="10" y="30">experiment</text> <text x="10" y="30">experiment</text>
</g> </g>
</svg> </svg>
<div id='info'> <div id='info' class="ui">
<div id="settings"> <div id="settings">
<details> <details>
<summary>settings</summary> <summary>settings</summary>
@@ -334,7 +334,7 @@
animation: dash 5s ease-in forwards; animation: dash 5s ease-in forwards;
} }
</style> </style>
<svg id='splash' class="intro" viewBox="0 0 800 800" onclick="simulation.startGame()"> <svg id='splash' class="intro ui" viewBox="0 0 800 800" onclick="simulation.startGame()">
<!-- title --> <!-- title -->
<!-- <g class="fade-in" transform="translate(100,210) scale(34)" fill='#bbb' stroke='none'> <!-- <g class="fade-in" transform="translate(100,210) scale(34)" fill='#bbb' stroke='none'>
<path d="M0 0 h1 v0.2 h1.7 l0.3 0.3 v2.6 h-1 v-1.7 h-1 v1.7 h-1 z" fill="rgb(50,200,255)" /> <path d="M0 0 h1 v0.2 h1.7 l0.3 0.3 v2.6 h-1 v-1.7 h-1 v1.7 h-1 z" fill="rgb(50,200,255)" />

View File

@@ -3154,6 +3154,40 @@ const b = {
if (bullet[i].botType && bullet[i].endCycle === Infinity) bullet[i].endCycle = 0 //remove active bots, but don't remove temp bots if (bullet[i].botType && bullet[i].endCycle === Infinity) bullet[i].endCycle = 0 //remove active bots, but don't remove temp bots
} }
}, },
removeBot() {
if (tech.nailBotCount > 1) {
tech.nailBotCount--
return
}
if (tech.laserBotCount > 1) {
tech.laserBotCount--
return
}
if (tech.foamBotCount > 1) {
tech.foamBotCount--
return
}
if (tech.boomBotCount > 1) {
tech.boomBotCount--
return
}
if (tech.orbitBotCount > 1) {
tech.orbitBotCount--
return
}
if (tech.dynamoBotCount > 1) {
tech.dynamoBotCount--
return
}
if (tech.missileBotCount > 1) {
tech.missileBotCount--
return
}
if (tech.plasmaBotCount > 1) {
tech.plasmaBotCount--
return
}
},
zeroBotCount() { //remove all bots zeroBotCount() { //remove all bots
tech.dynamoBotCount = 0 tech.dynamoBotCount = 0
tech.laserBotCount = 0 tech.laserBotCount = 0
@@ -5156,6 +5190,16 @@ const b = {
const length = tech.isLargeHarpoon ? 1 + 0.09 * Math.sqrt(this.ammo) : 1 const length = tech.isLargeHarpoon ? 1 + 0.09 * Math.sqrt(this.ammo) : 1
const totalCycles = 7 * (tech.isFilament ? 1 + 0.009 * Math.min(100, this.ammo) : 1) * Math.sqrt(length) const totalCycles = 7 * (tech.isFilament ? 1 + 0.009 * Math.min(100, this.ammo) : 1) * Math.sqrt(length)
if (input.down) { if (input.down) {
// if (true) {
// if (m.immuneCycle < m.cycle + 60) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles
// b.harpoon(where, closest.target, m.angle, length, false, 15)
// m.fireCDcycle = m.cycle + 50 * b.fireCDscale; // cool down
// const speed = 50
// const velocity = { x: speed * Math.cos(m.angle), y: speed * Math.sin(m.angle) }
// Matter.Body.setVelocity(player, velocity);
// } else {
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, m.pos, mob[i].position).length === 0) { if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, m.pos, mob[i].position).length === 0) {
const dot = Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, m.pos))) //the dot product of diff and dir will return how much over lap between the vectors const dot = Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, m.pos))) //the dot product of diff and dir will return how much over lap between the vectors
@@ -5168,6 +5212,7 @@ const b = {
} }
b.harpoon(where, closest.target, m.angle, length, false, 15) b.harpoon(where, closest.target, m.angle, length, false, 15)
m.fireCDcycle = m.cycle + 50 * b.fireCDscale; // cool down m.fireCDcycle = m.cycle + 50 * b.fireCDscale; // cool down
// }
} else if (tech.extraHarpoons) { } else if (tech.extraHarpoons) {
const range = 450 * (tech.isFilament ? 1 + Math.min(100, this.ammo) / 100 : 1) const range = 450 * (tech.isFilament ? 1 + Math.min(100, this.ammo) / 100 : 1)
let targetCount = 0 let targetCount = 0
@@ -5405,10 +5450,6 @@ const b = {
if ((!input.fire && this.charge > 0.6)) { //fire on mouse release or on low energy if ((!input.fire && this.charge > 0.6)) { //fire on mouse release or on low energy
m.fireCDcycle = m.cycle + 2; // set fire cool down m.fireCDcycle = m.cycle + 2; // set fire cool down
//normal bullet behavior occurs after firing, overwrites this function //normal bullet behavior occurs after firing, overwrites this function
this.do = function() {
this.force.y += this.mass * 0.0003 / this.charge; // low gravity that scales with charge
}
Matter.Body.scale(this, 8000, 8000) // show the bullet by scaling it up (don't judge me... I know this is a bad way to do it) Matter.Body.scale(this, 8000, 8000) // show the bullet by scaling it up (don't judge me... I know this is a bad way to do it)
this.endCycle = simulation.cycle + 140 this.endCycle = simulation.cycle + 140
this.collisionFilter.category = cat.bullet this.collisionFilter.category = cat.bullet
@@ -5423,6 +5464,96 @@ const b = {
y: m.Vy / 2 + speed * this.charge * Math.sin(m.angle) y: m.Vy / 2 + speed * this.charge * Math.sin(m.angle)
}); });
if (tech.isRodAreaDamage) {
this.auraRadius = 800
this.semiMinor = 0.5
this.where = { x: m.pos.x, y: m.pos.y }
this.velocityAura = { x: this.velocity.x, y: this.velocity.y }
this.angleAura = this.angle
this.do = function() {
this.force.y += this.mass * 0.0003 / this.charge; // low gravity that scales with charge
this.velocityAura.y += 0.085 / this.charge;
this.where = Vector.add(this.where, this.velocityAura)
//draw damage aura
this.semiMinor = this.semiMinor * 0.99
this.auraRadius = this.auraRadius * 0.99
let where = Vector.add(Vector.mult(this.velocityAura, -0.5), this.where)
ctx.beginPath();
ctx.ellipse(where.x, where.y, this.auraRadius * 0.25, this.auraRadius * 0.15 * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
ctx.fillStyle = "rgba(255,100,0,0.75)";
ctx.fill();
where = Vector.add(Vector.mult(this.velocity, -1), where)
ctx.beginPath();
ctx.ellipse(where.x, where.y, this.auraRadius * 0.5, this.auraRadius * 0.5 * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
ctx.fillStyle = "rgba(255,50,0,0.35)";
ctx.fill();
where = Vector.add(Vector.mult(this.velocity, -1), where)
ctx.beginPath();
ctx.ellipse(where.x, where.y, this.auraRadius * 0.75, this.auraRadius * 0.7 * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
ctx.fillStyle = "rgba(255,0,0,0.15)";
ctx.fill();
where = Vector.add(Vector.mult(this.velocity, -1), where)
ctx.beginPath();
ctx.ellipse(where.x, where.y, this.auraRadius, this.auraRadius * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
ctx.fillStyle = "rgba(255,0,0,0.03)";
ctx.fill();
// this.semiMinor = this.semiMinor * 0.95 + (1 - Math.min(0.5, this.speed * 0.02)) * 0.05
// this.auraRadius = this.auraRadius * 0.95 + this.speed * 10 * 0.05
// let where = Vector.add(Vector.mult(this.velocity, -1), this.position)
// const angle = Math.atan2(this.velocity.y, this.velocity.x)
// ctx.beginPath();
// ctx.ellipse(where.x, where.y, this.auraRadius * 0.25, this.auraRadius * 0.15 * this.semiMinor, angle, 0, 2 * Math.PI)
// ctx.fillStyle = "rgba(255,100,0,0.75)";
// ctx.fill();
// where = Vector.add(Vector.mult(this.velocity, -2), where)
// ctx.beginPath();
// ctx.ellipse(where.x, where.y, this.auraRadius * 0.5, this.auraRadius * 0.5 * this.semiMinor, angle, 0, 2 * Math.PI)
// ctx.fillStyle = "rgba(255,50,0,0.35)";
// ctx.fill();
// where = Vector.add(Vector.mult(this.velocity, -2), where)
// ctx.beginPath();
// ctx.ellipse(where.x, where.y, this.auraRadius * 0.75, this.auraRadius * 0.7 * this.semiMinor, angle, 0, 2 * Math.PI)
// ctx.fillStyle = "rgba(255,0,0,0.15)";
// ctx.fill();
// where = Vector.add(Vector.mult(this.velocity, -2), where)
// ctx.beginPath();
// ctx.ellipse(where.x, where.y, this.auraRadius, this.auraRadius * this.semiMinor, angle, 0, 2 * Math.PI)
// ctx.fillStyle = "rgba(255,0,0,0.03)";
// ctx.fill();
//damage mobs in a circle based on this.semiMinor radius
if (this.auraRadius > 200) {
for (let i = 0, len = mob.length; i < len; ++i) {
const dist = Vector.magnitude(Vector.sub(mob[i].position, where))
if (dist < mob[i].radius + this.auraRadius) {
//push mob in direction of bullet
const mag = 0.0001
mob[i].force.x += mag * this.velocity.x;
mob[i].force.y += mag * this.velocity.y;
//damage mob
const damage = b.dmgScale * 0.002 * dist
mob[i].damage(damage);
mob[i].locatePlayer();
simulation.drawList.push({ //add dmg to draw queue
x: mob[i].position.x,
y: mob[i].position.y,
radius: Math.log(2 * damage + 1.1) * 40,
color: "rgba(255,0,0,0.25)",
time: simulation.drawTime
});
}
}
}
//push blocks power ups and mobs to the direction the rod is moving
}
} else {
this.do = function() {
this.force.y += this.mass * 0.0003 / this.charge; // low gravity that scales with charge
}
}
//knock back //knock back
const KNOCK = ((input.down) ? 0.1 : 0.5) * this.charge * this.charge * (tech.isShotgunReversed ? -2 : 1) const KNOCK = ((input.down) ? 0.1 : 0.5) * this.charge * this.charge * (tech.isShotgunReversed ? -2 : 1)
player.force.x -= KNOCK * Math.cos(m.angle) player.force.x -= KNOCK * Math.cos(m.angle)

View File

@@ -103,7 +103,6 @@ function collisionChecks(event) {
if ( if (
m.immuneCycle < m.cycle && m.immuneCycle < m.cycle &&
(obj === playerBody || obj === playerHead) && (obj === playerBody || obj === playerHead) &&
// (obj === player) &&
!(tech.isFreezeHarmImmune && (mob[k].isSlowed || mob[k].isStunned)) !(tech.isFreezeHarmImmune && (mob[k].isSlowed || mob[k].isStunned))
) { ) {
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0 let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0

View File

@@ -155,13 +155,9 @@ function setupCanvas() {
canvas.height = window.innerHeight; canvas.height = window.innerHeight;
canvas.width2 = canvas.width / 2; //precalculated because I use this often (in mouse look) canvas.width2 = canvas.width / 2; //precalculated because I use this often (in mouse look)
canvas.height2 = canvas.height / 2; canvas.height2 = canvas.height / 2;
// canvas.diagonal = Math.sqrt(canvas.width2 * canvas.width2 + canvas.height2 * canvas.height2);
// ctx.font = "18px Arial";
// ctx.textAlign = "center";
ctx.font = "25px Arial"; ctx.font = "25px Arial";
ctx.lineJoin = "round"; ctx.lineJoin = "round";
ctx.lineCap = "round"; ctx.lineCap = "round";
// ctx.lineCap='square';
simulation.setZoom(); simulation.setZoom();
} }
setupCanvas(); setupCanvas();

View File

@@ -15,11 +15,10 @@ const level = {
// localSettings.levelsClearedLastGame = 10 // localSettings.levelsClearedLastGame = 10
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// b.giveGuns("laser")
// m.setField("plasma torch") // m.setField("plasma torch")
// tech.giveTech("extruder") // b.giveGuns("railgun")
// tech.giveTech("aerodynamic heating")
// for (let i = 0; i < 2; i++) tech.giveTech("refractory metal") // for (let i = 0; i < 2; i++) tech.giveTech("refractory metal")
// tech.giveTech("mouth")
// tech.giveTech("all-stars") // tech.giveTech("all-stars")
// for (let i = 0; i < 3; i++) tech.giveTech("overcharge") // for (let i = 0; i < 3; i++) tech.giveTech("overcharge")
// for (let i = 0; i < 2; i++) tech.giveTech("laser-bot") // for (let i = 0; i < 2; i++) tech.giveTech("laser-bot")
@@ -78,6 +77,20 @@ const level = {
simulation.draw.setPaths(); simulation.draw.setPaths();
b.respawnBots(); b.respawnBots();
m.resetHistory(); m.resetHistory();
if (tech.isForeverDrones) {
if (tech.isDroneRadioactive) {
for (let i = 0; i < tech.isForeverDrones * 0.25; i++) {
b.droneRadioactive({ x: m.pos.x + 30 * (Math.random() - 0.5), y: m.pos.y + 30 * (Math.random() - 0.5) }, 5)
bullet[bullet.length - 1].endCycle = Infinity
}
} else {
for (let i = 0; i < tech.isForeverDrones; i++) {
b.drone({ x: m.pos.x + 30 * (Math.random() - 0.5), y: m.pos.y + 30 * (Math.random() - 0.5) }, 5)
bullet[bullet.length - 1].endCycle = Infinity
}
}
}
if (tech.isExtraMaxEnergy) { if (tech.isExtraMaxEnergy) {
tech.healMaxEnergyBonus += 0.03 * powerUps.totalPowerUps //Math.min(0.02 * powerUps.totalPowerUps, 0.51) tech.healMaxEnergyBonus += 0.03 * powerUps.totalPowerUps //Math.min(0.02 * powerUps.totalPowerUps, 0.51)
m.setMaxEnergy(); m.setMaxEnergy();
@@ -2294,9 +2307,9 @@ const level = {
spawn.mapRect(5300, -275, 50, 175); spawn.mapRect(5300, -275, 50, 175);
spawn.mapRect(5050, -100, 50, 150); spawn.mapRect(5050, -100, 50, 150);
spawn.mapRect(4850, -275, 50, 175); spawn.mapRect(4850, -275, 50, 175);
level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
spawn.starter(1900, -500, 200) //big boy // spawn.starter(1900, -500, 200) //big boy
// spawn.blockGroup(1900, -500) spawn.blockGroup(1900, -500)
// for (let i = 0; i < 10; ++i) spawn.bodyRect(1600 + 5, -500, 30, 40); // for (let i = 0; i < 10; ++i) spawn.bodyRect(1600 + 5, -500, 30, 40);
// spawn.laserBombingBoss(1900, -500) // spawn.laserBombingBoss(1900, -500)
// for (let i = 0; i < 5; i++) spawn.focuser(1900, -500) // for (let i = 0; i < 5; i++) spawn.focuser(1900, -500)

View File

@@ -438,7 +438,7 @@ const m = {
m.health = 0; m.health = 0;
m.displayHealth(); m.displayHealth();
document.getElementById("text-log").style.opacity = 0; //fade out any active text logs document.getElementById("text-log").style.opacity = 0; //fade out any active text logs
document.getElementById("fade-out").style.opacity = 0.8; //1; //slowly fade to white document.getElementById("fade-out").style.opacity = 0.9; //slowly fade to 90% white on top of canvas
// build.shareURL(false) // build.shareURL(false)
setTimeout(function() { setTimeout(function() {
Composite.clear(engine.world); Composite.clear(engine.world);

View File

@@ -524,14 +524,22 @@ const simulation = {
document.getElementById("choose-grid").style.visibility = "hidden" document.getElementById("choose-grid").style.visibility = "hidden"
document.getElementById("choose-grid").style.opacity = "0" document.getElementById("choose-grid").style.opacity = "0"
document.getElementById("info").style.display = "inline"; document.getElementById("info").style.display = "inline";
document.getElementById("info").style.opacity = "0";
document.getElementById("experiment-button").style.display = "inline" document.getElementById("experiment-button").style.display = "inline"
document.getElementById("experiment-button").style.opacity = "0";
document.getElementById("experiment-grid").style.display = "none" document.getElementById("experiment-grid").style.display = "none"
document.getElementById("pause-grid-left").style.display = "none" document.getElementById("pause-grid-left").style.display = "none"
document.getElementById("pause-grid-right").style.display = "none" document.getElementById("pause-grid-right").style.display = "none"
document.getElementById("splash").style.display = "inline"; document.getElementById("splash").style.display = "inline";
document.getElementById("splash").style.opacity = "0";
document.getElementById("dmg").style.display = "none"; document.getElementById("dmg").style.display = "none";
document.getElementById("health-bg").style.display = "none"; document.getElementById("health-bg").style.display = "none";
document.body.style.cursor = "auto"; document.body.style.cursor = "auto";
setTimeout(() => {
document.getElementById("experiment-button").style.opacity = "1";
document.getElementById("info").style.opacity = "1";
document.getElementById("splash").style.opacity = "1";
}, 200);
}, },
fpsInterval: 0, //set in startGame fpsInterval: 0, //set in startGame
then: null, then: null,
@@ -590,6 +598,7 @@ const simulation = {
document.getElementById("experiment-grid").style.display = "none" document.getElementById("experiment-grid").style.display = "none"
document.getElementById("info").style.display = "none"; document.getElementById("info").style.display = "none";
document.getElementById("experiment-button").style.display = "none"; document.getElementById("experiment-button").style.display = "none";
// document.getElementById("experiment-button").style.opacity = "0";
document.getElementById("splash").onclick = null; //removes the onclick effect so the function only runs once document.getElementById("splash").onclick = null; //removes the onclick effect so the function only runs once
document.getElementById("splash").style.display = "none"; //hides the element that spawned the function document.getElementById("splash").style.display = "none"; //hides the element that spawned the function
document.getElementById("dmg").style.display = "inline"; document.getElementById("dmg").style.display = "inline";

View File

@@ -670,7 +670,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
// console.log(`mass=${me.mass}, radius = ${radius}`) // console.log(`mass=${me.mass}, radius = ${radius}`)
me.accelMag = 0.0002 me.accelMag = 0.0002
me.repulsionRange = 100000 + radius * radius; //squared me.repulsionRange = 200000 + radius * radius; //squared
// me.memory = 120; // me.memory = 120;
me.seeAtDistance2 = 2000000 //1400 vision range 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 Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback

View File

@@ -934,7 +934,7 @@
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return ((m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isDroneTeleport || tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isDroneRadioactive && !tech.isDroneTeleport) || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot return ((m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isDroneTeleport || tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isForeverDrones && !tech.isDroneRadioactive && !tech.isDroneTeleport) || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot
}, },
requires: "super balls, basic or slug shotgun, drones, not irradiated drones or burst drones", requires: "super balls, basic or slug shotgun, drones, not irradiated drones or burst drones",
effect() { effect() {
@@ -1504,7 +1504,7 @@
}, },
{ {
name: "robotics", name: "robotics",
description: `spawn a random <strong>bot</strong><br><strong>quadruple</strong> the <strong class='flicker'>frequency</strong> of finding <strong>bot</strong> <strong class='color-m'>tech</strong>`, description: `spawn <strong>2</strong> random <strong>bots</strong><br><strong>quadruple</strong> the <strong class='flicker'>frequency</strong> of finding <strong>bot</strong> <strong class='color-m'>tech</strong>`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -1515,6 +1515,7 @@
}, },
requires: "at least 2 bots", requires: "at least 2 bots",
effect: () => { effect: () => {
b.randomBot()
b.randomBot() b.randomBot()
for (let i = 0, len = tech.tech.length; i < len; i++) { for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].isBotTech) tech.tech[i].frequency *= 4 if (tech.tech[i].isBotTech) tech.tech[i].frequency *= 4
@@ -1522,8 +1523,12 @@
}, },
remove() { remove() {
if (this.count > 0) { if (this.count > 0) {
b.removeBot()
b.removeBot()
b.clearPermanentBots();
b.respawnBots();
for (let i = 0, len = tech.tech.length; i < len; i++) { for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].isBotTech) tech.tech[i].frequency /= 4 if (tech.tech[i].isBotTech) tech.tech[i].frequency = Math.ceil(tech.tech[i].frequency / 4)
} }
} }
} }
@@ -4384,7 +4389,7 @@
{ {
name: "missile-bot", name: "missile-bot",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Robot' class="link">missile-bot</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Robot' class="link">missile-bot</a>`,
description: "remove your <strong>missile gun</strong><br>gain a <strong class='color-bot'>bot</strong> that fires <strong>missiles</strong> at mobs", description: "gain a <strong class='color-bot'>bot</strong> that fires <strong>missiles</strong> at mobs<br>remove your <strong>missile gun</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -4747,10 +4752,44 @@
tech.wormSurviveDmg = false tech.wormSurviveDmg = false
} }
}, },
{
name: "fault tolerance",
description: "spawn <strong>9</strong> <strong>drones</strong> that last <strong>forever</strong><br>remove your <strong>drone gun</strong>",
isGunTech: true,
maxCount: 3,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("drones") || tech.isForeverDrones
},
requires: "drone gun",
effect() {
const num = 9
tech.isForeverDrones += num
if (tech.haveGunCheck("drones")) b.removeGun("drones")
//spawn drones
if (tech.isDroneRadioactive) {
for (let i = 0; i < num * 0.25; i++) {
b.droneRadioactive({ x: m.pos.x + 30 * (Math.random() - 0.5), y: m.pos.y + 30 * (Math.random() - 0.5) }, 5)
bullet[bullet.length - 1].endCycle = Infinity
}
} else {
for (let i = 0; i < num; i++) {
b.drone({ x: m.pos.x + 30 * (Math.random() - 0.5), y: m.pos.y + 30 * (Math.random() - 0.5) }, 5)
bullet[bullet.length - 1].endCycle = Infinity
}
}
},
remove() {
tech.isForeverDrones = 0
if (this.count && !tech.haveGunCheck("drones")) b.giveGuns("drones")
}
},
{ {
name: "reduced tolerances", name: "reduced tolerances",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Engineering_tolerance' class="link">reduced tolerances</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Engineering_tolerance' class="link">reduced tolerances</a>`,
description: `increase <strong>drones</strong> per ${powerUps.orb.ammo()} or <strong class='color-f'>energy</strong> <strong>66%</strong><br>reduce the average <strong>drone</strong> lifetime by <strong>40%</strong>`, description: `increase <strong>drones</strong> per ${powerUps.orb.ammo()} or <strong class='color-f'>energy</strong> by <strong>66%</strong><br>reduce the average <strong>drone</strong> lifetime by <strong>40%</strong>`,
isGunTech: true, isGunTech: true,
maxCount: 3, maxCount: 3,
count: 0, count: 0,
@@ -4787,7 +4826,7 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return !tech.isExtraMaxEnergy && (tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isSporeField || tech.isMissileField || tech.isIceField))) return !tech.isExtraMaxEnergy && (tech.haveGunCheck("drones") || tech.isForeverDrones || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isSporeField || tech.isMissileField || tech.isIceField)))
}, },
requires: "drones, not inductive coupling", requires: "drones, not inductive coupling",
effect() { effect() {
@@ -4800,7 +4839,7 @@
{ {
name: "drone repair", name: "drone repair",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Unmanned_aerial_vehicle' class="link">drone repair</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Unmanned_aerial_vehicle' class="link">drone repair</a>`,
description: "after a <strong>drone</strong> ends it <strong>redeploys</strong><br>for a <strong>25%</strong> chance to use <strong>1</strong> <strong>drone</strong> <strong class='color-ammo'>ammo</strong>", description: "after a <strong>drone</strong> expires it <strong>redeploys</strong><br>for a <strong>25%</strong> chance to use <strong>1</strong> <strong>drone</strong> <strong class='color-ammo'>ammo</strong>",
// description: "broken <strong>drones</strong> <strong>repair</strong> if the drone <strong class='color-g'>gun</strong> is active<br><strong>repairing</strong> has a <strong>25%</strong> chance to use <strong>1</strong> <strong>drone</strong>", // description: "broken <strong>drones</strong> <strong>repair</strong> if the drone <strong class='color-g'>gun</strong> is active<br><strong>repairing</strong> has a <strong>25%</strong> chance to use <strong>1</strong> <strong>drone</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
@@ -4819,8 +4858,7 @@
} }
}, },
{ {
name: "torque bursts", name: "brushless motor",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Electric_motor#Torque_motor' class="link">torque bursts</a>`,
description: "<strong>drones</strong> rapidly <strong>rush</strong> towards their target<br>increase <strong>drone</strong> collision <strong class='color-d'>damage</strong> by <strong>33%</strong>", description: "<strong>drones</strong> rapidly <strong>rush</strong> towards their target<br>increase <strong>drone</strong> collision <strong class='color-d'>damage</strong> by <strong>33%</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
@@ -4828,7 +4866,7 @@
frequency: 3, frequency: 3,
frequencyDefault: 3, frequencyDefault: 3,
allowed() { allowed() {
return tech.haveGunCheck("drones") && !tech.isDroneRadioactive && !tech.isIncendiary return (tech.haveGunCheck("drones") || tech.isForeverDrones) && !tech.isDroneRadioactive && !tech.isIncendiary
}, },
requires: "drone gun, not irradiated drones, incendiary", requires: "drone gun, not irradiated drones, incendiary",
effect() { effect() {
@@ -4839,7 +4877,7 @@
} }
}, },
{ {
name: "brushless motor", name: "axial flux motor",
description: "<strong>drones</strong> can <strong>rush</strong> <strong>66%</strong> more often<br>increase <strong>drone</strong> collision <strong class='color-d'>damage</strong> by <strong>44%</strong>", description: "<strong>drones</strong> can <strong>rush</strong> <strong>66%</strong> more often<br>increase <strong>drone</strong> collision <strong class='color-d'>damage</strong> by <strong>44%</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
@@ -4867,7 +4905,7 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.droneCycleReduction === 1 && !tech.isIncendiary && !tech.isDroneTeleport && (tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isSporeField || tech.isMissileField || tech.isIceField))) return tech.droneCycleReduction === 1 && !tech.isIncendiary && !tech.isDroneTeleport && (tech.haveGunCheck("drones") || tech.isForeverDrones || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isSporeField || tech.isMissileField || tech.isIceField)))
}, },
requires: "drones, not reduced tolerances, incendiary, torque bursts", requires: "drones, not reduced tolerances, incendiary, torque bursts",
effect() { effect() {
@@ -5183,6 +5221,25 @@
tech.isRailAreaDamage = false; tech.isRailAreaDamage = false;
} }
}, },
{
name: "aerodynamic heating",
description: "<strong>railgun</strong> rod <strong class='color-d'>damage</strong> nearby mobs",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("railgun")
},
requires: "railgun",
effect() {
tech.isRodAreaDamage = true;
},
remove() {
tech.isRodAreaDamage = false;
}
},
{ {
name: "capacitor bank", name: "capacitor bank",
description: "the <strong>railgun</strong> no longer takes time to <strong>charge</strong><br><strong>railgun</strong> rods are <strong>66%</strong> less massive", description: "the <strong>railgun</strong> no longer takes time to <strong>charge</strong><br><strong>railgun</strong> rods are <strong>66%</strong> less massive",
@@ -5971,9 +6028,9 @@
isBot: true, isBot: true,
isBotTech: true, isBotTech: true,
allowed() { allowed() {
return !tech.isExtruder && m.fieldUpgrades[m.fieldMode].name === "plasma torch" && (build.isExperimentSelection || powerUps.research.count > 0) return m.fieldUpgrades[m.fieldMode].name === "plasma torch" && (build.isExperimentSelection || powerUps.research.count > 0)
}, },
requires: "plasma torch, not extruder", requires: "plasma torch",
effect() { effect() {
tech.plasmaBotCount++; tech.plasmaBotCount++;
b.plasmaBot(); b.plasmaBot();
@@ -6030,9 +6087,9 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return m.fieldUpgrades[m.fieldMode].name === "plasma torch" && tech.plasmaBotCount === 0 return m.fieldUpgrades[m.fieldMode].name === "plasma torch"
}, },
requires: "plasma torch, not plasma-bot", requires: "plasma torch",
effect() { effect() {
tech.isExtruder = true; tech.isExtruder = true;
m.fieldUpgrades[m.fieldMode].set() m.fieldUpgrades[m.fieldMode].set()
@@ -8486,5 +8543,7 @@
removeMaxHealthOnKill: null, removeMaxHealthOnKill: null,
isSpawnExitTech: null, isSpawnExitTech: null,
cloakDuplication: null, cloakDuplication: null,
extruderRange: null extruderRange: null,
isRodAreaDamage: null,
isForeverDrones: null
} }

View File

@@ -54,6 +54,7 @@ em {
width: 100%; width: 100%;
height: 100%; height: 100%;
z-index: 2; z-index: 2;
transition: opacity 5s ease-in;
} }
*:focus { *:focus {
@@ -121,6 +122,7 @@ summary {
bottom: 3px; bottom: 3px;
right: 3px; right: 3px;
z-index: 12; z-index: 12;
transition: opacity 5s ease-in;
} }
#construct { #construct {
@@ -360,6 +362,7 @@ summary {
left: 3px; left: 3px;
z-index: 12; z-index: 12;
font-size: 1.5em; font-size: 1.5em;
transition: opacity 5s ease-in;
} }
.details-div { .details-div {

View File

@@ -1,22 +1,26 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
after you die your canvas sticks around at 10% opacity tech: fault tolerance - spawn 9 drones that last forever, remove your drone gun
add a mouse over underline effect to hint that names are links
molecular assembler: all 3 manufacturing tech cost 3 -> 1 research fade in after death is more gradual
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
death animation ideas: tech rocket jump - jumping produces an explosion at your feet that lets you jump extra high, but does some damage
redraw game in strange ways, to show that it's a simulation (for example the testing mode is a strange redraw of map)
stroke only, but connect all vertices together, no moveTo
draw dots at all the vertices
buff railgun harpoon tech: dash - press down and fire to go immune to harm for 1 second and dash forward with your harpoon acting like a lance
relativistic jets: fire something out the front and back after you fire harpoon replace it's this.do() with just being in front of player
alternate name: gamma-ray burst
harpoon grappling hook - basic effect is working, but needs work before it becomes fun
tech: aerodynamic heating - railgun rods super heat the air around it doing AoE damage
tech: relativistic jets:
small particles that shot out from front and back poles and end up in a wide variety of spirals small particles that shot out from front and back poles and end up in a wide variety of spirals
slow trickle when charging and several more when firing slow trickle when charging and several more when firing
Tech: Make player smol
adapt the cloaking graphics to make a flashlight cone visual effect adapt the cloaking graphics to make a flashlight cone visual effect
put code in level.do? put code in level.do?
@@ -26,30 +30,8 @@ be nice if block throwing had a projected path
JUNK tech: planetesimals game inside n-gon JUNK tech: planetesimals game inside n-gon
https://codepen.io/lilgreenland/pen/jrMvaB?editors=0010 https://codepen.io/lilgreenland/pen/jrMvaB?editors=0010
Tech: Make player smol
disable zoom progress when paused disable zoom progress when paused
harpoon
post launch tracking: more airFriction, more thrust, harder turning
if no target found slow down and aim much better?
harpoon tech
crouch fire grapple hook
attaches to map at long range and pulls player?
tech that buffs alt fire:
remove the string, all shots are alt fire
alt fire has a 50% chance to not use ammo?
holding down fire lets the string extend farther,
this can overwrite crouch mode
can't have 2+ harpoons
it uses up ammo as extends, and returns it as it contracts?
will this effect performance?
2+ harpoons, with separate CDs
can't have extended string?
grappling hook?
tracking so good harpoon can hit a target, circle around and hit it again
doesn't seem to be good physics, the harpoon hits walls and doesn't get room to build up speed
"Interstellar Disturbance": Cosmic String applies to mobs who cross the wormhole's path, even after initial wormholing, but at reduced damage and stun time. "Interstellar Disturbance": Cosmic String applies to mobs who cross the wormhole's path, even after initial wormholing, but at reduced damage and stun time.
on mouse down wormhole shows a possible wormhole on mouse down wormhole shows a possible wormhole
@@ -453,6 +435,7 @@ possible names for tech
nonlocal nonlocal
fine-tuned universe fine-tuned universe
eternalism https://en.wikipedia.org/wiki/Eternalism_(philosophy_of_time) eternalism https://en.wikipedia.org/wiki/Eternalism_(philosophy_of_time)
axial motor
a tutorial / lore intro a tutorial / lore intro
needs to be optional so it doesn't slow experienced players needs to be optional so it doesn't slow experienced players