autonomous navigation

tech: autonomous navigation - drones travel with you through levels and drones reset durability
tech: technical debt - increase damage by 300%, but reduce damage by 10% for each tech you have

molecular assembler now has a higher bullet spawn cap 200->300
  but it increases energy cost per spawn above around 150

fragments are about 15% fewer
thermal runaway is about 40% bigger and more damage
plasma torch: extruder uses less energy
pilot wave uses less energy

bug fixes
This commit is contained in:
landgreen
2022-03-12 05:48:52 -08:00
parent d39e5c784d
commit fc64d2daa4
8 changed files with 134 additions and 70 deletions

View File

@@ -765,7 +765,7 @@ const b = {
bullet[me].explodeRad = 300 * size;
bullet[me].onEnd = function() {
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 2 * Math.random()))
if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 1.5 * Math.random()))
}
bullet[me].minDmgSpeed = 1;
bullet[me].beforeDmg = function() {
@@ -790,7 +790,7 @@ const b = {
bullet[me].explodeRad = 305 * size;
bullet[me].onEnd = function() {
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 2 * Math.random()))
if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 1.5 * Math.random()))
}
bullet[me].minDmgSpeed = 1;
bullet[me].beforeDmg = function() {
@@ -825,7 +825,7 @@ const b = {
bullet[me].explodeRad = 350 * size + Math.floor(Math.random() * 50) + tech.isBlockExplode * 110
bullet[me].onEnd = function() {
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 2 * Math.random()))
if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 1.5 * Math.random()))
}
bullet[me].minDmgSpeed = 1;
bullet[me].beforeDmg = function() {
@@ -902,7 +902,7 @@ const b = {
bullet[me].explodeRad = 350 * size + Math.floor(Math.random() * 50) + tech.isBlockExplode * 100
bullet[me].onEnd = function() {
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
if (tech.fragments) b.targetedNail(this.position, tech.fragments * 5)
if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 1.5 * Math.random()))
}
bullet[me].beforeDmg = function() {
this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion
@@ -1253,7 +1253,7 @@ const b = {
requestAnimationFrame(() => { who.isShielded = true });
}
if (tech.fragments) {
b.targetedNail(this.vertices[2], tech.fragments * 4)
b.targetedNail(this.vertices[2], tech.fragments * Math.floor(2 + 1.5 * Math.random()))
this.endCycle = 0;
}
if (!who.isBadTarget) {
@@ -1373,7 +1373,7 @@ const b = {
requestAnimationFrame(() => { who.isShielded = true });
}
if (tech.fragments) {
b.targetedNail(this.vertices[2], tech.fragments * 3)
b.targetedNail(this.vertices[2], tech.fragments * Math.floor(2 + Math.random()))
}
// if (!who.isBadTarget) {
// this.do = this.returnToPlayer
@@ -1635,7 +1635,7 @@ const b = {
requestAnimationFrame(() => { who.isShielded = true });
}
if (tech.fragments) {
b.targetedNail(this.vertices[2], tech.fragments * 3)
b.targetedNail(this.vertices[2], tech.fragments * Math.floor(2 + Math.random()))
if (!isReturn) this.endCycle = 0;
}
if (!who.isBadTarget) {
@@ -1927,7 +1927,7 @@ const b = {
},
onEnd() {
b.explosion(this.position, this.explodeRad * size); //makes bullet do explosive damage at end
if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 2 * Math.random()))
if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 1.5 * Math.random()))
},
lockedOn: null,
tryToLockOn() {
@@ -2002,7 +2002,7 @@ const b = {
didExtruderDrain: false,
canExtruderFire: true,
extruder() {
const DRAIN = 0.0021
const DRAIN = 0.0018
if (m.energy > DRAIN && b.canExtruderFire) {
m.energy -= DRAIN
if (m.energy < 0) {
@@ -2854,7 +2854,6 @@ const b = {
},
minDmgSpeed: 0,
lockedOn: null,
isFollowMouse: true,
beforeDmg(who) {
mobs.statusSlow(who, 180)
this.endCycle = simulation.cycle
@@ -2923,17 +2922,17 @@ const b = {
lookFrequency: (tech.isDroneFastLook ? 20 : 70) + Math.floor(17 * Math.random()),
endCycle: simulation.cycle + Math.floor((950 + 400 * Math.random()) * tech.isBulletsLastLonger * tech.droneCycleReduction) + 5 * RADIUS + Math.max(0, 150 - bullet.length),
classType: "bullet",
isDrone: true,
collisionFilter: {
category: cat.bullet,
mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield //self collide
},
minDmgSpeed: 0,
lockedOn: null,
isFollowMouse: true,
deathCycles: 110 + RADIUS * 5,
isImproved: false,
beforeDmg(who) {
if (tech.isIncendiary && simulation.cycle + this.deathCycles < this.endCycle) {
if (tech.isIncendiary && simulation.cycle + this.deathCycles < this.endCycle && !tech.isForeverDrones) {
const max = Math.max(Math.min(this.endCycle - simulation.cycle - this.deathCycles, 1500), 0)
b.explosion(this.position, max * 0.1 + this.isImproved * 110 + 60 * Math.random()); //makes bullet do explosive damage at end
if (tech.isForeverDrones) {
@@ -3127,6 +3126,7 @@ const b = {
lookFrequency: 120 + Math.floor(23 * Math.random()),
endCycle: simulation.cycle + Math.floor((900 + 110 * Math.random()) * tech.isBulletsLastLonger / tech.droneRadioDamage) + 5 * RADIUS + Math.max(0, 150 - 2 * bullet.length),
classType: "bullet",
isDrone: true,
collisionFilter: {
category: cat.bullet,
mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield //self collide
@@ -3134,7 +3134,6 @@ const b = {
minDmgSpeed: 0,
speedCap: 5 + 2 * Math.random(), //6 is normal
lockedOn: null,
isFollowMouse: true,
deathCycles: 110 + RADIUS * 5,
isImproved: false,
radioRadius: 0,
@@ -4790,7 +4789,7 @@ const b = {
}
if (tech.isNailRadiation) mobs.statusDoT(who, 7 * (tech.isFastRadiation ? 0.7 : 0.24), tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles
if (this.speed > 4 && tech.fragments) {
b.targetedNail(this.position, 1.5 * tech.fragments * tech.bulletSize)
b.targetedNail(this.position, 1.25 * tech.fragments * tech.bulletSize)
this.endCycle = 0 //triggers despawn
}
};
@@ -4861,7 +4860,7 @@ const b = {
}
if (tech.isNailRadiation) mobs.statusDoT(who, 7 * (tech.isFastRadiation ? 0.7 : 0.24), tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles
if (this.speed > 4 && tech.fragments) {
b.targetedNail(this.position, 1.5 * tech.fragments * tech.bulletSize)
b.targetedNail(this.position, 1.25 * tech.fragments * tech.bulletSize)
this.endCycle = 0 //triggers despawn
}
};
@@ -5017,7 +5016,7 @@ const b = {
if (tech.fragments) {
bullet[me].beforeDmg = function() {
if (this.speed > 4) {
b.targetedNail(this.position, 7 * tech.fragments * tech.bulletSize)
b.targetedNail(this.position, 6 * tech.fragments * tech.bulletSize)
this.endCycle = 0 //triggers despawn
}
}

View File

@@ -15,13 +15,13 @@ const level = {
start() {
if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.isHorizontalFlipped = true
// m.setField("time dilation")
// b.giveGuns("foam")
// tech.giveTech("quantum foam")
// tech.giveTech("capacitor bank")
// tech.giveTech("isotropic radiator")
// m.setField("molecular assembler")
// b.giveGuns("drones")
// tech.giveTech("autonomous navigation")
// tech.giveTech("delivery drone")
// tech.giveTech("dynamo-bot upgrade")
// for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech");
// for (let i = 0; i < 3; i++) tech.giveTech("undefined")
// for (let i = 0; i < 9; i++) tech.giveTech("dynamo-bot")
// for (let i = 10; i < tech.tech.length; i++) { tech.tech[i].isBanished = true }
// powerUps.research.changeRerolls(100000)
// for (let i = 0; i < 2; i++) tech.giveTech("laser-bot")

View File

@@ -1151,7 +1151,7 @@ const mobs = {
for (let i = 0; i < len; i++) b.spore(this.position)
}
} else if (tech.isExplodeMob) {
b.explosion(this.position, Math.min(600, Math.sqrt(this.mass + 1.5) * (22 + 60 * Math.random())))
b.explosion(this.position, Math.min(700, Math.sqrt(this.mass + 6) * (30 + 60 * Math.random())))
} else if (tech.nailsDeathMob) {
b.targetedNail(this.position, tech.nailsDeathMob, 39 + 6 * Math.random())
}

View File

@@ -1957,11 +1957,12 @@ const m = {
// m.fieldMeterColor = "#0c5"
// m.eyeFillColor = m.fieldMeterColor
m.hold = function() {
if (m.energy > m.maxEnergy - 0.02 && m.fieldCDcycle < m.cycle && !input.field && bullet.length < 200 && (m.cycle % 2)) {
if (m.energy > m.maxEnergy - 0.02 && m.fieldCDcycle < m.cycle && !input.field && bullet.length < 300 && (m.cycle % 2)) {
if (tech.isSporeField) {
if (tech.isSporeWorm) {
if (m.energy > 0.16) {
m.energy -= 0.16
const drain = 0.16 + (Math.max(bullet.length, 130) - 130) * 0.02
if (m.energy > drain) {
m.energy -= drain
b.worm({ x: m.pos.x + 35 * Math.cos(m.angle), y: m.pos.y + 35 * Math.sin(m.angle) })
const SPEED = 2 + 1 * Math.random();
Matter.Body.setVelocity(bullet[bullet.length - 1], {
@@ -1970,13 +1971,13 @@ const m = {
});
}
} else {
const drain = 0.08 + (Math.max(bullet.length, 130) - 130) * 0.01
for (let i = 0, len = Math.random() * 20; i < len; i++) {
m.energy -= 0.08
if (m.energy > 0) {
if (m.energy > drain) {
m.energy -= drain
b.spore(m.pos)
} else {
m.energy = 0.001
break;
break
}
}
}
@@ -1987,11 +1988,19 @@ const m = {
m.energy -= 0.04;
b.iceIX(1)
} else if (tech.isDroneRadioactive) {
m.energy -= 0.8;
b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 25)
const drain = 0.8 + (Math.max(bullet.length, 50) - 50) * 0.01
if (m.energy > drain) {
m.energy -= drain
b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 25)
}
} else {
m.energy -= 0.45 * tech.droneEnergyReduction;
b.drone()
//every bullet above 100 adds 0.005 to the energy cost per drone
//at 200 bullets the energy cost is 0.45 + 100*0.006 = 1.05
const drain = (0.45 + (Math.max(bullet.length, 100) - 100) * 0.006) * tech.droneEnergyReduction
if (m.energy > drain) {
m.energy -= drain
b.drone()
}
}
}
@@ -2775,7 +2784,7 @@ const m = {
for (let i = 0, len = body.length; i < len; ++i) {
if (Vector.magnitude(Vector.sub(body[i].position, m.fieldPosition)) < m.fieldRadius && !body[i].isNotHoldable) {
const DRAIN = speed * body[i].mass * 0.000006 // * (1 + m.energy * m.energy) //drain more energy when you have more energy
const DRAIN = speed * body[i].mass * 0.000005 // * (1 + m.energy * m.energy) //drain more energy when you have more energy
if (m.energy > DRAIN) {
m.energy -= DRAIN;
Matter.Body.setVelocity(body[i], velocity); //give block mouse velocity

View File

@@ -821,6 +821,44 @@ const simulation = {
level.zones = [];
simulation.drawList = [];
if (tech.isDronesTravel) {
//count drones
let count = 0
let deliveryCount = 0
for (let i = 0; i < bullet.length; ++i) {
if (bullet[i].isDrone) {
count++
if (bullet[i].isImproved) deliveryCount++
}
}
// count *= 2
//respawn drones in animation frame
let respawnDrones = () => {
if (count > 0) {
requestAnimationFrame(respawnDrones);
if (!simulation.paused && !simulation.isChoosing) {
count--
const where = { x: level.enter.x + 50, y: level.enter.y - 60 }
if (tech.isDroneRadioactive) {
b.droneRadioactive({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 100 * (Math.random() - 0.5) }, 0)
} else {
b.drone({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 120 * (Math.random() - 0.5) }, 0)
if (tech.isDroneGrab && deliveryCount > 0) {
const who = bullet[bullet.length - 1]
who.isImproved = true;
const SCALE = 2.25
Matter.Body.scale(who, SCALE, SCALE);
who.lookFrequency = 30 + Math.floor(11 * Math.random());
who.endCycle += 3000 * tech.droneCycleReduction * tech.isBulletsLastLonger
deliveryCount--
}
}
}
}
}
requestAnimationFrame(respawnDrones);
}
function removeAll(array) {
// for (let i = 0; i < array.length; ++i) Matter.Composite.remove(engine.world, array[i]);
for (let i = 0; i < array.length; ++i) Matter.Composite.remove(engine.world, array[i]);

View File

@@ -211,6 +211,7 @@ const tech = {
},
damageFromTech() {
let dmg = 1 //m.fieldDamage
if (tech.isTechDebt) dmg *= 4 - 0.1 * tech.totalCount
if (tech.isAxion && tech.isHarmMACHO) dmg *= 1 + 0.75 * (1 - m.harmReduction())
if (tech.OccamDamage) dmg *= tech.OccamDamage
if (tech.isCloakingDamage) dmg *= 1.35
@@ -3082,6 +3083,26 @@ const tech = {
tech.isPauseEjectTech = false;
}
},
{
name: "technical debt", // overengineering
// description: `increase <strong class='color-d'>damage</strong> by <strong>300%</strong> minus <strong>10%</strong> for <strong class='color-m'>tech</strong> you have learned(${4 - 0.1 * tech.totalCount})`,
// description: `increase <strong class='color-d'>damage</strong> by <strong>300%</strong>, but reduce <strong class='color-d'>damage</strong><br>by <strong>10%</strong> for <strong class='color-m'>tech</strong> you have learned`,
descriptionFunction() {
return `increase <strong class='color-d'>damage</strong> by <strong>300%</strong> minus <strong>10%</strong><br>for <strong class='color-m'>tech</strong> you have learned <em>(${Math.floor(100*(4 - 0.1 * tech.totalCount))-100}%)</em>`
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
effect() {
tech.isTechDebt = true;
},
remove() {
tech.isTechDebt = false;
}
},
{
name: "abiogenesis",
description: `at the start of a level spawn a 2nd <strong>boss</strong><br>use ${powerUps.orb.research(4)}or add <strong>49%</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool`,
@@ -5021,7 +5042,7 @@ const tech = {
{
name: "reduced tolerances",
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> by <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 average <strong>drone</strong> <strong>durability</strong> by <strong>40%</strong>`,
isGunTech: true,
maxCount: 3,
count: 0,
@@ -5089,6 +5110,25 @@ const tech = {
tech.isDroneRespawn = false
}
},
{
name: "autonomous navigation",
description: "<strong>drones</strong> travel with you through <strong>levels</strong><br>and reset their <strong>durability</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isSporeField || tech.isMissileField || tech.isIceField))
},
requires: "drones",
effect() {
tech.isDronesTravel = true
},
remove() {
tech.isDronesTravel = false
}
},
{
name: "brushless motor",
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>",
@@ -5212,9 +5252,9 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
return tech.haveGunCheck("drones", false) && !tech.isDroneRespawn && tech.isBulletsLastLonger === 1
return tech.haveGunCheck("drones", false) && !tech.isDroneRespawn && tech.isBulletsLastLonger === 1 && !tech.isDronesTravel
},
requires: "drones, not drone repair, anti-shear topology",
requires: "drones, not drone repair, anti-shear topology, autonomous navigation",
effect() {
const num = 6
tech.isForeverDrones += num
@@ -6337,7 +6377,6 @@ const tech = {
for (let i = 0; i < 3; i++) {
if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
}
//fill array of available bots
const notUpgradedBots = []
const num = 2
@@ -9497,4 +9536,6 @@ const tech = {
isRailGun: null,
isGrapple: null,
isImmuneGrapple: null,
isDronesTravel: null,
isTechDebt: null
}