shotgun rivets

some shotgun ammo tech upgrades will continue to fire some original recipe shotgun bullets
  rivets, fleas, worms, iceIX
tech: band gap - boosts give more damage but it lasts for 1 less second

WIMPs are 10% faster
controlled explosion renamed shaped charge

bug fixes
  construction mode works better with my buttons
  to unlock run this and press T to enter testing mode
  simulation.enableConstructMode() //used to build maps in testing mode

removed -experiment- tech because it's function was reproduced by "tech - tinker"
This commit is contained in:
landgreen
2022-08-28 19:47:32 -07:00
parent 6d1e62d6b8
commit cc1bbeb53b
11 changed files with 525 additions and 378 deletions

View File

@@ -1926,7 +1926,7 @@ const b = {
if (tech.isMissileBig) {
size *= 1.55
if (tech.isMissileBiggest) {
size *= 2
size *= 1.55
}
}
@@ -2015,7 +2015,7 @@ const b = {
ctx.fill();
},
});
const thrust = 0.0066 * bullet[me].mass * (tech.isMissileBig ? (tech.isMissileBiggest ? 0.15 : 0.7) : 1);
const thrust = 0.0066 * bullet[me].mass * (tech.isMissileBig ? (tech.isMissileBiggest ? 0.3 : 0.7) : 1);
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + speed * Math.cos(angle),
y: m.Vy / 2 + speed * Math.sin(angle)
@@ -5463,16 +5463,40 @@ const b = {
player.force.y -= knock * Math.sin(m.angle) * 0.5 //reduce knock back in vertical direction to stop super jumps
}
const spray = (num) => {
const side = 22
for (let i = 0; i < num; i++) {
const me = bullet.length;
const dir = m.angle + (Math.random() - 0.5) * spread
bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle) + 15 * (Math.random() - 0.5), m.pos.y + 35 * Math.sin(m.angle) + 15 * (Math.random() - 0.5), side, side, b.fireAttributes(dir));
Composite.add(engine.world, bullet[me]); //add bullet to world
const SPEED = 52 + Math.random() * 8
Matter.Body.setVelocity(bullet[me], {
x: SPEED * Math.cos(dir),
y: SPEED * Math.sin(dir)
});
bullet[me].endCycle = simulation.cycle + 40 * tech.isBulletsLastLonger
bullet[me].minDmgSpeed = 15
if (tech.isShotgunReversed) Matter.Body.setDensity(bullet[me], 0.0015)
// bullet[me].restitution = 0.4
bullet[me].frictionAir = 0.034;
bullet[me].do = function() {
const scale = 1 - 0.034 / tech.isBulletsLastLonger
Matter.Body.scale(this, scale, scale);
};
}
}
b.muzzleFlash(35);
if (tech.isRivets) {
const me = bullet.length;
// const dir = m.angle + 0.02 * (Math.random() - 0.5)
bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle), m.pos.y + 35 * Math.sin(m.angle), 60 * tech.bulletSize, 27 * tech.bulletSize, b.fireAttributes(m.angle));
bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle), m.pos.y + 35 * Math.sin(m.angle), 56 * tech.bulletSize, 25 * tech.bulletSize, b.fireAttributes(m.angle));
Matter.Body.setDensity(bullet[me], 0.007 * (tech.isShotgunReversed ? 1.6 : 1));
Matter.Body.setDensity(bullet[me], 0.005 * (tech.isShotgunReversed ? 1.5 : 1));
Composite.add(engine.world, bullet[me]); //add bullet to world
const SPEED = (input.down ? 50 : 37)
const SPEED = (input.down ? 50 : 43)
Matter.Body.setVelocity(bullet[me], {
x: SPEED * Math.cos(m.angle),
y: SPEED * Math.sin(m.angle)
@@ -5480,7 +5504,7 @@ const b = {
if (tech.isIncendiary) {
bullet[me].endCycle = simulation.cycle + 60
bullet[me].onEnd = function() {
b.explosion(this.position, 300 + (Math.random() - 0.5) * 60); //makes bullet do explosive damage at end
b.explosion(this.position, 360 + (Math.random() - 0.5) * 60); //makes bullet do explosive damage at end
}
bullet[me].beforeDmg = function() {
this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion
@@ -5490,10 +5514,10 @@ const b = {
}
bullet[me].minDmgSpeed = 7
// bullet[me].restitution = 0.4
bullet[me].frictionAir = 0.006;
bullet[me].frictionAir = 0.004;
bullet[me].turnMag = 0.04 * Math.pow(tech.bulletSize, 3.75)
bullet[me].do = function() {
this.force.y += this.mass * 0.0022
this.force.y += this.mass * 0.002
if (this.speed > 6) { //rotates bullet to face current velocity?
const facing = { x: Math.cos(this.angle), y: Math.sin(this.angle) }
if (Vector.cross(Vector.normalise(this.velocity), facing) < 0) {
@@ -5512,9 +5536,11 @@ const b = {
b.targetedNail(this.position, 6 * tech.fragments * tech.bulletSize)
this.endCycle = 0 //triggers despawn
}
if (tech.isIncendiary) this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion
if (tech.isCritKill) b.crit(who, this)
}
}
spray(12); //fires normal shotgun bullets
} else if (tech.isIncendiary) {
spread *= 0.15
const END = Math.floor(input.down ? 10 : 7);
@@ -5534,7 +5560,7 @@ const b = {
y: speed * Math.sin(dirOff)
});
bullet[me].onEnd = function() {
b.explosion(this.position, 150 * (tech.isShotgunReversed ? 1.5 : 1) + (Math.random() - 0.5) * 40); //makes bullet do explosive damage at end
b.explosion(this.position, 150 * (tech.isShotgunReversed ? 1.4 : 1) + (Math.random() - 0.5) * 40); //makes bullet do explosive damage at end
}
bullet[me].beforeDmg = function() {
this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion
@@ -5546,7 +5572,7 @@ const b = {
}
} else if (tech.isNailShot) {
spread *= 0.65
const dmg = 2 * (tech.isShotgunReversed ? 1.6 : 1)
const dmg = 2 * (tech.isShotgunReversed ? 1.5 : 1)
if (input.down) {
for (let i = 0; i < 17; i++) {
speed = 38 + 15 * Math.random()
@@ -5576,47 +5602,49 @@ const b = {
}
} else if (tech.isSporeFlea) {
const where = { x: m.pos.x + 35 * Math.cos(m.angle), y: m.pos.y + 35 * Math.sin(m.angle) }
const number = 4 * (tech.isShotgunReversed ? 1.6 : 1)
const number = 2 * (tech.isShotgunReversed ? 1.5 : 1)
for (let i = 0; i < number; i++) {
const angle = m.angle + 0.2 * (Math.random() - 0.5)
const speed = (input.down ? 33 : 20) * (1 + 0.1 * Math.random())
const speed = (input.down ? 35 * (1 + 0.05 * Math.random()) : 30 * (1 + 0.15 * Math.random()))
b.flea(where, { x: speed * Math.cos(angle), y: speed * Math.sin(angle) })
bullet[bullet.length - 1].setDamage()
}
spray(10); //fires normal shotgun bullets
} else if (tech.isSporeWorm) {
const where = { x: m.pos.x + 35 * Math.cos(m.angle), y: m.pos.y + 35 * Math.sin(m.angle) }
const spread = (input.down ? 0.02 : 0.07)
const number = 4 * (tech.isShotgunReversed ? 1.6 : 1)
const number = 3 * (tech.isShotgunReversed ? 1.5 : 1)
let angle = m.angle - (number - 1) * spread * 0.5
for (let i = 0; i < number; i++) {
b.worm(where)
const SPEED = (8 + 10 * input.down) * (1 + 0.15 * Math.random())
const SPEED = (30 + 10 * input.down) * (1 + 0.2 * Math.random())
Matter.Body.setVelocity(bullet[bullet.length - 1], {
x: player.velocity.x * 0.5 + SPEED * Math.cos(angle),
y: player.velocity.y * 0.5 + SPEED * Math.sin(angle)
});
angle += spread
}
spray(7); //fires normal shotgun bullets
} else if (tech.isIceShot) {
const spread = (input.down ? 0.7 : 1.2)
for (let i = 0, len = 16 * (tech.isShotgunReversed ? 1.6 : 1); i < len; i++) {
// iceIX(speed = 0, dir = m.angle + Math.PI * 2 * Math.random(), where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }) {
b.iceIX(25 + 20 * Math.random(), m.angle + spread * (Math.random() - 0.5))
for (let i = 0, len = 10 * (tech.isShotgunReversed ? 1.5 : 1); i < len; i++) {
b.iceIX(23 + 10 * Math.random(), m.angle + spread * (Math.random() - 0.5))
}
spray(10); //fires normal shotgun bullets
} else if (tech.isFoamShot) {
const spread = (input.down ? 0.15 : 0.4)
const where = {
x: m.pos.x + 25 * Math.cos(m.angle),
y: m.pos.y + 25 * Math.sin(m.angle)
}
const number = 16 * (tech.isShotgunReversed ? 1.6 : 1)
const number = 16 * (tech.isShotgunReversed ? 1.5 : 1)
for (let i = 0; i < number; i++) {
const SPEED = 11 + 4 * Math.random();
const SPEED = 13 + 4 * Math.random();
const angle = m.angle + spread * (Math.random() - 0.5)
b.foam(where, { x: SPEED * Math.cos(angle), y: SPEED * Math.sin(angle) }, 8 + 7 * Math.random())
}
} else if (tech.isNeedles) {
const number = 9 * (tech.isShotgunReversed ? 1.6 : 1)
const number = 9 * (tech.isShotgunReversed ? 1.5 : 1)
const spread = (input.down ? 0.03 : 0.05)
let angle = m.angle - (number - 1) * spread * 0.5
for (let i = 0; i < number; i++) {
@@ -5624,27 +5652,7 @@ const b = {
angle += spread
}
} else {
const side = 22
for (let i = 0; i < 17; i++) {
const me = bullet.length;
const dir = m.angle + (Math.random() - 0.5) * spread
bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle) + 15 * (Math.random() - 0.5), m.pos.y + 35 * Math.sin(m.angle) + 15 * (Math.random() - 0.5), side, side, b.fireAttributes(dir));
Composite.add(engine.world, bullet[me]); //add bullet to world
const SPEED = 52 + Math.random() * 8
Matter.Body.setVelocity(bullet[me], {
x: SPEED * Math.cos(dir),
y: SPEED * Math.sin(dir)
});
bullet[me].endCycle = simulation.cycle + 40 * tech.isBulletsLastLonger
bullet[me].minDmgSpeed = 15
if (tech.isShotgunReversed) Matter.Body.setDensity(bullet[me], 0.0016)
// bullet[me].restitution = 0.4
bullet[me].frictionAir = 0.034;
bullet[me].do = function() {
const scale = 1 - 0.034 / tech.isBulletsLastLonger
Matter.Body.scale(this, scale, scale);
};
}
spray(16); //fires normal shotgun bullets
}
}
}, {

View File

@@ -208,7 +208,6 @@ function collisionChecks(event) {
const v = Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity));
if (v > 9) {
if (tech.blockDmg) { //electricity
// 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

View File

@@ -431,7 +431,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
//update tech text //disable not allowed tech
for (let i = 0, len = tech.tech.length; i < len; i++) {
const techID = document.getElementById("tech-" + i)
if (!tech.tech[i].isExperimentHide && !tech.tech[i].isNonRefundable && (!tech.tech[i].isJunk || tech.tech[i].isExperimentalMode || localSettings.isJunkExperiment)) {
if (!tech.tech[i].isExperimentHide && !tech.tech[i].isNonRefundable && (!tech.tech[i].isJunk || localSettings.isJunkExperiment)) {
if (tech.tech[i].allowed() || isAllowed || tech.tech[i].count > 0) {
const techCountText = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
// <div class="circle-grid-small research" style="position:absolute; top:13px; left:30px;opacity:0.85;"></div>
@@ -460,8 +460,6 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
</div>`
} else if (tech.tech[i].isJunk) {
techID.innerHTML = `<div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
} else if (tech.tech[i].isExperimentalMode) {
techID.innerHTML = `<div class="grid-title">${tech.tech[i].name}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
} else {
techID.innerHTML = `<div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
}
@@ -531,11 +529,9 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
text += `<div id = "gun-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'gun')"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[i].name)}</div> ${b.guns[i].description}</div>`
}
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (!tech.tech[i].isExperimentHide && (!tech.tech[i].isJunk || localSettings.isJunkExperiment)) { //&& (!tech.tech[i].isNonRefundable || tech.tech[i].isExperimentalMode)) {
if (tech.tech[i].allowed() && (!tech.tech[i].isNonRefundable || tech.tech[i].isExperimentalMode || localSettings.isJunkExperiment)) { // || tech.tech[i].name === "+1 cardinality") { //|| tech.tech[i].name === "leveraged investment"
if (tech.tech[i].isExperimentalMode) {
text += `<div id="tech-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'tech')"><div class="grid-title">${tech.tech[i].name}</div> ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
} else if (tech.tech[i].isJunk) {
if (!tech.tech[i].isExperimentHide && (!tech.tech[i].isJunk || localSettings.isJunkExperiment)) { //&& (!tech.tech[i].isNonRefundable)) {
if (tech.tech[i].allowed() && (!tech.tech[i].isNonRefundable || localSettings.isJunkExperiment)) { // || tech.tech[i].name === "+1 cardinality") { //|| tech.tech[i].name === "leveraged investment"
if (tech.tech[i].isJunk) {
text += `<div id="tech-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'tech')"><div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[i].link}</div> ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
} else {
text += `<div id="tech-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'tech')"><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[i].link}</div> ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
@@ -668,13 +664,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
build.hasExperimentalMode = false
if (!simulation.isCheating) {
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].count > 0) {
if (tech.tech[i].isExperimentalMode) {
build.hasExperimentalMode = true
} else if (!tech.tech[i].isLore) {
simulation.isCheating = true;
}
}
if (tech.tech[i].count > 0 && !tech.tech[i].isLore) simulation.isCheating = true;
}
if (b.inventory.length !== 0 || m.fieldMode !== 0) simulation.isCheating = true;
}

View File

@@ -16,7 +16,7 @@ const level = {
start() {
if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(3 * 4) //30 is near max on hard //60 is near max on why
// level.difficultyIncrease(10 * 4) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true
// m.maxHealth = m.health = 100
// tech.isRerollDamage = true
@@ -24,9 +24,11 @@ const level = {
// m.immuneCycle = Infinity //you can't take damage
// tech.tech[297].frequency = 100
// m.setField("metamaterial cloaking") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass
// b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 matter wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("shotgun") //0 nail gun 1 shotgun 2 super balls 3 matter wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.guns[0].ammo = 1000000
// tech.giveTech("1st ionization energy")
// tech.giveTech("rivet gun")
// tech.isFoamShot = true
// tech.isIncendiary = true
// for (let i = 0; i < 1; ++i) tech.giveTech("field coupling")
// for (let i = 0; i < 1; ++i) tech.giveTech("free-electron laser")
// m.damage(0.1);
@@ -36,10 +38,10 @@ const level = {
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling");
// spawn.starter(1900, -500, 200)
// spawn.beetleBoss(1900, -400)
// spawn.shooter(1900, -500)
// for (let i = 0; i < 15; ++i) spawn.starter(1900 + 300 * Math.random(), -500 + 300 * Math.random())
// spawn.ghoster(2538, -1950)
// for (let i = 0; i < 15; ++i) spawn.shooter(1900 + 300 * Math.random(), -500 + 300 * Math.random())
// level.testing();
// spawn.blowSuckBoss(1900, -500)
// for (let i = 0; i < 7; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research");
// for (let i = 0; i < 4; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech");
@@ -114,7 +116,6 @@ const level = {
spawn.WIMP()
for (let j = 0, len = 5; j < len; j++) powerUps.spawn(level.exit.x + 100 * (Math.random() - 0.5), level.exit.y - 100 + 100 * (Math.random() - 0.5), "research", false)
}
for (let i = 0; i < tech.wimpExperiment; i++) spawn.WIMP()
// if (tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) {
if ((tech.isRelay || tech.isFlipFlop) && !tech.isFlipFlopOn) {
tech.isFlipFlopOn = true
@@ -2809,6 +2810,17 @@ const level = {
spawn.mapRect(5300, -275, 50, 175);
spawn.mapRect(5050, -100, 50, 150);
spawn.mapRect(4850, -275, 50, 175);
spawn.mapRect(-950, -3250, 850, 1750);
//roof
spawn.mapRect(-175, -2975, 300, 1425);
spawn.mapRect(75, -2650, 325, 1150);
spawn.mapRect(375, -2225, 250, 650);
spawn.mapRect(4075, -2125, 700, 800);
spawn.mapRect(4450, -2950, 675, 1550);
spawn.mapRect(4875, -3625, 725, 2225);
spawn.mapRect(5525, -4350, 1725, 2925);
spawn.mapRect(7200, -5125, 300, 3900);
//???
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
@@ -10926,9 +10938,6 @@ const level = {
simulation.fallHeight = -1000;
simulation.setZoom(1800);
templePlayer.startAnim = -1;
for (let i = 0; i < tech.wimpCount + tech.wimpExperiment; i++) {
addWIMP();
}
templePlayer.drawExit = false;
}
},

View File

@@ -899,7 +899,7 @@ const mobs = {
//accelerate towards the searchTarget
if (!this.seePlayer.recall) {
const newTarget = function(that) {
if (Math.random() < 0.0005) {
if (Math.random() < 0.0007) {
that.searchTarget = player.position; //chance to target player
} else {
//target random body
@@ -1246,18 +1246,6 @@ const mobs = {
}
}
}
if (tech.removeMaxHealthOnKill) {
const amount = 0.002
if (tech.isEnergyHealth) {
if (m.maxEnergy > amount) {
tech.healMaxEnergyBonus -= amount
m.setMaxEnergy();
}
} else if (m.maxHealth > amount) {
tech.extraMaxHealth -= amount //decrease max health
m.setMaxHealth();
}
}
if (tech.cloakDuplication && !this.isBoss) {
tech.cloakDuplication -= 0.02
powerUps.setDupChance(); //needed after adjusting duplication chance

View File

@@ -1571,24 +1571,24 @@ const m = {
case 0: //field emitter
return `gain the effects of <strong>all</strong> <strong class='color-f'>fields</strong>`
case 1: //standing wave
return `<span style = 'font-size:95%;'><strong>deflecting</strong> condenses +${Math.ceil(couple)} <strong class='color-s'>ice IX</strong></span>`
return `<span style = 'font-size:95%;'><strong>deflecting</strong> condenses +${couple.toFixed(1)} <strong class='color-s'>ice IX</strong></span>`
case 2: //perfect diamagnetism
return `<span style = 'font-size:95%;'><strong>deflecting</strong> condenses +${Math.ceil(couple)} <strong class='color-s'>ice IX</strong></span>`
return `<span style = 'font-size:95%;'><strong>deflecting</strong> condenses +${couple.toFixed(1)} <strong class='color-s'>ice IX</strong></span>`
// return `<span style = 'font-size:89%;'><strong>invulnerable</strong> <strong>+${2*couple}</strong> seconds post collision</span>`
case 3: //negative mass
return `<strong>+${((1-0.73 ** couple)*100).toFixed(1)}%</strong> <strong class='color-defense'>defense</strong>`
case 4: //assembler
return `generate <strong>${6*couple}</strong> <strong class='color-f'>energy</strong> per second`
return `generate <strong>${(6*couple).toFixed(0)}</strong> <strong class='color-f'>energy</strong> per second`
case 5: //plasma
return `<strong>+${15*couple}</strong> <strong class='color-d'>damage</strong>`
return `<strong>+${(15*couple).toFixed(0)}%</strong> <strong class='color-d'>damage</strong>`
case 6: //time dilation
return `<strong>+${25*couple}%</strong> longer <strong style='letter-spacing: 2px;'>stopped time</strong>` //<strong>movement</strong>, <strong>jumping</strong>, and
return `<strong>+${(25*couple).toFixed(0)}%</strong> longer <strong style='letter-spacing: 2px;'>stopped time</strong>` //<strong>movement</strong>, <strong>jumping</strong>, and
case 7: //cloaking
return `<strong>+${33*couple}%</strong> ambush <strong class='color-d'>damage</strong>`
return `<strong>+${(33*couple).toFixed(0)}%</strong> ambush <strong class='color-d'>damage</strong>`
case 8: //pilot wave
return `<strong>+${40*couple}%</strong> <strong class='color-block'>block</strong> collision <strong class='color-d'>damage</strong>`
return `<strong>+${(40*couple).toFixed(0)}%</strong> <strong class='color-block'>block</strong> collision <strong class='color-d'>damage</strong>`
case 9: //wormhole
return `<span style = 'font-size:89%;'>after eating <strong class='color-block'>blocks</strong> <strong>+${20*couple}</strong> <strong class='color-f'>energy</strong></span>`
return `<span style = 'font-size:89%;'>after eating <strong class='color-block'>blocks</strong> <strong>+${(20*couple).toFixed(0)}</strong> <strong class='color-f'>energy</strong></span>`
}
},
couplingChange() {

View File

@@ -333,7 +333,7 @@ const powerUps = {
},
endDraft(type, isCanceled = false) { //type should be a gun, tech, or field
if (isCanceled) {
if (tech.isCancelTech && Math.random() < 0.9) {
if (tech.isCancelTech && Math.random() < 0.88) {
// powerUps.research.use('tech')
powerUps[type].effect();
return
@@ -414,8 +414,8 @@ const powerUps = {
return 11;
},
endCycle: 0,
duration: 600,
damage: 1.5,
duration: null, //set by "tech: band gap"
damage: null, //set by "tech: band gap"
effect() {
powerUps.boost.endCycle = m.cycle + Math.floor(Math.max(0, powerUps.boost.endCycle - m.cycle) * 0.6) + powerUps.boost.duration //duration+seconds plus 2/3 of current time left
},
@@ -912,7 +912,7 @@ const powerUps = {
}
function removeOption(index) {
for (let i = options.length; i > -1; i--) {
for (let i = options.length - 1; i > -1; i--) {
if (index === options[i]) {
options.splice(i, 1) //remove all copies of that option form the options array (some tech are in the options array multiple times because of frequency)
optionLengthNoDuplicates--
@@ -1272,9 +1272,11 @@ const powerUps = {
}
if (tech.isCouplingPowerUps && Math.random() < 0.17) {
powerUps.spawn(x, y, "coupling");
return;
}
if (tech.isBoostPowerUps && Math.random() < 0.17) {
if (tech.isBoostPowerUps && Math.random() < 0.18) {
powerUps.spawn(x, y, "boost");
return;
}
// if (Math.random() < 0.01) {
// powerUps.spawn(x, y, "research");

View File

@@ -1458,21 +1458,22 @@ const simulation = {
const y = round(simulation.constructMouseDownPosition.y)
const dx = Math.max(25, round(simulation.mouseInGame.x) - x)
const dy = Math.max(25, round(simulation.mouseInGame.y) - y)
if (e.button === 2) {
console.log(e.button)
if (e.button === 1) {
if (level.isProcedural) {
simulation.outputMapString(`spawn.randomMob(x+${x}, y+${y}, 0);`);
simulation.outputMapString(`spawn.randomMob(x+${x}, y+${y}, 0);\n`);
} else {
simulation.outputMapString(`spawn.randomMob(${x}, ${y}, 0);`);
simulation.outputMapString(`spawn.randomMob(${x}, ${y}, 0);\n`);
}
} else if (e.button === 4) {
simulation.outputMapString(`${Math.floor(simulation.constructMouseDownPosition.x)}, ${Math.floor(simulation.constructMouseDownPosition.y)}`);
} else if (simulation.mouseInGame.x > simulation.constructMouseDownPosition.x && simulation.mouseInGame.y > simulation.constructMouseDownPosition.y) { //make sure that the width and height are positive
if (e.button === 1) { //add map
if (e.button === 0) { //add map
if (level.isProcedural) {
simulation.outputMapString(`spawn.mapRect(x+${x}, y+${y}, ${dx}, ${dy});`);
simulation.outputMapString(`spawn.mapRect(x+${x}, y+${y}, ${dx}, ${dy});\n`);
} else {
simulation.outputMapString(`spawn.mapRect(${x}, ${y}, ${dx}, ${dy});`);
simulation.outputMapString(`spawn.mapRect(${x}, ${y}, ${dx}, ${dy});\n`);
}
//see map in world
@@ -1484,11 +1485,11 @@ const simulation = {
Composite.add(engine.world, map[len]); //add to world
simulation.draw.setPaths() //update map graphics
} else if (e.button === 3) { //add body
} else if (e.button === 2) { //add body
if (level.isProcedural) {
simulation.outputMapString(`spawn.bodyRect(x+${x}, y+${y}, ${dx}, ${dy});`);
simulation.outputMapString(`spawn.bodyRect(x+${x}, y+${y}, ${dx}, ${dy});\n`);
} else {
simulation.outputMapString(`spawn.bodyRect(${x}, ${y}, ${dx}, ${dy});`);
simulation.outputMapString(`spawn.bodyRect(${x}, ${y}, ${dx}, ${dy});\n`);
}
//see map in world
@@ -1513,6 +1514,7 @@ const simulation = {
}
});
//undo last element added after you press z
document.body.addEventListener("keydown", (e) => { // e.keyCode z=90 m=77 b=66 shift = 16 c = 67
if (simulation.testing && e.keyCode === 90 && simulation.constructMapString.length) {
if (simulation.constructMapString[simulation.constructMapString.length - 1][6] === 'm') { //remove map from current level

View File

@@ -5,8 +5,8 @@ const spawn = {
randomBossList: [
"orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
"powerUpBoss", "powerUpBossBaby", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss",
"snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss", "shieldingBoss", "timeSkipBoss",
"dragonFlyBoss", "beetleBoss"
"snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss", "shieldingBoss",
"timeSkipBoss", "dragonFlyBoss", "beetleBoss"
],
bossTypeSpawnOrder: [], //preset list of boss names calculated at the start of a run by the randomSeed
bossTypeSpawnIndex: 0, //increases as the boss type cycles
@@ -142,7 +142,7 @@ const spawn = {
const pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x, y);
}
if (tech.isMoreMobs || (tech.isDuplicateBoss && Math.random() < tech.duplicationChance())) {
if (tech.isDuplicateBoss && Math.random() < tech.duplicationChance()) {
const pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x, y);
}
@@ -158,7 +158,7 @@ const spawn = {
spawn[pick](x + Math.round((Math.random() - 0.5) * 20) + i * size * 2.5, y + Math.round((Math.random() - 0.5) * 20), size);
}
}
if (tech.isMoreMobs || (tech.isDuplicateBoss && Math.random() < tech.duplicationChance())) {
if (tech.isDuplicateBoss && Math.random() < tech.duplicationChance()) {
for (let i = 0; i < num; ++i) {
const pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x + Math.round((Math.random() - 0.5) * 20) + i * size * 2.5, y + Math.round((Math.random() - 0.5) * 20), size);
@@ -296,7 +296,7 @@ const spawn = {
me.showHealthBar = false;
me.collisionFilter.category = 0;
me.collisionFilter.mask = 0; //cat.player //| cat.body
me.chaseSpeed = 1 + 2 * Math.random()
me.chaseSpeed = 1.2 + 2 * Math.random()
me.awake = function() {
//chase player
@@ -4104,8 +4104,8 @@ const spawn = {
if (this.phaseCycle > -1) {
Matter.Body.rotate(this, 0.02)
for (let i = 0, len = this.vertices.length; i < len; i++) { //fire a bullet from each vertex
spawn.sniperBullet(this.vertices[i].x, this.vertices[i].y, 6, 4);
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[i])), -17)
spawn.sniperBullet(this.vertices[i].x, this.vertices[i].y, 5, 4);
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[i])), -15)
Matter.Body.setVelocity(mob[mob.length - 1], {
x: velocity.x,
y: velocity.y
@@ -5013,13 +5013,13 @@ const spawn = {
}, 2000); //add in a delay in case the level gets flipped left right
me.isBoss = true;
Matter.Body.setDensity(me, 0.01 + 0.0003 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
Matter.Body.setDensity(me, 0.01 + 0.0004 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
me.isVerticesChange = true
me.memory = 240;
me.fireFreq = 0.025;
me.fireFreq = 0.009 + 0.0004 * Math.min(40, simulation.difficulty); //bigger number means more shots per second
me.noseLength = 0;
me.fireAngle = 0;
me.accelMag = 0.005 * simulation.accelScale;
@@ -5066,16 +5066,14 @@ const spawn = {
//fire
for (let i = 0, len = 2 + 0.07 * simulation.difficulty; i < len; i++) {
spawn.bullet(this.vertices[1].x, this.vertices[1].y, 7 + Math.ceil(this.radius / 25));
const v = 15;
Matter.Body.setVelocity(mob[mob.length - 1], {
x: this.velocity.x + this.fireDir.x * v + 7 * Math.random(),
y: this.velocity.y + this.fireDir.y * v + 7 * Math.random()
});
const spread = Vector.rotate({
x: Math.sqrt(len) + 4,
y: 0
}, 2 * Math.PI * Math.random())
const dir = Vector.add(Vector.mult(this.fireDir, 15), spread)
Matter.Body.setVelocity(mob[mob.length - 1], dir);
}
this.noseLength = 0;
// recoil
this.force.x -= 0.005 * this.fireDir.x * this.mass;
this.force.y -= 0.005 * this.fireDir.y * this.mass;
}
if (this.noseLength < 1.5) this.noseLength += this.fireFreq;
setNoseShape();
@@ -5421,6 +5419,163 @@ const spawn = {
}
};
},
// blowSuckBoss(x, y, radius = 80) {
// mobs.spawn(x, y, 10, radius, "transparent");
// let me = mob[mob.length - 1];
// me.isBoss = true;
// Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
// me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
// me.fireFreq = Math.floor(60 * simulation.CDScale)
// me.seePlayerFreq = 15
// me.seeAtDistance2 = 300000;
// me.accelMag = 0.0003 * simulation.accelScale;
// if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search
// // Matter.Body.setDensity(me, 0.001); //normal is 0.001 //makes effective life much lower
// me.stroke = "transparent"; //used for drawGhost
// me.alpha = 1; //used in drawGhost
// me.canTouchPlayer = false; //used in drawGhost
// me.isBadTarget = true;
// // me.leaveBody = false;
// me.collisionFilter.mask = cat.bullet //| cat.body
// me.showHealthBar = false;
// me.memory = 480;
// me.onDeath = function() {
// powerUps.spawnBossPowerUp(this.position.x, this.position.y)
// };
// me.onDamage = function() {};
// me.suck = function() {
// for (let i = 0; i < mob.length; i++) {
// if (mob[i].isBlowSuckBullet) {
// const unit = Vector.normalise(Vector.sub(this.position, mob[i].position))
// const mag = Vector.mult(unit, 0.0008 * mob[i].mass)
// mob[i].force.x += mag.x
// mob[i].force.y += mag.y
// }
// }
// }
// me.do = function() {
// //cap max speed
// if (this.speed > 8) {
// Matter.Body.setVelocity(this, {
// x: this.velocity.x * 0.8,
// y: this.velocity.y * 0.8
// });
// }
// this.seePlayerCheckByDistance();
// this.checkStatus();
// this.attraction();
// this.search();
// //draw
// if (this.distanceToPlayer2() < this.seeAtDistance2) {
// if (this.alpha < 1) this.alpha += 0.005 * simulation.CDScale; //near player go solid
// } else {
// if (this.alpha > 0) this.alpha -= 0.05; ///away from player, hide
// }
// if (this.alpha > 0) {
// if (this.alpha > 0.8 && this.seePlayer.recall) {
// this.healthBar();
// if (!this.canTouchPlayer) {
// this.canTouchPlayer = true;
// this.isBadTarget = false;
// this.collisionFilter.mask = cat.player | cat.bullet
// }
// }
// //draw body
// ctx.beginPath();
// const vertices = this.vertices;
// ctx.moveTo(vertices[0].x, vertices[0].y);
// for (let j = 1, len = vertices.length; j < len; ++j) {
// ctx.lineTo(vertices[j].x, vertices[j].y);
// }
// ctx.lineTo(vertices[0].x, vertices[0].y);
// ctx.lineWidth = 1;
// ctx.fillStyle = `rgba(255,255,255,${this.alpha * this.alpha})`;
// ctx.fill();
// this.suck();
// if (this.seePlayer.recall && !(simulation.cycle % this.fireFreq)) {
// this.suckCount = 0;
// Matter.Body.setAngularVelocity(this, 0.11)
// //fire a bullet from each vertex
// for (let i = 0, len = this.vertices.length; i < len; i++) {
// spawn.bounceBullet(this.vertices[i].x, this.vertices[i].y, 8)
// //give the bullet a rotational velocity as if they were attached to a vertex
// const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[i]))), -16)
// const who = mob[mob.length - 1]
// who.isBlowSuckBullet = true
// Matter.Body.setVelocity(who, {
// x: this.velocity.x + velocity.x,
// y: this.velocity.y + velocity.y
// });
// }
// }
// } else if (this.canTouchPlayer) {
// this.canTouchPlayer = false;
// this.isBadTarget = true;
// this.collisionFilter.mask = cat.bullet; //can't touch player or walls
// }
// };
// },
// blowSuckBoss(x, y, radius = 80, isSpawnBossPowerUp = true) {
// mobs.spawn(x, y, 10, radius, "transparent"); //rgb(60,60,85)
// let me = mob[mob.length - 1];
// me.isBoss = true;
// Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
// me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
// me.accelMag = 0.0001 * simulation.accelScale;
// me.fireFreq = Math.floor(180 * simulation.CDScale)
// me.frictionStatic = 0;
// me.friction = 0;
// me.frictionAir = 0.005;
// me.memory = 420;
// me.repulsionRange = 1000000; //squared
// // spawn.shield(me, x, y, 1);
// // spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random())
// me.onDeath = function() {
// if (isSpawnBossPowerUp) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
// };
// me.onDamage = function() {};
// me.suck = function() {
// for (let i = 0; i < mob.length; i++) {
// if (mob[i].isBlowSuckBullet) {
// const unit = Vector.normalise(Vector.sub(this.position, mob[i].position))
// const mag = Vector.mult(unit, 0.0008 * mob[i].mass)
// mob[i].force.x += mag.x
// mob[i].force.y += mag.y
// }
// }
// }
// me.do = function() {
// this.seePlayerCheck();
// this.checkStatus();
// this.attraction();
// // this.repulsion();
// this.suck();
// if (this.seePlayer.recall && !(simulation.cycle % this.fireFreq)) {
// this.suckCount = 0;
// Matter.Body.setAngularVelocity(this, 0.11)
// //fire a bullet from each vertex
// for (let i = 0, len = this.vertices.length; i < len; i++) {
// spawn.bounceBullet(this.vertices[i].x, this.vertices[i].y, 8)
// //give the bullet a rotational velocity as if they were attached to a vertex
// const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[i]))), -16)
// const who = mob[mob.length - 1]
// who.isBlowSuckBullet = true
// Matter.Body.setVelocity(who, {
// x: this.velocity.x + velocity.x,
// y: this.velocity.y + velocity.y
// });
// }
// }
// };
// },
grenadierBoss(x, y, radius = 95) {
mobs.spawn(x, y, 6, radius, "rgb(0,235,255)");
let me = mob[mob.length - 1];
@@ -6192,7 +6347,7 @@ const spawn = {
mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)");
let me = mob[mob.length - 1];
me.collisionFilter.mask = cat.bullet | cat.player //| cat.mob //| cat.body
me.damageReduction = 0.021
me.damageReduction = 0.024
Matter.Body.setDensity(me, 0.0001); //normal is 0.001
// me.accelMag = 0.0007 * simulation.accelScale;

View File

@@ -2227,7 +2227,7 @@ const tech = {
name: "1st ionization energy",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Ionization_energy' class="link">1st ionization energy</a>`,
description: `after you collect ${powerUps.orb.heal()}<br><strong>+10</strong> maximum <strong class='color-f'>energy</strong>`,
description: `convert ${powerUps.orb.heal()} into <div class="heal-circle" style = "background-color: #ff0; border: 0.5px #000 solid;"></div><br><div class="heal-circle" style = "background-color: #ff0; border: 0.5px #000 solid;"></div> give <strong>+10</strong> maximum <strong class='color-f'>energy</strong>`,
description: `convert current and future ${powerUps.orb.heal()} into <div class="heal-circle" style = "background-color: #ff0; border: 0.5px #000 solid;"></div><br><div class="heal-circle" style = "background-color: #ff0; border: 0.5px #000 solid;"></div> give <strong>+10</strong> maximum <strong class='color-f'>energy</strong>`,
maxCount: 1,
count: 0,
frequency: 2,
@@ -3240,7 +3240,8 @@ const tech = {
},
{
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`,
description: `use ${powerUps.orb.research(4)} (or <strong>49%</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool if you can't) to add a 2nd <strong>boss</strong> to each level`,
description: `<span style = 'font-size:94%;'>as a level begins spawn a 2nd <strong>boss</strong> using ${powerUps.orb.research(4)}<br>(<strong>+49%</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool if you can't pay)</span>`,
maxCount: 1,
count: 0,
frequency: 2,
@@ -3297,7 +3298,7 @@ const tech = {
{
name: "exciton",
descriptionFunction() {
return `<span style = 'font-size:94%;'>after mobs <strong>die</strong> they have a <strong>17%</strong> chance to<br>spawn ${powerUps.orb.boost(1)} that give <strong>+${powerUps.boost.damage*100}%</strong> <strong class='color-d'>damage</strong> for <strong>${(powerUps.boost.duration/60).toFixed(0)}</strong> seconds</span>`
return `<span style = 'font-size:94%;'>after mobs <strong>die</strong> they have a <strong>18%</strong> chance to<br>spawn ${powerUps.orb.boost(1)} that give <strong>+${(powerUps.boost.damage*100).toFixed(0)}%</strong> <strong class='color-d'>damage</strong> for <strong>${(powerUps.boost.duration/60).toFixed(0)}</strong> seconds</span>`
},
maxCount: 1,
count: 0,
@@ -3314,6 +3315,29 @@ const tech = {
tech.isBoostPowerUps = false
}
},
{
name: "band gap",
descriptionFunction() {
return `${powerUps.orb.boost(1)} give <strong>+77%</strong> <strong class='color-d'>damage</strong><br>but their duration is reduced by <strong>1</strong> second`
},
maxCount: 9,
count: 1,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.isBoostPowerUps || tech.isBoostReplaceAmmo
},
requires: "exciton, quasiparticles",
effect() {
powerUps.boost.duration -= 60
powerUps.boost.damage += 0.77
},
remove() {
powerUps.boost.duration = 600
powerUps.boost.damage = 1.25
}
},
{
name: "eternalism",
description: "<strong>+34%</strong> <strong class='color-d'>damage</strong><br><strong>time</strong> can't be <strong>paused</strong> <em>(time can be dilated)</em>",
@@ -3463,7 +3487,7 @@ const tech = {
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
frequencyDefault: 100,
allowed() {
return true
},
@@ -3474,11 +3498,14 @@ const tech = {
simulation.makeTextLog(`m.coupling <span class='color-symbol'>+=</span> ${(this.value).toFixed(1)}`);
m.coupling += this.value
m.couplingChange()
this.maxCount = 0
},
remove() {
if (this.count) {
m.coupling -= this.value
m.couplingChange()
} else {
this.maxCount = 1
}
tech.isCouplingNoHit = false
}
@@ -3506,7 +3533,7 @@ const tech = {
{
name: "options exchange",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Option_(finance)' class="link">options exchange</a>`,
description: `clicking <strong style = 'font-size:150%;'>×</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong> has a <strong>90%</strong><br>chance to randomize <strong>choices</strong> and not <strong>cancel</strong>`,
description: `clicking <strong style = 'font-size:150%;'>×</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong> has a <strong>88%</strong><br>chance to randomize <strong>choices</strong> and not <strong>cancel</strong>`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -3542,7 +3569,7 @@ const tech = {
},
{
name: "futures exchange",
description: "clicking <strong style = 'font-size:150%;'>×</strong> to <strong>cancel</strong> a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br><strong>+4.5%</strong> power up <strong class='color-dup'>duplication</strong> chance",
description: "clicking <strong style = 'font-size:150%;'>×</strong> to <strong>cancel</strong> a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>gives <strong>+4.5%</strong> power up <strong class='color-dup'>duplication</strong> chance",
maxCount: 1,
count: 0,
frequency: 1,
@@ -4034,7 +4061,7 @@ const tech = {
frequencyDefault: 2,
allowed() {
// return (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("mines"))
return tech.isMineDrop || tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !(tech.isLaserMine || tech.isFoamMine)) || (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot))
return tech.isMineDrop || tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !(tech.isLaserMine || tech.isFoamMine)) || (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot) && !tech.isRivets && !tech.isNeedles)
},
//
requires: "nail gun, not rotary cannon, rivets, or needles",
@@ -4298,7 +4325,7 @@ const tech = {
{
name: "Noether violation",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Noether%27s_theorem' class="link">Noether violation</a>`,
description: "<strong>+60%</strong> <strong>shotgun</strong> <strong class='color-d'>damage</strong><br><strong>shotgun</strong> <strong>recoil</strong> is <strong>reversed</strong>",
description: "<strong>+50%</strong> <strong>shotgun</strong> <strong class='color-d'>damage</strong><br><strong>shotgun</strong> <strong>recoil</strong> is <strong>reversed</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -4318,7 +4345,7 @@ const tech = {
{
name: "nail-shot",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Nail_(fastener)' class="link">nail-shot</a>`,
description: "<strong>shotgun</strong> fires <strong>17</strong> <strong>nails</strong>",
description: "<strong>shotgun</strong> drives a long clip of <strong>nails</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -4338,7 +4365,7 @@ const tech = {
{
name: "foam-shot",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Foam' class="link">foam-shot</a>`,
description: "<strong>shotgun</strong> sprays <strong>15</strong> sticky <strong>foam</strong> bubbles",
description: "<strong>shotgun</strong> sprays sticky <strong>foam</strong> bubbles",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -4358,7 +4385,7 @@ const tech = {
{
name: "ice-shot",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Ice-nine_(disambiguation)' class="link">ice-shot</a>`,
description: "<strong>shotgun</strong> grows <strong>15</strong> freezing <strong class='color-s'>ice IX</strong> crystals",
description: "<strong>shotgun</strong> grows freezing <strong class='color-s'>ice IX</strong> crystals",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -4756,7 +4783,7 @@ const tech = {
},
{
name: "cruise missile",
description: "<strong>+100%</strong> <strong>missile</strong> <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong>, radius<br><strong>50%</strong> <strong>missiles</strong> speed",
description: "<strong>+100%</strong> <strong>missile</strong> <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong>, radius<br><strong>50%</strong> <strong>missile</strong> speed",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -4765,7 +4792,7 @@ const tech = {
allowed() {
return (tech.haveGunCheck("missiles") && tech.missileFireCD === 45) || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && simulation.molecularMode === 1) || tech.missileBotCount
},
requires: "missiles",
requires: "missiles, not launch system",
effect() {
tech.isMissileBig = true
},
@@ -4775,7 +4802,7 @@ const tech = {
},
{
name: "ICBM",
description: "<strong>+100%</strong> <strong>missile</strong> <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong>, radius<br><strong>66%</strong> <strong>missiles</strong> speed",
description: "<strong>+75%</strong> <strong>missile</strong> <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong>, radius<br><strong>50%</strong> <strong>missile</strong> speed",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -4803,7 +4830,7 @@ const tech = {
allowed() {
return tech.haveGunCheck("missiles") && !tech.isMissileBig
},
requires: "missiles",
requires: "missiles, not cruise missile",
ammoBonus: 1.2,
effect() {
tech.missileFireCD = 10
@@ -4976,7 +5003,7 @@ const tech = {
}
},
{
name: "controlled explosion",
name: "shaped charge",
description: `use ${powerUps.orb.research(4)} to dynamically <strong>reduce</strong><br>all <strong class='color-e'>explosions</strong> to prevent <strong class='color-h'>health</strong> loss`,
isGunTech: true,
maxCount: 1,
@@ -5959,9 +5986,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.isHarpoonPowerUp && !tech.isGrapple
return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.isHarpoonPowerUp && !tech.isGrapple && !tech.isBoostReplaceAmmo
},
requires: "harpoon, not UHMWPE, induction furnace, grappling hook",
requires: "harpoon, not UHMWPE, induction furnace, grappling hook, quasiparticles",
ammoBonus: 9,
effect() {
tech.isRailGun = true;
@@ -6179,6 +6206,35 @@ const tech = {
tech.harpoonDensity = 0.004
}
},
{
name: "quasiparticles",
descriptionFunction() {
return `convert current and future ${powerUps.orb.ammo(1)} into ${powerUps.orb.boost(1)} which<br>give <strong>+${(powerUps.boost.damage*100).toFixed(0)}%</strong> <strong class='color-d'>damage</strong> for <strong>${(powerUps.boost.duration/60).toFixed(0)}</strong> seconds`
},
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("laser") || (tech.haveGunCheck("harpoon") && !tech.isRailGun)
},
requires: "harpoon, laser, not railgun",
effect() {
tech.isBoostReplaceAmmo = true
for (let i = powerUp.length - 1; i > -1; i--) {
if (powerUp[i].name === "ammo") {
powerUps.spawn(powerUp[i].position.x + 50 * (Math.random() - 0.5), powerUp[i].position.y + 50 * (Math.random() - 0.5), "boost");
Matter.Composite.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1);
}
}
},
remove() {
tech.isBoostReplaceAmmo = false
}
},
{
name: "optical amplifier",
description: "gain <strong>3</strong> random <strong class='color-laser'>laser</strong> <strong class='color-g'>gun</strong><strong class='color-m'>tech</strong><br><strong class='color-laser'>laser</strong> only turns <strong>off</strong> if you have no <strong class='color-f'>energy</strong>",
@@ -6195,7 +6251,7 @@ const tech = {
effect() {
let techGiven = 0
for (let j = 0; j < 3; j++) {
const names = ["lens", "compound lens", "arc length", "infrared diode", "free-electron laser", "dye laser", "relativistic momentum", "specular reflection", "diffraction grating", "diffuse beam", "output coupler", "slow light", "laser-bot", "laser-bot upgrade"]
const names = ["quasiparticles", "lens", "compound lens", "arc length", "infrared diode", "free-electron laser", "dye laser", "relativistic momentum", "specular reflection", "diffraction grating", "diffuse beam", "output coupler", "slow light", "laser-bot", "laser-bot upgrade"]
//convert names into indexes
const options = []
for (let i = 0; i < names.length; i++) {
@@ -6241,27 +6297,6 @@ const tech = {
tech.isStuckOn = false
}
},
{
name: "quasiparticles",
descriptionFunction() {
return `replace all ${powerUps.orb.ammo(1)} spawns with ${powerUps.orb.boost(1)} which give<br><strong>+${powerUps.boost.damage*100}%</strong> <strong class='color-d'>damage</strong> for <strong>${(powerUps.boost.duration/60).toFixed(0)}</strong> seconds`
},
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("laser")
},
requires: "laser, not pulse",
effect() {
tech.isBoostReplaceAmmo = true
},
remove() {
tech.isBoostReplaceAmmo = false
}
},
{
name: "relativistic momentum",
description: "<strong class='color-laser'>lasers</strong> push <strong>mobs</strong> and <strong class='color-block'>blocks</strong>",
@@ -7812,207 +7847,153 @@ const tech = {
//************************************************** experimental
//************************************************** modes
//**************************************************
{
name: "-ship-",
description: "<strong style='color: #f55;'>experiment:</strong> fly around with no legs<br>aim with the keyboard",
maxCount: 1,
count: 0,
frequency: 0,
isNonRefundable: true,
isBadRandomOption: true,
isExperimentalMode: true,
allowed() {
return build.isExperimentSelection && !m.isShipMode && m.fieldUpgrades[m.fieldMode].name !== "negative mass"
},
requires: "",
effect() {
m.shipMode()
},
remove() {}
},
{
name: "-quantum leap-",
description: "<strong style='color: #f55;'>experiment:</strong> every 20 seconds<br>become an <strong class='alt'>alternate</strong> version of yourself",
maxCount: 1,
count: 0,
frequency: 0,
isBadRandomOption: true,
isExperimentalMode: true,
allowed() {
return build.isExperimentSelection
},
requires: "",
interval: undefined,
effect() {
this.interval = setInterval(() => {
if (!build.isExperimentSelection) {
m.switchWorlds()
simulation.trails()
}
}, 20000); //every 20 seconds
// {
// name: "-ship-",
// description: "<strong style='color: #f55;'>experiment:</strong> fly around with no legs<br>aim with the keyboard",
// maxCount: 1,
// count: 0,
// frequency: 0,
// isNonRefundable: true,
// isBadRandomOption: true,
// isExperimentalMode: true,
// allowed() {
// return build.isExperimentSelection && !m.isShipMode && m.fieldUpgrades[m.fieldMode].name !== "negative mass"
// },
// requires: "",
// effect() {
// m.shipMode()
// },
// remove() {}
// },
// {
// name: "-quantum leap-",
// description: "<strong style='color: #f55;'>experiment:</strong> every 20 seconds<br>become an <strong class='alt'>alternate</strong> version of yourself",
// maxCount: 1,
// count: 0,
// frequency: 0,
// isBadRandomOption: true,
// isExperimentalMode: true,
// allowed() {
// return build.isExperimentSelection
// },
// requires: "",
// interval: undefined,
// effect() {
// this.interval = setInterval(() => {
// if (!build.isExperimentSelection) {
// m.switchWorlds()
// simulation.trails()
// }
// }, 20000); //every 20 seconds
// },
// remove() {
// if (this.count > 0) clearTimeout(this.interval);
// }
// },
// {
// name: "-shields-",
// description: "<strong style='color: #f55;'>experiment:</strong> every 5 seconds<br>all mobs gain a shield",
// maxCount: 1,
// count: 0,
// frequency: 0,
// isBadRandomOption: true,
// isExperimentalMode: true,
// allowed() {
// return build.isExperimentSelection
// },
// requires: "",
// effect() {
// this.interval = setInterval(() => {
// if (!build.isExperimentSelection) {
// for (let i = 0; i < mob.length; i++) {
// if (!mob[i].isShielded && !mob[i].shield && mob[i].isDropPowerUp) spawn.shield(mob[i], mob[i].position.x, mob[i].position.y, 1, true);
// }
// }
// }, 5000); //every 5 seconds
// },
// interval: undefined,
// remove() {
// if (this.count > 0) clearTimeout(this.interval);
// }
// },
// {
// name: "-Fourier analysis-",
// description: "<strong style='color: #f55;'>experiment:</strong> your aiming is random",
// maxCount: 1,
// count: 0,
// frequency: 0,
// isBadRandomOption: true,
// isExperimentalMode: true,
// allowed() {
// return build.isExperimentSelection && !m.isShipMode
// },
// requires: "not ship",
// effect() {
// m.look = () => {
// m.angle = 2 * Math.sin(m.cycle * 0.0133) + Math.sin(m.cycle * 0.013) + 0.5 * Math.sin(m.cycle * 0.031) + 0.33 * Math.sin(m.cycle * 0.03)
// const scale = 0.8;
// m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale;
// m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale;
// m.transX += (m.transSmoothX - m.transX) * 0.07;
// m.transY += (m.transSmoothY - m.transY) * 0.07;
// }
// },
// remove() {
// if (this.count > 0) m.look = m.lookDefault()
// }
// },
// {
// name: "-panopticon-",
// description: "<strong style='color: #f55;'>experiment:</strong> mobs can always see you",
// maxCount: 1,
// count: 0,
// frequency: 0,
// isBadRandomOption: true,
// isExperimentalMode: true,
// allowed() {
// return build.isExperimentSelection
// },
// requires: "",
// effect() {
// this.interval = setInterval(() => {
// if (!build.isExperimentSelection) {
// for (let i = 0; i < mob.length; i++) {
// if (!mob[i].shield && mob[i].isDropPowerUp) {
// mob[i].locatePlayer()
// mob[i].seePlayer.yes = true;
// }
// }
// }
// }, 1000); //every 1 seconds
// },
// interval: undefined,
// remove() {
// if (this.count > 0) clearTimeout(this.interval);
// }
// },
// {
// name: "-decomposers-",
// description: "<strong style='color: #f55;'>experiment:</strong> after they die<br>mobs leave behind spawns",
// maxCount: 1,
// count: 0,
// frequency: 0,
// isBadRandomOption: true,
// isExperimentalMode: true,
// allowed() {
// return build.isExperimentSelection
// },
// requires: "",
// effect() {
// tech.deathSpawns = 0.2
// },
// remove() {
// tech.deathSpawns = 0
// }
// },
},
remove() {
if (this.count > 0) clearTimeout(this.interval);
}
},
{
name: "-shields-",
description: "<strong style='color: #f55;'>experiment:</strong> every 5 seconds<br>all mobs gain a shield",
maxCount: 1,
count: 0,
frequency: 0,
isBadRandomOption: true,
isExperimentalMode: true,
allowed() {
return build.isExperimentSelection
},
requires: "",
effect() {
this.interval = setInterval(() => {
if (!build.isExperimentSelection) {
for (let i = 0; i < mob.length; i++) {
if (!mob[i].isShielded && !mob[i].shield && mob[i].isDropPowerUp) spawn.shield(mob[i], mob[i].position.x, mob[i].position.y, 1, true);
}
}
}, 5000); //every 5 seconds
},
interval: undefined,
remove() {
if (this.count > 0) clearTimeout(this.interval);
}
},
{
name: "-Fourier analysis-",
description: "<strong style='color: #f55;'>experiment:</strong> your aiming is random",
maxCount: 1,
count: 0,
frequency: 0,
isBadRandomOption: true,
isExperimentalMode: true,
allowed() {
return build.isExperimentSelection && !m.isShipMode
},
requires: "not ship",
effect() {
m.look = () => {
m.angle = 2 * Math.sin(m.cycle * 0.0133) + Math.sin(m.cycle * 0.013) + 0.5 * Math.sin(m.cycle * 0.031) + 0.33 * Math.sin(m.cycle * 0.03)
const scale = 0.8;
m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale;
m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale;
m.transX += (m.transSmoothX - m.transX) * 0.07;
m.transY += (m.transSmoothY - m.transY) * 0.07;
}
},
remove() {
if (this.count > 0) m.look = m.lookDefault()
}
},
{
name: "-panopticon-",
description: "<strong style='color: #f55;'>experiment:</strong> mobs can always see you",
maxCount: 1,
count: 0,
frequency: 0,
isBadRandomOption: true,
isExperimentalMode: true,
allowed() {
return build.isExperimentSelection
},
requires: "",
effect() {
this.interval = setInterval(() => {
if (!build.isExperimentSelection) {
for (let i = 0; i < mob.length; i++) {
if (!mob[i].shield && mob[i].isDropPowerUp) {
mob[i].locatePlayer()
mob[i].seePlayer.yes = true;
}
}
}
}, 1000); //every 1 seconds
},
interval: undefined,
remove() {
if (this.count > 0) clearTimeout(this.interval);
}
},
{
name: "-decomposers-",
description: "<strong style='color: #f55;'>experiment:</strong> after they die<br>mobs leave behind spawns",
maxCount: 1,
count: 0,
frequency: 0,
isBadRandomOption: true,
isExperimentalMode: true,
allowed() {
return build.isExperimentSelection
},
requires: "",
effect() {
tech.deathSpawns = 0.2
},
remove() {
tech.deathSpawns = 0
}
},
{
name: "-WIMP-",
description: "<strong style='color: #f55;'>experiment:</strong> <strong class='color-defense'>harmful</strong> particles slowly <strong>chase</strong> you",
maxCount: 1,
count: 0,
frequency: 0,
isBadRandomOption: true,
isExperimentalMode: true,
allowed() {
return build.isExperimentSelection
},
requires: "",
effect() {
tech.wimpExperiment = 5
},
remove() {
tech.wimpExperiment = 0
}
},
{
name: "-symbiosis-",
description: "<strong style='color: #f55;'>experiment:</strong> if you <strong>kill</strong> a <strong>mob</strong><br>lose <strong>0.2</strong> max <strong class='color-h'>health</strong>",
maxCount: 1,
count: 0,
frequency: 0,
isBadRandomOption: true,
isExperimentalMode: true,
allowed() {
return build.isExperimentSelection
},
requires: "",
effect() {
tech.removeMaxHealthOnKill = 0.002
},
remove() {
tech.removeMaxHealthOnKill = 0
}
},
{
name: "-parthenocarpy-",
description: "<strong style='color: #f55;'>experiment:</strong> spawn about 50% more mobs",
maxCount: 1,
count: 1,
frequency: 0,
isBadRandomOption: true,
isExperimentalMode: true,
allowed() {
return build.isExperimentSelection
},
requires: "",
effect() {
tech.isMoreMobs = true
},
remove() {
tech.isMoreMobs = false
}
},
//**************************************************
//************************************************** JUNK
//************************************************** tech
@@ -10629,12 +10610,10 @@ const tech = {
isHarpoonPowerUp: null,
harpoonDensity: null,
isAddRemoveMaxHealth: null,
removeMaxHealthOnKill: null,
isSpawnExitTech: null,
cloakDuplication: null,
extruderRange: null,
isForeverDrones: null,
isMoreMobs: null,
nailRecoil: null,
baseJumpForce: null,
baseFx: null,