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,

View File

@@ -1,21 +1,41 @@
******************************************************** NEXT PATCH **************************************************
tech: virtual particles - mobs have a chance to spawn coupling power ups
old tech virtual particles renamed vacuum fluctuation
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
tech: exciton - mobs have a chance to spawn a boost
boosts are a power up that increases your damage for 10 seconds
old tech exciton renamed non-renewables
laser tech: quasiparticles - replace all ammo with boosts
WIMPs are 10% faster
controlled explosion renamed shaped charge
added +20px to grid elements to prevent text spillover
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"
*********************************************************** TODO *****************************************************
complete blowSuckBoss... or don't
tech: laser reflections increase damage
JUNK tech different effects based on night or day
use system time
buffing your deflecting for 1 second after pressing the field button
2 second cooldown on the effect to prevent spamming it
buff: giving energy or doing damage makes sense
maybe this could be a rework for bremstralung
replace field descriptions with a function call so they can have dynamic text
add in dynamic coupling text as a 4th line
Boss that shoots out a ring of bullets, then after a few seconds it gravitates the bullets back
JUNK: Placebo: double the power up spawn rate but make half of them do nothing
coupling
pause menu +defense on coupling description goes above 100%
put coupling description as 4th line on field description
raw text no function call
no need for coupling description in power ups, pause
@@ -27,15 +47,8 @@ coupling tech
tech: coupling starts at 200%, but decays when the field is in use, coupling recharges when the field is not in use
some fields aren't used much (that's ok?)
tech: increase the effect of boosts, but shorten the duration?
tech give laser mines more lasers (3->4? 5?)
buffing your deflecting for 1 second after pressing the field button sounds cool
2 second cooldown on the effect to prevent spamming it
buff: giving energy or doing damage makes sense
maybe this could be a rework for bremstralung
rewindBoss: after hitting 1/5 damage thresholds the boss rewinds back in time to where it was a few seconds ago
track it's data like player history
@@ -913,6 +926,8 @@ possible names for tech
lenticular lens: is an array of lenses, designed so that when viewed from slightly different angles, different parts of the image underneath are shown.
p-zombie
p-hacking JUNK tech
https://en.wikipedia.org/wiki/High-entropy_alloys
https://en.wikipedia.org/wiki/Refractory_metals
plot script: