you're a firework

grenade tech: flame test - grenades release a cluster of smaller explosions
grenade tech: pyrotechnics - grenades release a circle of smaller explosions
grenade tech: implosion - explosions pull things in, not out,  +25% to grenade explosion damage and radius
chain reaction no longer requires vacuum bomb
bosses and mobs have much less knock back from explosions
  invulnerable mobs have no knock back

alternator harpoon/grapple/railgun energy drain reduced by 100->60%
bots no longer unlock tech until you upgrade to a bot type
JUNK tech rule 30 is now sometimes rule 90 instead
disabled testing for why? mode

wave beam
  amplitude 50->37% damage
  propagation 50->37% damage
worms
  annelids 10-120% -> about 37% damage
radiation
  nuclear transmutation stacks 9x
    gives 70->47% damage per stack
explosions
  ammonium nitrate 27->24% damage and radius
This commit is contained in:
landgreen
2022-05-17 15:35:49 -07:00
parent c65e163b6f
commit dd8fd925e0
11 changed files with 434 additions and 617 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -352,13 +352,11 @@ const b = {
explosion(where, radius, color = "rgba(255,25,0,0.6)") { // typically explode is used for some bullets with .onEnd
radius *= tech.explosiveRadius
// radius = Math.max(0, Math.min(radius, (distanceToPlayer - 70) / b.explosionRange()))
let dist, sub, knock;
let dmg = radius * 0.019 * (tech.isExplosionStun ? 0.7 : 1); //* 0.013 * (tech.isExplosionStun ? 0.7 : 1);
if (tech.isExplosionHarm) radius *= 1.8 // 1/sqrt(2) radius -> area
if (tech.isSmallExplosion) {
color = "rgba(255,0,30,0.7)"
// color = "rgba(255,0,30,0.7)"
radius *= 0.66
dmg *= 1.66
}
@@ -432,18 +430,18 @@ const b = {
m.energy -= 0.15
m.damage(0.01 * harm); //remove 99% of the damage 1-0.99
// console.log(Math.max(0, Math.min(0.15 - 0.01 * player.speed, 0.15)))
knock = Vector.mult(Vector.normalise(sub), -0.6 * player.mass * Math.max(0, Math.min(0.15 - 0.002 * player.speed, 0.15)));
knock = Vector.mult(Vector.normalise(sub), 0.6 * player.mass * Math.max(0, Math.min(0.15 - 0.002 * player.speed, 0.15)) * tech.implosion);
player.force.x = knock.x; // not += so crazy forces can't build up with MIRV
player.force.y = knock.y - 0.3; //some extra vertical kick
} else {
if (simulation.dmgScale) m.damage(harm);
knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass * 0.013);
knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg) * player.mass * 0.013 * tech.implosion);
player.force.x += knock.x;
player.force.y += knock.y;
}
}
} else if (dist < alertRange) {
knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass * 0.005);
knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg) * player.mass * 0.005 * tech.implosion);
player.force.x += knock.x;
player.force.y += knock.y;
}
@@ -455,7 +453,7 @@ const b = {
sub = Vector.sub(where, body[i].position);
dist = Vector.magnitude(sub);
if (dist < radius) {
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.022);
knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg) * body[i].mass * 0.022 * tech.implosion);
body[i].force.x += knock.x;
body[i].force.y += knock.y;
if (tech.isBlockExplode) {
@@ -470,7 +468,7 @@ const b = {
}, 150 + 300 * Math.random());
}
} else if (dist < alertRange) {
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.011);
knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg) * body[i].mass * 0.011 * tech.implosion);
body[i].force.x += knock.x;
body[i].force.y += knock.y;
}
@@ -482,11 +480,11 @@ const b = {
sub = Vector.sub(where, powerUp[i].position);
dist = Vector.magnitude(sub);
if (dist < radius) {
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * powerUp[i].mass) * 0.013);
knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg) * powerUp[i].mass * 0.013 * tech.implosion);
powerUp[i].force.x += knock.x;
powerUp[i].force.y += knock.y;
} else if (dist < alertRange) {
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * powerUp[i].mass) * 0.007);
knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg) * powerUp[i].mass * 0.007 * tech.implosion);
powerUp[i].force.x += knock.x;
powerUp[i].force.y += knock.y;
}
@@ -503,18 +501,28 @@ const b = {
if (Matter.Query.ray(map, mob[i].position, where).length > 0) dmg *= 0.5 //reduce damage if a wall is in the way
mob[i].damage(dmg * damageScale * m.dmgScale);
mob[i].locatePlayer();
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) * 0.01);
mob[i].force.x += knock.x;
mob[i].force.y += knock.y;
if (tech.isExplosionStun) mobs.statusStun(mob[i], 120)
if (tech.isExplosionStun) {
mobs.statusStun(mob[i], 120)
knock *= 0.1
}
knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg * damageScale) * mob[i].mass * (mob[i].isBoss ? 0.005 : 0.01) * tech.implosion);
if (!mob[i].isInvulnerable) {
mob[i].force.x += knock.x;
mob[i].force.y += knock.y;
}
radius *= 0.95 //reduced range for each additional explosion target
damageScale *= 0.87 //reduced damage for each additional explosion target
} else if (!mob[i].seePlayer.recall && dist < alertRange) {
mob[i].locatePlayer();
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) * 0.006);
mob[i].force.x += knock.x;
mob[i].force.y += knock.y;
if (tech.isExplosionStun) mobs.statusStun(mob[i], 60)
knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg * damageScale) * mob[i].mass * (mob[i].isBoss ? 0.002 : 0.006) * tech.implosion);
if (tech.isExplosionStun) {
mobs.statusStun(mob[i], 60)
knock *= 0.1
}
if (!mob[i].isInvulnerable) {
mob[i].force.x += knock.x;
mob[i].force.y += knock.y;
}
}
}
}
@@ -761,6 +769,37 @@ const b = {
// });
// }
// },
fireworks(where, size) { //can occur after grenades detonate
const cycle = () => {
if (simulation.paused || m.isBodiesAsleep) { requestAnimationFrame(cycle) } else {
count++
if (count < 60 && m.alive) requestAnimationFrame(cycle);
if (!(count % 8)) {
const unit = Vector.rotate({ x: 1, y: 0 }, 6.28 * Math.random())
b.explosion(Vector.add(where, Vector.mult(unit, size * (count * 0.011 + 0.03 * Math.random()))), size * (0.5 + Math.random() * 0.35), `hsla(${360*Math.random()},100%,66%,0.6)`); //makes bullet do explosive damage at end
}
}
}
let count = 7
requestAnimationFrame(cycle);
},
starburst(where, size) { //can occur after grenades detonate
const color = `hsla(${360*Math.random()},100%,66%,0.6)`
const cycle = () => {
if (simulation.paused || m.isBodiesAsleep) { requestAnimationFrame(cycle) } else {
count++
if (count < 21 && m.alive) requestAnimationFrame(cycle);
if (count % 2) {
const unit = Vector.rotate({ x: 1, y: 0 }, curl * 6.28 * count / 18 + off)
b.explosion(Vector.add(where, Vector.mult(unit, size * 0.8)), size * 0.75, color); //makes bullet do explosive damage at end
}
}
}
const off = 6 * Math.random()
const curl = Math.random() < 0.5 ? -1 : 1;
let count = 0
requestAnimationFrame(cycle);
},
grenade() {
},
@@ -769,9 +808,15 @@ const b = {
const me = bullet.length;
bullet[me] = Bodies.circle(where.x, where.y, 15, b.fireAttributes(angle, false));
Matter.Body.setDensity(bullet[me], 0.0003);
bullet[me].explodeRad = 300 * size;
bullet[me].explodeRad = (tech.implosion ? 375 : 300) * size + 100 * tech.isBlockExplode;
bullet[me].onEnd = function() {
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
if (tech.isCircleExplode) {
b.starburst(this.position, this.explodeRad)
} else if (tech.isClusterExplode) {
b.fireworks(this.position, this.explodeRad)
} else {
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
}
if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 1.5 * Math.random()))
}
bullet[me].minDmgSpeed = 1;
@@ -794,8 +839,13 @@ const b = {
const me = bullet.length;
bullet[me] = Bodies.circle(where.x, where.y, 15, b.fireAttributes(angle, false));
Matter.Body.setDensity(bullet[me], 0.0003);
bullet[me].explodeRad = 305 * size;
bullet[me].explodeRad = (tech.implosion ? 375 : 300) * size + 100 * tech.isBlockExplode;
bullet[me].onEnd = function() {
if (tech.isCircleExplode) {
b.starburst(this.position, this.explodeRad)
} else if (tech.isClusterExplode) {
b.fireworks(this.position, this.explodeRad)
}
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 1.5 * Math.random()))
}
@@ -829,8 +879,13 @@ const b = {
const me = bullet.length;
bullet[me] = Bodies.circle(where.x, where.y, 15, b.fireAttributes(angle, false));
Matter.Body.setDensity(bullet[me], 0.0003);
bullet[me].explodeRad = 350 * size + Math.floor(Math.random() * 50) + tech.isBlockExplode * 110
bullet[me].explodeRad = (tech.implosion ? 425 : 350) * size + Math.floor(Math.random() * 50) + tech.isBlockExplode * 100
bullet[me].onEnd = function() {
if (tech.isCircleExplode) {
b.starburst(this.position, this.explodeRad)
} else if (tech.isClusterExplode) {
b.fireworks(this.position, this.explodeRad)
}
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 1.5 * Math.random()))
}
@@ -862,7 +917,7 @@ const b = {
for (i = 0, len = who.length; i < len; i++) {
const sub = Vector.sub(that.position, who[i].position);
const dist = Vector.magnitude(sub);
if (dist < radius && dist > 150) {
if (dist < radius && dist > 150 && !who.isInvulnerable) {
knock = Vector.mult(Vector.normalise(sub), mag * who[i].mass / Math.sqrt(dist));
who[i].force.x += knock.x;
who[i].force.y += knock.y;
@@ -906,8 +961,13 @@ const b = {
const me = bullet.length;
bullet[me] = Bodies.circle(where.x, where.y, 20, b.fireAttributes(angle, false));
Matter.Body.setDensity(bullet[me], 0.0002);
bullet[me].explodeRad = 350 * size + Math.floor(Math.random() * 50) + tech.isBlockExplode * 100
bullet[me].explodeRad = (tech.implosion ? 425 : 350) * size + Math.floor(Math.random() * 50) + tech.isBlockExplode * 100
bullet[me].onEnd = function() {
if (tech.isCircleExplode) {
b.starburst(this.position, this.explodeRad)
} else if (tech.isClusterExplode) {
b.fireworks(this.position, this.explodeRad)
}
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 1.5 * Math.random()))
}
@@ -926,7 +986,7 @@ const b = {
for (i = 0, len = who.length; i < len; i++) {
const sub = Vector.sub(that.position, who[i].position);
const dist = Vector.magnitude(sub);
if (dist < radius && dist > 150) {
if (dist < radius && dist > 150 && !who.isInvulnerable) {
knock = Vector.mult(Vector.normalise(sub), mag * who[i].mass / Math.sqrt(dist));
who[i].force.x += knock.x;
who[i].force.y += knock.y;
@@ -1099,7 +1159,7 @@ const b = {
}
}
//aoe damage to mobs
const dmg = m.dmgScale * 0.11 * tech.radioactiveDamage
let dmg = m.dmgScale * 0.11 * tech.radioactiveDamage
for (let i = 0, len = mob.length; i < len; i++) {
if (Vector.magnitude(Vector.sub(mob[i].position, this.position)) < this.damageRadius + mob[i].radius) {
if (Matter.Query.ray(map, mob[i].position, this.position).length > 0) dmg *= 0.25 //reduce damage if a wall is in the way
@@ -1140,21 +1200,12 @@ const b = {
}
}
let gunIndex = null
for (let i = 0, len = b.guns.length; i < len; i++) {
if (b.guns[i].name === "grenades") {
gunIndex = i
}
}
if (tech.isNeutronBomb) {
b.grenade = grenadeNeutron
if (tech.isRPG) {
b.guns[gunIndex].do = function() {}
b.guns[5].do = function() {}
} else {
if (gunIndex) b.guns[gunIndex].do = function() {
b.guns[5].do = function() {
if (!input.field && input.down) {
const cycles = 80
const speed = input.down ? 35 : 20 //input.down ? 43 : 32
@@ -1172,7 +1223,7 @@ const b = {
}
}
} else if (tech.isRPG) {
b.guns[gunIndex].do = function() {}
b.guns[5].do = function() {}
if (tech.isVacuumBomb) {
b.grenade = grenadeRPGVacuum
} else {
@@ -1180,7 +1231,7 @@ const b = {
}
} else if (tech.isVacuumBomb) {
b.grenade = grenadeVacuum
if (gunIndex) b.guns[gunIndex].do = function() {
b.guns[5].do = function() {
if (!input.field && input.down) {
const cycles = Math.floor(input.down ? 50 : 30) //30
const speed = input.down ? 44 : 35
@@ -1197,7 +1248,7 @@ const b = {
}
} else {
b.grenade = grenadeDefault
if (gunIndex) b.guns[gunIndex].do = function() {
b.guns[5].do = function() {
if (!input.field && input.down) {
const cycles = Math.floor(input.down ? 120 : 80) //30
const speed = input.down ? 43 : 32
@@ -1374,7 +1425,7 @@ const b = {
minDmgSpeed: 4,
lookFrequency: Math.floor(7 + Math.random() * 3),
density: tech.harpoonDensity, //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed
drain: 0.004,
drain: tech.isRailEnergyGain ? 0.002 : 0.006,
beforeDmg(who) {
if (tech.isShieldPierce && who.isShielded) { //disable shields
who.isShielded = false
@@ -1467,7 +1518,7 @@ const b = {
}
}
} else {
if (!tech.isRailEnergyGain && m.energy > 0.005) m.energy -= 0.005
if (m.energy > this.drain) m.energy -= this.drain
const sub = Vector.sub(this.position, m.pos)
const rangeScale = 1 + 0.000001 * Vector.magnitude(sub) * Vector.magnitude(sub) //return faster when far from player
const returnForce = Vector.mult(Vector.normalise(sub), rangeScale * this.thrustMag * this.mass)
@@ -1556,13 +1607,13 @@ const b = {
dist = 0
player.force.y += 5 * player.mass * simulation.g;
}
if (m.energy > this.drain || tech.isRailEnergyGain) {
if (m.energy > this.drain) {
Matter.Body.setVelocity(player, { x: player.velocity.x * 0.8, y: player.velocity.y * 0.8 });
const pull = Vector.mult(Vector.normalise(sub), 0.0008 * Math.min(Math.max(15, dist), 200))
player.force.x += pull.x
player.force.y += pull.y
if (!tech.isRailEnergyGain && dist > 500) {
if (dist > 500) {
m.energy -= this.drain
if (m.energy < 0) {
this.endCycle = 0;
@@ -1626,6 +1677,7 @@ const b = {
friction: 1,
frictionAir: 0.4,
thrustMag: 0.1,
drain: tech.isRailEnergyGain ? 0.002 : 0.006,
turnRate: isReturn ? 0.1 : 0.03, //0.015
drawStringControlMagnitude: 3000 + 5000 * Math.random(),
drawStringFlip: (Math.round(Math.random()) ? 1 : -1),
@@ -1747,7 +1799,7 @@ const b = {
}
}
} else {
if (!tech.isRailEnergyGain && m.energy > 0.005) m.energy -= 0.005
if (m.energy > this.drain) m.energy -= this.drain
const sub = Vector.sub(this.position, m.pos)
const rangeScale = 1 + 0.000001 * Vector.magnitude(sub) * Vector.magnitude(sub) //return faster when far from player
const returnForce = Vector.mult(Vector.normalise(sub), rangeScale * this.thrustMag * this.mass)
@@ -2621,7 +2673,7 @@ const b = {
},
worm(where, isFreeze = tech.isSporeFreeze) { //used with the tech upgrade in mob.death()
const bIndex = bullet.length;
const wormSize = 6 + tech.wormSize * 6 * Math.random()
const wormSize = 6 + tech.wormSize * 4.2 * Math.random()
if (bIndex < 500) { //can't make over 500 spores
bullet[bIndex] = Bodies.polygon(where.x, where.y, 3, 3, {
inertia: Infinity,
@@ -4858,8 +4910,20 @@ const b = {
// ******************************** Guns *********************************************
// **************************************************************************************************
// **************************************************************************************************
//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
guns: [{
name: "nail gun",
name: "nail gun", // 0
description: "use compressed air to fire a stream of <strong>nails</strong><br><strong><em>delay</em></strong> after firing <strong>decreases</strong> as you shoot",
ammo: 0,
ammoPack: 50,
@@ -5133,7 +5197,7 @@ const b = {
},
},
{
name: "shotgun",
name: "shotgun", //1
description: "fire a wide <strong>burst</strong> of short range <strong> bullets</strong>",
ammo: 0,
ammoPack: 3.5,
@@ -5336,10 +5400,10 @@ const b = {
}
}
}, {
name: "super balls",
name: "super balls", //2
description: "fire <strong>3</strong> balls in a wide arc<br>balls <strong>bounce</strong> with no momentum loss",
ammo: 0,
ammoPack: 10,
ammoPack: 9,
have: false,
// num: 5,
do() {},
@@ -5491,7 +5555,7 @@ const b = {
fire() {}
},
{
name: "matter wave",
name: "matter wave", //3
description: "emit a <strong>wave packet</strong> of oscillating particles<br>that propagates through <strong>solids</strong>",
ammo: 0,
ammoPack: 115,
@@ -5830,7 +5894,7 @@ const b = {
fire() {}
},
{
name: "missiles",
name: "missiles", //6
description: "launch <strong>homing</strong> missiles that <strong class='color-e'>explode</strong>",
ammo: 0,
ammoPack: 5,
@@ -5923,7 +5987,7 @@ const b = {
}
}
}, {
name: "grenades",
name: "grenades", //5
description: "lob a single <strong>bouncy</strong> projectile<br><strong class='color-e'>explodes</strong> on <strong>contact</strong> or after one second",
ammo: 0,
ammoPack: 7,
@@ -5941,7 +6005,7 @@ const b = {
}
},
}, {
name: "spores",
name: "spores", //6
description: "fire a <strong class='color-p' style='letter-spacing: 2px;'>sporangium</strong> that discharges <strong class='color-p' style='letter-spacing: 2px;'>spores</strong><br><strong class='color-p' style='letter-spacing: 2px;'>spores</strong> seek out nearby mobs",
ammo: 0,
ammoPack: 2.6,
@@ -6072,7 +6136,7 @@ const b = {
}
}
}, {
name: "drones",
name: "drones", //7
description: "deploy drones that <strong>crash</strong> into mobs<br>crashes reduce their <strong>lifespan</strong> by 1 second",
ammo: 0,
ammoPack: 16,
@@ -6100,7 +6164,7 @@ const b = {
}
},
{
name: "foam",
name: "foam", //8
description: "spray bubbly foam that <strong>sticks</strong> to mobs<br><strong class='color-s'>slows</strong> mobs and does <strong class='color-d'>damage</strong> over time",
ammo: 0,
ammoPack: 24,
@@ -6206,7 +6270,7 @@ const b = {
do() {},
},
{
name: "harpoon",
name: "harpoon", //9
description: "fire a <strong>self-steering</strong> harpoon that uses <strong class='color-f'>energy</strong><br>to <strong>retract</strong> and refund its <strong class='color-ammo'>ammo</strong> cost",
ammo: 0,
ammoPack: 0.6, //update this in railgun tech
@@ -6228,9 +6292,11 @@ const b = {
charge: 0,
railDo() {
if (this.charge > 0) {
const DRAIN = (tech.isRailEnergyGain ? 0.0005 : 0.002)
//exit railgun charging without firing
if (m.energy < 0.005 && !tech.isRailEnergyGain) {
m.energy += 0.025 + this.charge * 0.11
if (m.energy < DRAIN) {
// m.energy += 0.025 + this.charge * 22 * this.drain
// m.energy -= this.drain
m.fireCDcycle = m.cycle + 120; // cool down if out of energy
this.endCycle = 0;
this.charge = 0
@@ -6365,7 +6431,8 @@ const b = {
if (input.down) smoothRate *= 0.995
this.charge = this.charge * smoothRate + 1 - smoothRate
m.energy += (this.charge - previousCharge) * ((tech.isRailEnergyGain ? 0.5 : -0.3)) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen
if (m.energy > DRAIN) m.energy -= DRAIN
// m.energy += (this.charge - previousCharge) * ((tech.isRailEnergyGain ? 0.5 : -0.3)) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen
//draw magnetic field
const X = m.pos.x
@@ -6722,7 +6789,7 @@ const b = {
// }
// },
}, {
name: "mine",
name: "mine", //10
description: "toss a <strong>proximity</strong> mine that <strong>sticks</strong> to walls<br>refund <strong>undetonated</strong> mines on <strong>exiting</strong> a level", //fires <strong>nails</strong> at mobs within range
ammo: 0,
ammoPack: 1.25,
@@ -6765,393 +6832,8 @@ const b = {
}
}
},
// {
// name: "railgun",
// description: "use <strong class='color-f'>energy</strong> to launch a high-speed <strong>dense</strong> rod<br><strong>hold</strong> left mouse to charge, <strong>release</strong> to fire",
// ammo: 0,
// ammoPack: 3.8,
// have: false,
// do() {},
// fire() {
// function pushAway(range) { //push away blocks when firing
// for (let i = 0, len = mob.length; i < len; ++i) {
// const SUB = Vector.sub(mob[i].position, m.pos)
// const DISTANCE = Vector.magnitude(SUB)
// if (DISTANCE < range) {
// const DEPTH = Math.min(range - DISTANCE, 1500)
// const FORCE = Vector.mult(Vector.normalise(SUB), 0.001 * Math.sqrt(DEPTH) * mob[i].mass)
// mob[i].force.x += FORCE.x;
// mob[i].force.y += FORCE.y;
// }
// }
// for (let i = 0, len = body.length; i < len; ++i) {
// const SUB = Vector.sub(body[i].position, m.pos)
// const DISTANCE = Vector.magnitude(SUB)
// if (DISTANCE < range) {
// const DEPTH = Math.min(range - DISTANCE, 500)
// const FORCE = Vector.mult(Vector.normalise(SUB), 0.002 * Math.sqrt(DEPTH) * body[i].mass)
// body[i].force.x += FORCE.x;
// body[i].force.y += FORCE.y - body[i].mass * simulation.g * 1.5; //kick up a bit to give them some arc
// }
// }
// }
// if (tech.isCapacitor) {
// if ((m.energy > 0.16 || tech.isRailEnergyGain)) { //&& m.immuneCycle < m.cycle
// m.energy += 0.16 * (tech.isRailEnergyGain ? 2.5 : -1)
// m.fireCDcycle = m.cycle + Math.floor(40 * b.fireCDscale);
// const me = bullet.length;
// bullet[me] = Bodies.rectangle(m.pos.x + 50 * Math.cos(m.angle), m.pos.y + 50 * Math.sin(m.angle), 60, 14, {
// density: 0.005, //0.001 is normal
// restitution: 0,
// frictionAir: 0,
// angle: m.angle,
// dmg: 0, //damage done in addition to the damage from momentum
// classType: "bullet",
// collisionFilter: {
// category: cat.bullet,
// mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
// },
// minDmgSpeed: 5,
// endCycle: simulation.cycle + 140,
// beforeDmg(who) {
// if (who.shield) {
// for (let i = 0, len = mob.length; i < len; i++) {
// if (mob[i].id === who.shieldTargetID) { //apply some knock back to shield mob before shield breaks
// Matter.Body.setVelocity(mob[i], Vector.mult(Vector.normalise(this.velocity), 10));
// break
// }
// }
// Matter.Body.setVelocity(this, {
// x: -0.5 * this.velocity.x,
// y: -0.5 * this.velocity.y
// });
// // Matter.Body.setDensity(this, 0.001);
// }
// if (tech.fragments && this.speed > 10) {
// b.targetedNail(this.position, tech.fragments * 13)
// this.endCycle = 0 //triggers despawn
// }
// },
// onEnd() {},
// drawCycle: Math.floor(10 * b.fireCDscale),
// do() {
// this.force.y += this.mass * 0.0003; // low gravity that scales with charge
// if (this.drawCycle > 0) {
// this.drawCycle--
// //draw magnetic field
// const X = m.pos.x
// const Y = m.pos.y
// // const unitVector = Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos))
// const unitVector = { x: Math.cos(m.angle), y: Math.sin(m.angle) }
// const unitVectorPerp = Vector.perp(unitVector)
// function magField(mag, arc) {
// ctx.moveTo(X, Y);
// ctx.bezierCurveTo(
// X + unitVector.x * mag, Y + unitVector.y * mag,
// X + unitVector.x * mag + unitVectorPerp.x * arc, Y + unitVector.y * mag + unitVectorPerp.y * arc,
// X + unitVectorPerp.x * arc, Y + unitVectorPerp.y * arc)
// ctx.bezierCurveTo(
// X - unitVector.x * mag + unitVectorPerp.x * arc, Y - unitVector.y * mag + unitVectorPerp.y * arc,
// X - unitVector.x * mag, Y - unitVector.y * mag,
// X, Y)
// }
// ctx.fillStyle = `rgba(50,0,100,0.05)`;
// for (let i = 3; i < 7; i++) {
// const MAG = 8 * i * i * (0.93 + 0.07 * Math.random()) * (0.95 + 0.1 * Math.random())
// const ARC = 6 * i * i * (0.93 + 0.07 * Math.random()) * (0.95 + 0.1 * Math.random())
// ctx.beginPath();
// magField(MAG, ARC)
// magField(MAG, -ARC)
// ctx.fill();
// }
// }
// }
// });
// Composite.add(engine.world, bullet[me]); //add bullet to world
// const speed = 67
// Matter.Body.setVelocity(bullet[me], {
// x: m.Vx / 2 + speed * Math.cos(m.angle),
// y: m.Vy / 2 + speed * Math.sin(m.angle)
// });
// //knock back
// const KNOCK = (input.down ? 0.08 : 0.34)
// player.force.x -= KNOCK * Math.cos(m.angle)
// player.force.y -= KNOCK * Math.sin(m.angle) * 0.35 //reduce knock back in vertical direction to stop super jumps
// pushAway(800)
// } else {
// b.refundAmmo()
// m.fireCDcycle = m.cycle + Math.floor(120);
// }
// } else {
// const me = bullet.length;
// bullet[me] = Bodies.rectangle(0, 0, 0.015, 0.0015, {
// density: 0.008, //0.001 is normal
// restitution: 0,
// frictionAir: 0,
// dmg: 0, //damage done in addition to the damage from momentum
// classType: "bullet",
// collisionFilter: {
// category: 0,
// mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
// },
// minDmgSpeed: 5,
// beforeDmg(who) {
// if (who.shield) {
// for (let i = 0, len = mob.length; i < len; i++) {
// if (mob[i].id === who.shieldTargetID) { //apply some knock back to shield mob before shield breaks
// Matter.Body.setVelocity(mob[i], Vector.mult(Vector.normalise(this.velocity), 10));
// break
// }
// }
// Matter.Body.setVelocity(this, {
// x: -0.5 * this.velocity.x,
// y: -0.5 * this.velocity.y
// });
// }
// if (tech.fragments && this.speed > 10) {
// b.targetedNail(this.position, tech.fragments * 17)
// this.endCycle = 0 //triggers despawn
// }
// },
// onEnd() {}
// });
// m.fireCDcycle = Infinity; // cool down
// Composite.add(engine.world, bullet[me]); //add bullet to world
// bullet[me].endCycle = Infinity
// bullet[me].charge = 0;
// bullet[me].do = function() {
// if (m.energy < 0.005 && !tech.isRailEnergyGain) {
// m.energy += 0.05 + this.charge * 0.2
// m.fireCDcycle = m.cycle + 120; // cool down if out of energy
// this.endCycle = 0;
// b.refundAmmo()
// return
// }
// if ((!input.fire && this.charge > 0.6)) { //fire on mouse release or on low energy
// m.fireCDcycle = m.cycle + 2; // set fire cool down
// //normal bullet behavior occurs after firing, overwrites this function
// Matter.Body.scale(this, 8000, 8000) // show the bullet by scaling it up (don't judge me... I know this is a bad way to do it)
// this.endCycle = simulation.cycle + 140
// this.collisionFilter.category = cat.bullet
// Matter.Body.setPosition(this, {
// x: m.pos.x,
// y: m.pos.y
// })
// Matter.Body.setAngle(this, m.angle)
// const speed = 90
// Matter.Body.setVelocity(this, {
// x: m.Vx / 2 + speed * this.charge * Math.cos(m.angle),
// y: m.Vy / 2 + speed * this.charge * Math.sin(m.angle)
// });
// if (tech.isRodAreaDamage) {
// this.auraRadius = 800
// this.semiMinor = 0.5
// this.where = { x: m.pos.x, y: m.pos.y }
// this.velocityAura = { x: this.velocity.x, y: this.velocity.y }
// this.angleAura = this.angle
// this.do = function() {
// this.force.y += this.mass * 0.0003 / this.charge; // low gravity that scales with charge
// this.velocityAura.y += 0.085 / this.charge;
// this.where = Vector.add(this.where, this.velocityAura)
// //draw damage aura
// this.semiMinor = this.semiMinor * 0.99
// this.auraRadius = this.auraRadius * 0.99
// let where = Vector.add(Vector.mult(this.velocityAura, -0.5), this.where)
// ctx.beginPath();
// ctx.ellipse(where.x, where.y, this.auraRadius * 0.25, this.auraRadius * 0.15 * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
// ctx.fillStyle = "rgba(255,100,0,0.75)";
// ctx.fill();
// where = Vector.add(Vector.mult(this.velocity, -1), where)
// ctx.beginPath();
// ctx.ellipse(where.x, where.y, this.auraRadius * 0.5, this.auraRadius * 0.5 * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
// ctx.fillStyle = "rgba(255,50,0,0.35)";
// ctx.fill();
// where = Vector.add(Vector.mult(this.velocity, -1), where)
// ctx.beginPath();
// ctx.ellipse(where.x, where.y, this.auraRadius * 0.75, this.auraRadius * 0.7 * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
// ctx.fillStyle = "rgba(255,0,0,0.15)";
// ctx.fill();
// where = Vector.add(Vector.mult(this.velocity, -1), where)
// ctx.beginPath();
// ctx.ellipse(where.x, where.y, this.auraRadius, this.auraRadius * this.semiMinor, this.angleAura, 0, 2 * Math.PI)
// ctx.fillStyle = "rgba(255,0,0,0.03)";
// ctx.fill();
// //damage mobs in a circle based on this.semiMinor radius
// if (this.auraRadius > 200) {
// for (let i = 0, len = mob.length; i < len; ++i) {
// const dist = Vector.magnitude(Vector.sub(mob[i].position, where))
// if (dist < mob[i].radius + this.auraRadius) {
// //push mob in direction of bullet
// const mag = 0.0001
// mob[i].force.x += mag * this.velocity.x;
// mob[i].force.y += mag * this.velocity.y;
// //damage mob
// const damage = m.dmgScale * 0.002 * dist
// mob[i].damage(damage);
// mob[i].locatePlayer();
// simulation.drawList.push({ //add dmg to draw queue
// x: mob[i].position.x,
// y: mob[i].position.y,
// radius: Math.log(2 * damage + 1.1) * 40,
// color: "rgba(255,0,0,0.25)",
// time: simulation.drawTime
// });
// }
// }
// }
// //push blocks power ups and mobs to the direction the rod is moving
// }
// } else {
// this.do = function() {
// this.force.y += this.mass * 0.0003 / this.charge; // low gravity that scales with charge
// }
// }
// //knock back
// const KNOCK = ((input.down) ? 0.1 : 0.5) * this.charge * this.charge
// player.force.x -= KNOCK * Math.cos(m.angle)
// player.force.y -= KNOCK * Math.sin(m.angle) * 0.35 //reduce knock back in vertical direction to stop super jumps
// pushAway(1200 * this.charge)
// } else { // charging on mouse down
// if (tech.isFireMoveLock) {
// Matter.Body.setVelocity(player, {
// x: 0,
// y: -55 * player.mass * simulation.g //undo gravity before it is added
// });
// player.force.x = 0
// player.force.y = 0
// }
// m.fireCDcycle = Infinity //can't fire until mouse is released
// const previousCharge = this.charge
// let smoothRate = Math.min(0.998, (input.down ? 0.98 : 0.985) * (0.98 + 0.02 * b.fireCDscale)) //small b.fireCDscale = faster shots, b.fireCDscale=1 = normal shot, big b.fireCDscale = slower chot
// this.charge = this.charge * smoothRate + 1 - smoothRate
// m.energy += (this.charge - previousCharge) * (tech.isRailEnergyGain ? 1 : -0.33) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen
// //draw targeting
// let best;
// let range = 3000
// const dir = m.angle
// const path = [{
// x: m.pos.x + 20 * Math.cos(dir),
// y: m.pos.y + 20 * Math.sin(dir)
// },
// {
// x: m.pos.x + range * Math.cos(dir),
// y: m.pos.y + range * Math.sin(dir)
// }
// ];
// const vertexCollision = function(v1, v1End, domain) {
// for (let i = 0; i < domain.length; ++i) {
// let vertices = domain[i].vertices;
// const len = vertices.length - 1;
// for (let j = 0; j < len; j++) {
// results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
// if (results.onLine1 && results.onLine2) {
// const dx = v1.x - results.x;
// const dy = v1.y - results.y;
// const dist2 = dx * dx + dy * dy;
// if (dist2 < best.dist2) {
// best = {
// x: results.x,
// y: results.y,
// dist2: dist2,
// who: domain[i],
// v1: vertices[j],
// v2: vertices[j + 1]
// };
// }
// }
// }
// results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
// if (results.onLine1 && results.onLine2) {
// const dx = v1.x - results.x;
// const dy = v1.y - results.y;
// const dist2 = dx * dx + dy * dy;
// if (dist2 < best.dist2) {
// best = {
// x: results.x,
// y: results.y,
// dist2: dist2,
// who: domain[i],
// v1: vertices[0],
// v2: vertices[len]
// };
// }
// }
// }
// };
// //check for collisions
// best = {
// x: null,
// y: null,
// dist2: Infinity,
// who: null,
// v1: null,
// v2: null
// };
// vertexCollision(path[0], path[1], mob);
// vertexCollision(path[0], path[1], map);
// vertexCollision(path[0], path[1], body);
// if (best.dist2 != Infinity) { //if hitting something
// path[path.length - 1] = {
// x: best.x,
// y: best.y
// };
// }
// //draw beam
// ctx.beginPath();
// ctx.moveTo(path[0].x, path[0].y);
// ctx.lineTo(path[1].x, path[1].y);
// ctx.strokeStyle = `rgba(100,0,180,0.7)`;
// ctx.lineWidth = this.charge * 1
// ctx.setLineDash([10, 20]);
// ctx.stroke();
// ctx.setLineDash([]);
// //draw magnetic field
// const X = m.pos.x
// const Y = m.pos.y
// const unitVector = { x: Math.cos(m.angle), y: Math.sin(m.angle) }
// //Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos))
// const unitVectorPerp = Vector.perp(unitVector)
// function magField(mag, arc) {
// ctx.moveTo(X, Y);
// ctx.bezierCurveTo(
// X + unitVector.x * mag, Y + unitVector.y * mag,
// X + unitVector.x * mag + unitVectorPerp.x * arc, Y + unitVector.y * mag + unitVectorPerp.y * arc,
// X + unitVectorPerp.x * arc, Y + unitVectorPerp.y * arc)
// ctx.bezierCurveTo(
// X - unitVector.x * mag + unitVectorPerp.x * arc, Y - unitVector.y * mag + unitVectorPerp.y * arc,
// X - unitVector.x * mag, Y - unitVector.y * mag,
// X, Y)
// }
// ctx.fillStyle = `rgba(50,0,100,0.05)`;
// for (let i = 3; i < 7; i++) {
// const MAG = 8 * i * i * this.charge * (0.93 + 0.07 * Math.random())
// const ARC = 6 * i * i * this.charge * (0.93 + 0.07 * Math.random())
// ctx.beginPath();
// magField(MAG, ARC)
// magField(MAG, -ARC)
// ctx.fill();
// }
// }
// }
// }
// }
// },
{
name: "laser",
name: "laser", //11
description: "emit a <strong>beam</strong> of collimated coherent <strong class='color-laser'>light</strong><br>drains <strong class='color-f'>energy</strong> instead of ammunition",
ammo: 0,
ammoPack: Infinity,
@@ -7409,47 +7091,4 @@ const b = {
// },
},
],
// gunRewind: { //this gun is added with a tech
// name: "CPT gun",
// description: "use <strong class='color-f'>energy</strong> to <strong>rewind</strong> your <strong class='color-h'>health</strong>, <strong>velocity</strong>,<br> and <strong>position</strong> up to <strong>10</strong> seconds",
// ammo: 0,
// ammoPack: Infinity,
// have: false,
// isRewinding: false,
// lastFireCycle: 0,
// holdCount: 0,
// activeGunIndex: null,
// do() {},
// fire() {
// if (this.lastFireCycle === m.cycle - 1) { //button has been held down
// this.rewindCount += 8;
// const DRAIN = 0.01
// let history = m.history[(m.cycle - this.rewindCount) % 600]
// if (this.rewindCount > 599 || m.energy < DRAIN || history.activeGun !== this.activeGunIndex) {
// this.rewindCount = 0;
// m.resetHistory();
// m.fireCDcycle = m.cycle + Math.floor(120 * b.fireCDscale); // cool down
// } else {
// m.energy -= DRAIN
// if (m.immuneCycle < m.cycle + 30) m.immuneCycle = m.cycle + 30; //player is immune to damage for 5 cycles
// Matter.Body.setPosition(player, history.position);
// Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
// if (m.health !== history.health) {
// m.health = history.health
// m.displayHealth();
// }
// m.yOff = history.yOff
// if (m.yOff < 48) {
// m.doCrouch()
// } else {
// m.undoCrouch()
// }
// }
// } else { //button is held the first time
// this.rewindCount = 0;
// this.activeGunIndex = b.activeGun
// }
// this.lastFireCycle = m.cycle;
// }
// }
};

View File

@@ -198,6 +198,7 @@ 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

@@ -927,6 +927,10 @@ window.addEventListener("keydown", function(event) {
break
case input.key.testing:
if (m.alive && localSettings.loreCount > 0) {
if (simulation.difficultyMode > 4) {
simulation.makeTextLog("<em>testing mode disabled for this difficulty</em>");
break
}
if (simulation.testing) {
simulation.testing = false;
simulation.loop = simulation.normalLoop

View File

@@ -17,11 +17,11 @@ const level = {
if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.isHorizontalFlipped = true
// m.setField("perfect diamagnetism")
// b.giveGuns("shotgun")
// tech.giveTech("bremsstrahlung")
// tech.giveTech("cherenkov radiation")
// tech.giveTech("enthalpy")
// b.giveGuns("grenades")
// tech.giveTech("rule 30")
// tech.giveTech("cherenkov radiation")
// tech.giveTech("flame test")
// tech.giveTech("pyrotechnics")
// for (let i = 0; i < 10; i++) tech.giveTech("replication")
// tech.giveTech("decoherence")
// tech.giveTech("pneumatic actuator")
@@ -39,7 +39,7 @@ const level = {
// m.immuneCycle = Infinity //you can't take damage
// level.difficultyIncrease(15) //30 is near max on hard //60 is near max on why
// simulation.enableConstructMode() //used to build maps in testing mode
// level.warehouse();
// level.temple();
// level.testing(); //not in rotation, used for testing
if (simulation.isTraining) { level.walk(); } else { level.intro(); } //normal starting level ************************************************
// powerUps.research.changeRerolls(3000)
@@ -2644,11 +2644,11 @@ const level = {
spawn.mapRect(4850, -275, 50, 175);
//???
level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
m.addHealth(Infinity)
// spawn.starter(1900, -500, 200) //big boy
for (let i = 0; i < 10; ++i) spawn.launcher(1900, -500)
// for (let i = 0; i < 10; ++i) spawn.launcher(1900, -500)
// spawn.slashBoss(1900, -500)
// spawn.launcherBoss(3200, -500)
// spawn.laserTargetingBoss(1700, -500)
@@ -2663,7 +2663,7 @@ const level = {
// spawn.blinkBoss(1700, -500)
// spawn.snakeSpitBoss(3200, -500)
// spawn.laserBombingBoss(1700, -500)
// spawn.launcherBoss(3200, -500)
spawn.launcherBoss(3200, -500)
// spawn.blockBoss(1700, -500)
// spawn.blinkBoss(3200, -500)
// spawn.spiderBoss(1700, -500)
@@ -9511,22 +9511,14 @@ const level = {
me.attackCycle = 0;
me.lastAttackCycle = 0;
Matter.Body.setDensity(me, 0.014); // extra dense, normal is 0.001 // makes effective life much larger
Matter.Body.setDensity(me, 0.012); // extra dense, normal is 0.001 // makes effective life much larger
me.onDeath = function() {
// applying forces to player doesn't seem to work inside this method, not sure why
powerUps.spawn(this.position.x + 20, this.position.y, "ammo");
if (Math.random() > 0.5) powerUps.spawn(this.position.x, this.position.y, "ammo");
if (Math.random() > 0.3) powerUps.spawn(this.position.x, this.position.y, "heal", true, null, 30 * (simulation.healScale ** 0.25) * Math.sqrt(tech.largerHeals) * Math.sqrt(0.1 + Math.random() * 0.5));
if (simulation.difficulty > 5) {
// fling player to center
const SUB = V.sub(this.position, player.position)
const DISTANCE = V.magnitude(SUB)
if (DISTANCE < this.eventHorizon) {
Matter.Body.setVelocity(player, V.mult(SUB, 5e4 / (100 + DISTANCE) / (100 + DISTANCE)))
}
}
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1);
me.do = function() {
// keep it slow, to stop issues from explosion knock backs
if (this.speed > 1) {
@@ -9650,12 +9642,13 @@ const level = {
me.isBoss = true;
me.stroke = "transparent";
me.eventHorizon = 1000;
me.eventHorizon = 950;
me.collisionFilter.mask = cat.player | cat.bullet | cat.body;
me.memory = Infinity;
me.attackCycle = 0;
me.lastAttackCycle = 0;
me.spawnCycle = 0;
Matter.Body.setDensity(me, 0.08); //extra dense //normal is 0.001 //makes effective life much larger
me.onDeath = function() {
for (let j = 0; j < 8; j++) { //in case some mobs leave things after they die
@@ -9763,14 +9756,16 @@ const level = {
}
}
me.periodicSpawns = function() {
if (this.isInvulnerable) return;
this.spawnCycle++;
// Spawn annoying purple thing(s) that chases the player
if (!(simulation.cycle % 180)) {
if (!(this.spawnCycle % 180)) {
spawn.seeker(this.position.x, this.position.y, 15 * (0.7 + 0.5 * Math.random()), 7);
spawn.seeker(this.position.x, this.position.y, 4 * (0.7 + 0.5 * Math.random()), 7);
spawn.seeker(this.position.x, this.position.y, 4 * (0.7 + 0.5 * Math.random()), 7);
}
// Spawn the annoying pink (now blue) exploder that doesn't chase the player
if (!(simulation.cycle % 300)) {
if (!(this.spawnCycle % 300)) {
for (let i = 0; i < 3; i++) {
mobGrenade(1100 + 700 * i, -13030, undefined, Math.min(700, 300 + simulation.difficulty * 4), 10);
setVel(mob[mob.length - 1], { x: 0, y: -10 });
@@ -9779,19 +9774,30 @@ const level = {
}
}
// Spawn a bunch of mobs
if (!(simulation.cycle % 600)) {
spawn.nodeGroup(this.position.x, this.position.y, "focuser", 3);
if (!(this.spawnCycle % 600)) {
// This is just ripped off of spawn.nodeGroup because I don't want the shield
const nodes = 3;
const radius = Math.ceil(Math.random() * 10) + 18;
const sideLength = Math.ceil(Math.random() * 100) + 70;
const stiffness = Math.random() * 0.03 + 0.005;
spawn.allowShields = false; //don't want shields on individual group mobs
const angle = 2 * Math.PI / nodes
for (let i = 0; i < nodes; ++i) {
spawn.focuser(x + sideLength * Math.sin(i * angle), y + sideLength * Math.cos(i * angle), radius);
}
spawn.constrainAllMobCombos(nodes, stiffness);
spawn.allowShields = true;
}
}
me.invulnerableTrap = function() {
if (this.trapCycle < 1) return;
this.trapCycle++;
// 32 is just an arbitrarily large number
const spawnCycles = Math.min(32, Math.max(8, 6 + Math.floor(simulation.difficulty / 3)));
// 24 is just an arbitrarily large number
const spawnCycles = Math.min(24, Math.max(6, 4 + Math.floor(simulation.difficulty / 3)));
// I have no idea how to balance at all, please help me
const spawnDelay = Math.floor(5 + 10 / (1 + Math.sqrt(simulation.difficulty) / 5));
if (this.trapCycle >= 120) {
const cycle = this.trapCycle - 120;
if (this.trapCycle >= 90) {
const cycle = this.trapCycle - 90;
if (!(cycle % spawnDelay)) {
const radius = Math.min(500, 200 + simulation.difficulty * 3);
mobGrenade(600, -13050, 30, radius);
@@ -10220,7 +10226,6 @@ const level = {
this.pit1.height = this.pit1.width = 0;
this.pit2.height = this.pit2.width = 0;
}
},
draw() {
this.pit1.query();
@@ -10412,8 +10417,6 @@ const level = {
break;
}
}
// UwU
// Will I get timed out for this
if (!isInBounds) {
m.damage(0.1 * simulation.difficultyMode);
trapPlayer(level.enter.x, level.enter.y);
@@ -10601,7 +10604,8 @@ const level = {
powerUps.addResearchToLevel();
}
if (templePlayer.room1.cycles % 600 === 0 && templePlayer.room1.cycles <= 2400) {
for (let i = 0; i < 3 + Math.pow(simulation.difficulty / 2, 0.7) + Math.floor(templePlayer.room1.cycles / 720); i++) {
const spawnAmt = Math.min(3 + Math.pow(simulation.difficulty / 1.7, 0.6), 10) + Math.floor(templePlayer.room1.cycles / 720);
for (let i = 0; i < spawnAmt; i++) {
if (Math.random() < 0.5 + 0.07 * simulation.difficulty) {
spawn.randomMob(800 + Math.random() * 3e3, -2400 - Math.random() * 600, Infinity);
}

View File

@@ -1060,28 +1060,17 @@ const mobs = {
dmg *= tech.damageFromTech()
//mobs specific damage changes
if (tech.isFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(500, Math.min(3000, this.distanceToPlayer())) - 500) * 0.0067 //up to 50% dmg at max range of 3500
// if (this.shield) dmg *= 0.075
// if (this.isBoss) dmg *= 0.25
// if (this.damageReduction < 1) { //only used for bosses with this.armor() or shields
// this.damageReductionGoal += dmg * this.damageReductionScale //reduce damageReductionGoal
// dmg *= this.damageReduction
// }
dmg *= this.damageReduction
//energy and heal drain should be calculated after damage boosts
if (tech.energySiphon && dmg !== Infinity && this.isDropPowerUp && m.immuneCycle < m.cycle) m.energy += Math.min(this.health, dmg) * tech.energySiphon
if (tech.healthDrain && dmg !== Infinity && this.isDropPowerUp && Math.random() < tech.healthDrain * Math.min(this.health, dmg)) {
powerUps.spawn(m.pos.x + 20 * (Math.random() - 0.5), m.pos.y + 20 * (Math.random() - 0.5), "heal");
// powerUps.spawn(this.position.x + 20 * (Math.random() - 0.5), this.position.y + 20 * (Math.random() - 0.5), "heal");
// m.addHealth(Math.min(this.health, dmg) * tech.healthDrain)
// if (m.health > m.maxHealth) m.health = m.maxHealth
}
dmg /= Math.sqrt(this.mass)
this.health -= dmg
//this.fill = this.color + this.health + ')';
this.onDamage(dmg); //custom damage effects
if ((this.health < 0.05 || isNaN(this.health)) && this.alive) {
this.death();
}
if ((this.health < 0.05 || isNaN(this.health)) && this.alive) this.death();
}
},
onDamage() {

View File

@@ -543,18 +543,19 @@ const m = {
for (let i = 1, len = Math.floor(4 + steps / 40); i < len; i++) {
b.grenade(Vector.add(m.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -i * Math.PI / len) //fire different angles for each grenade
const who = bullet[bullet.length - 1]
if (tech.isVacuumBomb) {
if (tech.isNeutronBomb) {
Matter.Body.setVelocity(who, {
x: who.velocity.x * 0.3,
y: who.velocity.y * 0.3
});
} else if (tech.isVacuumBomb) {
Matter.Body.setVelocity(who, {
x: who.velocity.x * 0.5,
y: who.velocity.y * 0.5
});
} else if (tech.isRPG) {
who.endCycle = simulation.cycle + 10
} else if (tech.isNeutronBomb) {
Matter.Body.setVelocity(who, {
x: who.velocity.x * 0.3,
y: who.velocity.y * 0.3
});
} else {
Matter.Body.setVelocity(who, {
x: who.velocity.x * 0.5,

View File

@@ -300,7 +300,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.94) {
// powerUps.research.use('tech')
powerUps[type].effect();
return

View File

@@ -838,13 +838,13 @@ const simulation = {
if (tech.isDronesTravel && m.alive) {
//count drones
let count = 0
let droneCount = 0
let sporeCount = 0
let wormCount = 0
let deliveryCount = 0
for (let i = 0; i < bullet.length; ++i) {
if (bullet[i].isDrone) {
count++
droneCount++
if (bullet[i].isImproved) deliveryCount++
} else if (bullet[i].isSpore) {
sporeCount++
@@ -855,11 +855,11 @@ const simulation = {
//respawn drones in animation frame
let respawnDrones = () => {
if (count > 0) {
if (droneCount > 0) {
requestAnimationFrame(respawnDrones);
if (!simulation.paused && !simulation.isChoosing) {
const where = { x: level.enter.x + 50, y: level.enter.y - 60 }
count--
droneCount--
if (tech.isDroneRadioactive) {
b.droneRadioactive({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 100 * (Math.random() - 0.5) }, 0)
} else {
@@ -1037,7 +1037,7 @@ const simulation = {
if (!(m.cycle % 420)) { //once every 7 seconds
if (tech.isZeno) {
m.health *= 0.93 //remove 7%
m.health *= 0.94 //remove 7%
m.displayHealth();
}
if (tech.cyclicImmunity && m.immuneCycle < m.cycle + tech.cyclicImmunity) m.immuneCycle = m.cycle + tech.cyclicImmunity; //player is immune to damage for 60 cycles

View File

@@ -217,7 +217,7 @@ const tech = {
}
},
hasExplosiveDamageCheck() {
return tech.haveGunCheck("missiles") || tech.isMissileField || tech.missileBotCount > 0 || tech.boomBotCount > 1 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb)
return tech.haveGunCheck("missiles") || tech.isMissileField || tech.missileBotCount > 0 || tech.isBoomBotUpgrade || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb)
},
damageFromTech() {
let dmg = 1 //m.fieldDamage
@@ -864,7 +864,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.isStunField || tech.oneSuperBall || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isExplosionStun
return tech.isStunField || tech.oneSuperBall || tech.isCloakStun || tech.isOrbitBotUpgrade || tech.isExplosionStun
},
requires: "a stun effect",
effect() {
@@ -2539,7 +2539,7 @@ const tech = {
},
{
name: "Zeno's paradox",
description: "reduce <strong class='color-harm'>harm</strong> by <strong>85%</strong>, but every <strong>5</strong> seconds<br>remove <strong>7%</strong> of your current <strong class='color-h'>health</strong>",
description: "reduce <strong class='color-harm'>harm</strong> by <strong>85%</strong>, but every <strong>5</strong> seconds<br>remove <strong>6%</strong> of your current <strong class='color-h'>health</strong>",
// description: "every <strong>5</strong> seconds remove <strong>1/10</strong> of your <strong class='color-h'>health</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>90%</strong>",
maxCount: 1,
count: 0,
@@ -2704,9 +2704,9 @@ const tech = {
frequencyDefault: 1,
isHealTech: true,
allowed() {
return !tech.isEnergyHealth
return !tech.isNoHeals
},
requires: "not mass-energy equivalence",
requires: "not ergodicity",
effect() {
tech.healthDrain += 0.02;
},
@@ -3296,9 +3296,9 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
return level.onLevel > 1 && !tech.isEnergyHealth
return level.onLevel > 1 && !tech.isEnergyHealth && !tech.healthDrain
},
requires: "past level 1, not mass-energy",
requires: "past level 1, not mass-energy, enthalpy",
effect() {
tech.isNoHeals = true;
level.difficultyDecrease(simulation.difficultyMode * 2)
@@ -3338,7 +3338,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>94%</strong><br>chance to randomize <strong>choices</strong> and not <strong>cancel</strong>`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -3961,7 +3961,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob + (tech.haveGunCheck("super balls") + (tech.haveGunCheck("mine") && !tech.isLaserMine) + (tech.haveGunCheck("nail gun")) + tech.isNeedles + tech.isNailShot + tech.isRivets) * 2 > 1
return tech.isMineDrop + tech.isNailBotUpgrade + tech.fragments + tech.nailsDeathMob + (tech.haveGunCheck("super balls") + (tech.haveGunCheck("mine") && !tech.isLaserMine) + (tech.haveGunCheck("nail gun")) + tech.isNeedles + tech.isNailShot + tech.isRivets) * 2 > 1
},
requires: "nails, nail gun, rivets, shotgun",
effect() {
@@ -4073,7 +4073,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return (tech.isNailShot || tech.isNeedles || tech.nailBotCount > 1 || tech.haveGunCheck("nail gun") || tech.isRivets) && !tech.isIncendiary
return (tech.isNailShot || tech.isNeedles || tech.isNailBotUpgrade || tech.haveGunCheck("nail gun") || tech.isRivets) && !tech.isIncendiary
},
requires: "nail gun, needles, nails, rivets, not incendiary",
effect() {
@@ -4093,8 +4093,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
// return tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob / 2 + ((tech.haveGunCheck("mine") && !tech.isLaserMine) + (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) + tech.isNeedles + tech.isNailShot) * 2 > 1
return tech.isMineDrop || tech.nailBotCount || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !tech.isLaserMine) || (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot))
return tech.isMineDrop || tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !tech.isLaserMine) || (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot))
},
requires: "nail gun, nails, rivets, mine, not ceramic needles",
effect() {
@@ -4436,7 +4435,7 @@ const tech = {
},
{
name: "amplitude",
description: "wave packet <strong>amplitude</strong> is <strong>33%</strong> higher<br>wave <strong class='color-d'>damage</strong> is increased by <strong>50%</strong>",
description: "wave packet <strong>amplitude</strong> is <strong>33%</strong> higher<br>wave <strong class='color-d'>damage</strong> is increased by <strong>37%</strong>",
isGunTech: true,
maxCount: 3,
count: 0,
@@ -4448,7 +4447,7 @@ const tech = {
requires: "matter wave",
effect() {
tech.waveFrequency *= 0.66
tech.wavePacketDamage *= 1.5
tech.wavePacketDamage *= 1.37
},
remove() {
tech.waveFrequency = 0.2
@@ -4457,7 +4456,7 @@ const tech = {
},
{
name: "propagation",
description: "wave packet propagation <strong>speed</strong> is <strong>20%</strong> slower<br>wave <strong class='color-d'>damage</strong> is increased by <strong>50%</strong>",
description: "wave packet propagation <strong>speed</strong> is <strong>25%</strong> slower<br>wave <strong class='color-d'>damage</strong> is increased by <strong>37%</strong>",
isGunTech: true,
maxCount: 9,
count: 0,
@@ -4469,11 +4468,11 @@ const tech = {
requires: "matter wave",
effect() {
tech.waveBeamSpeed *= 0.8;
tech.waveBeamDamage += 1.5 * 0.5 //this sets base matter wave damage, not used by arcs or circles
tech.waveBeamDamage += 1.5 * 0.37 //this sets base matter wave damage
},
remove() {
tech.waveBeamSpeed = 10;
tech.waveBeamDamage = 1.5 //this sets base matter wave damage, not used by arcs or circles
tech.waveBeamDamage = 1.5 //this sets base matter wave damage
}
},
{
@@ -4662,9 +4661,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.explosiveRadius === 1 && !tech.isSmallExplosion && (tech.haveGunCheck("missiles") || tech.missileBotCount || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isTokamak)
return tech.implosion === -1 && tech.explosiveRadius === 1 && !tech.isSmallExplosion && !tech.isBlockExplode && !tech.fragments && (tech.haveGunCheck("missiles") || tech.missileBotCount || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.isPulseLaser || tech.isMissileField || tech.isBoomBotUpgrade || tech.isTokamak)
},
requires: "an explosive damage source, not ammonium nitrate or nitroglycerin",
requires: "an explosive damage source, not ammonium nitrate, nitroglycerin, chain reaction, fragmentation, implosion",
effect: () => {
tech.isExplodeRadio = true; //iridium-192
},
@@ -4681,9 +4680,9 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
return tech.haveGunCheck("harpoon") || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || tech.missileBotCount || tech.isRivets || tech.blockDamage > 0.075
return !tech.isExplodeRadio && (tech.haveGunCheck("harpoon") || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || tech.missileBotCount || tech.isRivets || tech.blockDamage > 0.075)
},
requires: "grenades, missiles, rivets, harpoon, or mass driver",
requires: "grenades, missiles, rivets, harpoon, or mass driver, not iridium-192",
effect() {
tech.fragments++
},
@@ -4693,7 +4692,7 @@ const tech = {
},
{
name: "ammonium nitrate",
description: "increase <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>27%</strong><br>increase <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>27%</strong>",
description: "increase <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>24%</strong><br>increase <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>24%</strong>",
isGunTech: true,
maxCount: 9,
count: 0,
@@ -4704,7 +4703,7 @@ const tech = {
},
requires: "an explosive damage source, not iridium-192",
effect: () => {
tech.explosiveRadius += 0.27;
tech.explosiveRadius += 0.24;
},
remove() {
tech.explosiveRadius = 1;
@@ -4719,9 +4718,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck()
return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() && !tech.isExplosionHarm
},
requires: "an explosive damage source, not iridium-192",
requires: "an explosive damage source, not iridium-192, acetone peroxide",
effect: () => {
tech.isSmallExplosion = true;
},
@@ -4739,9 +4738,9 @@ const tech = {
frequencyDefault: 2,
isBadRandomOption: true,
allowed() {
return tech.hasExplosiveDamageCheck()
return tech.hasExplosiveDamageCheck() && !tech.isSmallExplosion
},
requires: "an explosive damage source",
requires: "an explosive damage source, not nitroglycerin",
effect: () => {
tech.isExplosionHarm = true;
},
@@ -4833,7 +4832,7 @@ const tech = {
},
{
name: "MIRV",
description: "fire <strong>+1</strong> <strong>missile</strong> and <strong>grenade</strong> per shot<br>decrease <strong class='color-e'>explosion</strong> <strong>radius</strong> up to <strong>12%</strong>",
description: "fire <strong>+1</strong> <strong>missile</strong> and <strong>grenade</strong> per shot<br>decrease <strong class='color-e'>explosion</strong> <strong class='color-d'>damage</strong> and <strong>radius</strong> <strong>12%</strong>",
isGunTech: true,
maxCount: 9,
count: 0,
@@ -4892,6 +4891,25 @@ const tech = {
b.setGrenadeMode()
}
},
{
name: "implosion",
description: "<strong class='color-e'>explosions</strong> pull objects towards them<br>increase <strong>grenade</strong> radius and <strong class='color-d'>damage</strong> <strong>25%</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("grenades") && !tech.isExplodeRadio && !tech.isNeutronBomb
},
requires: "grenades, not iridium-192, neutron bomb",
effect: () => {
tech.implosion = 1;
},
remove() {
tech.implosion = -1;
}
},
{
name: "chain reaction",
description: "increase <strong>grenade</strong> radius and <strong class='color-d'>damage</strong> <strong>33%</strong><br><strong class='color-block'>blocks</strong> caught in <strong class='color-e'>explosions</strong> also <strong class='color-e'>explode</strong>",
@@ -4901,9 +4919,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.isVacuumBomb && !tech.isExplodeRadio
return tech.haveGunCheck("grenades") && !tech.isExplodeRadio && !tech.isNeutronBomb //tech.isVacuumBomb
},
requires: "grenades, vacuum bomb, not iridium-192",
requires: "grenades, not iridium-192, neutron bomb",
effect() {
tech.isBlockExplode = true; //chain reaction
},
@@ -4911,6 +4929,44 @@ const tech = {
tech.isBlockExplode = false;
}
},
{
name: "flame test",
description: "when <strong>grenades</strong> detonate they release<br>a colorful <strong>cluster</strong> of small <strong class='color-e'>explosions</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("grenades") && !tech.isNeutronBomb
},
requires: "grenades, not neutron bomb",
effect() {
tech.isClusterExplode = true;
},
remove() {
tech.isClusterExplode = false;
}
},
{
name: "pyrotechnics",
description: "when <strong>grenades</strong> detonate they release<br>a colorful <strong>circle</strong> of <strong class='color-e'>explosions</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("grenades") && !tech.isNeutronBomb && tech.isClusterExplode
},
requires: "grenades, flame test, not neutron bomb",
effect() {
tech.isCircleExplode = true;
},
remove() {
tech.isCircleExplode = false;
}
},
{
name: "neutron bomb",
description: "<strong>grenades</strong> are <strong class='color-p'>irradiated</strong> with <strong class='color-p'>Cf-252</strong><br>does <strong class='color-d'>damage</strong>, <strong class='color-harm'>harm</strong>, and drains <strong class='color-f'>energy</strong>",
@@ -4920,9 +4976,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("grenades") && !tech.fragments && !tech.isVacuumBomb && !tech.isExplodeRadio
return tech.haveGunCheck("grenades") && !tech.fragments && !tech.isVacuumBomb && !tech.isExplodeRadio && !tech.isBlockExplode && !tech.isClusterExplode && tech.implosion === -1
},
requires: "grenades, not fragmentation, vacuum bomb, iridium-192",
requires: "grenades, not fragmentation, vacuum bomb, iridium-192, pyrotechnics, implosion",
effect() {
tech.isNeutronBomb = true;
b.setGrenadeMode()
@@ -4972,9 +5028,9 @@ const tech = {
},
{
name: "nuclear transmutation",
description: "<strong class='color-p'>radiation</strong> does <strong>70%</strong> more <strong class='color-d'>damage</strong> and <strong class='color-harm'>harm</strong><br><em>nail, drone, neutron bomb, iridium, string, deflect</em>",
description: "<strong class='color-p'>radiation</strong> does <strong>47%</strong> more <strong class='color-d'>damage</strong> and <strong class='color-harm'>harm</strong><br><em>nail, drone, neutron bomb, iridium, string, deflect</em>",
isGunTech: true,
maxCount: 1,
maxCount: 9,
count: 0,
frequency: 2,
frequencyDefault: 2,
@@ -4983,7 +5039,7 @@ const tech = {
},
requires: "radiation damage source",
effect() {
tech.radioactiveDamage = 1.7
tech.radioactiveDamage += 1.47
},
remove() {
tech.radioactiveDamage = 1
@@ -5213,7 +5269,7 @@ const tech = {
},
{
name: "annelids",
description: "increase <strong class='color-p' style='letter-spacing: -0.8px;'>worm</strong> size and <strong class='color-d'>damage</strong><br>between <strong>10%</strong> and <strong>120%</strong>",
description: "increase <strong class='color-p' style='letter-spacing: -0.8px;'>worm</strong> size and <strong class='color-d'>damage</strong><br>by an average of <strong>37%</strong>",
isGunTech: true,
maxCount: 3,
count: 0,
@@ -5259,7 +5315,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || tech.haveGunCheck("spores") || tech.haveGunCheck("drones") || tech.haveGunCheck("missiles") || tech.haveGunCheck("foam") || tech.haveGunCheck("matter wave") || tech.isNeutronBomb || tech.isIceField || tech.isIceShot || tech.relayIce || tech.isNeedleIce || tech.blockingIce > 1 || tech.isSporeWorm || tech.foamBotCount > 1 || tech.isFoamBall
return m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || tech.haveGunCheck("spores") || tech.haveGunCheck("drones") || tech.haveGunCheck("missiles") || tech.haveGunCheck("foam") || tech.haveGunCheck("matter wave") || tech.isNeutronBomb || tech.isIceField || tech.isIceShot || tech.relayIce || tech.isNeedleIce || tech.blockingIce > 1 || tech.isSporeWorm || tech.isFoamBotUpgrade || tech.isFoamBall
},
requires: "drones, spores, missiles, foam, matter wave, neutron bomb, ice IX",
effect() {
@@ -5530,7 +5586,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return !tech.isBulletTeleport && (tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot || tech.isFoamBall)
return !tech.isBulletTeleport && (tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall)
},
requires: "foam, not uncertainty",
effect() {
@@ -5549,7 +5605,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return (!tech.isFoamAttract && (tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot || tech.isFoamBall)) || (tech.haveGunCheck("matter wave") && !tech.isLongitudinal)
return (!tech.isFoamAttract && (tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall)) || (tech.haveGunCheck("matter wave") && !tech.isLongitudinal)
},
requires: "foam, matter wave, not electrostatic induction, not phonon",
effect() {
@@ -5568,7 +5624,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("foam") || tech.isFoamBall || tech.foamBotCount > 1 || tech.isFoamShot || tech.isSporeWorm
return tech.haveGunCheck("foam") || tech.isFoamBall || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isSporeWorm
},
requires: "foam, worms",
effect() {
@@ -5587,7 +5643,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot || tech.isFoamBall
return tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall
},
requires: "foam",
effect() {
@@ -5608,7 +5664,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot || tech.isFoamBall
return tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall
},
requires: "foam",
effect() {
@@ -5814,7 +5870,7 @@ const tech = {
},
{
name: "alternator",
description: "<strong>harpoons</strong> drain no <strong class='color-f'>energy</strong><br><strong>railgun</strong> generates <strong class='color-f'>energy</strong>", //as they <strong>retract</strong><br><strong>crouch</strong> firing <strong>harpoon</strong> generates <strong class='color-f'>energy</strong>",
description: "<strong>harpoon</strong>, <strong>railgun</strong>, and <strong>grappling hook</strong><br>drain <strong>60%</strong> less <strong class='color-f'>energy</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -5852,7 +5908,10 @@ const tech = {
},
{
name: "Bessemer process",
description: "increase the <strong>size</strong> of your <strong>harpoon</strong><br>by <strong>10%</strong> of the square root of harpoon <strong class='color-ammo'>ammo</strong>",
descriptionFunction() {
return `increase <strong>harpoon</strong> size and <strong class='color-d'>damage</strong><br>by 1/10 √ harpoon <strong class='color-ammo'>ammo</strong> <em>(${(10 * Math.sqrt(b.guns[9].ammo)).toFixed(0)}%)</em>`
},
// description: "increase the <strong>size</strong> of your <strong>harpoon</strong><br>by <strong>10%</strong> of √ of harpoon <strong class='color-ammo'>ammo</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -5878,8 +5937,8 @@ const tech = {
isGunTech: true,
maxCount: 9,
count: 0,
frequency: 1,
frequencyDefault: 1,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("harpoon") && b.returnGunAmmo('harpoon') >= (tech.isRailGun ? 5 : 3) * (1 + this.count)
},
@@ -5913,7 +5972,10 @@ const tech = {
},
{
name: "UHMWPE",
description: "increase the <strong>length</strong> of your <strong>harpoon</strong>'s <strong>rope</strong><br>by <strong>1%</strong> per harpoon <strong class='color-ammo'>ammo</strong>",
descriptionFunction() {
return `increase the <strong>length</strong> of your <strong>harpoon</strong>'s <strong>rope</strong><br>by 1/100 of harpoon <strong class='color-ammo'>ammo</strong> <em>(${(b.guns[9].ammo).toFixed(0)}%)</em>`
},
// description: "increase the <strong>length</strong> of your <strong>harpoon</strong>'s <strong>rope</strong><br>by <strong>1%</strong> per harpoon <strong class='color-ammo'>ammo</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -6021,7 +6083,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return (tech.haveGunCheck("laser") || tech.laserBotCount > 1 || tech.isLaserMine) && tech.laserDamage === 0.17
return (tech.haveGunCheck("laser") || tech.isLaserBotUpgrade || tech.isLaserMine) && tech.laserDamage === 0.17
},
requires: "laser, not free-electron",
effect() {
@@ -6044,7 +6106,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.laserBotCount > 1) && !tech.isPulseLaser && tech.isLaserDiode === 1
return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.isLaserBotUpgrade) && !tech.isPulseLaser && tech.isLaserDiode === 1
},
requires: "laser, not pulse, diodes",
effect() {
@@ -6069,7 +6131,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return (tech.haveGunCheck("laser") && !tech.isPulseLaser) || tech.laserBotCount > 1
return (tech.haveGunCheck("laser") && !tech.isPulseLaser) || tech.isLaserBotUpgrade
},
requires: "laser, not pulse",
effect() {
@@ -6088,7 +6150,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.laserBotCount > 1) && !tech.isWideLaser && !tech.isPulseLaser && !tech.historyLaser
return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.isLaserBotUpgrade) && !tech.isWideLaser && !tech.isPulseLaser && !tech.historyLaser
},
requires: "laser, not diffuse beam, pulse, or slow light",
effect() {
@@ -6344,7 +6406,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "standing wave" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism"
return m.fieldUpgrades[m.fieldMode].name === "standing wave" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" || m.fieldUpgrades[m.fieldMode].name === "pilot wave"
},
requires: "standing wave, perfect diamagnetism",
effect() {
@@ -6363,7 +6425,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return (m.fieldUpgrades[m.fieldMode].name === "standing wave" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism") && tech.blockDmg
return (m.fieldUpgrades[m.fieldMode].name === "standing wave" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" || m.fieldUpgrades[m.fieldMode].name === "pilot wave") && tech.blockDmg
},
requires: "bremsstrahlung",
effect() {
@@ -6459,9 +6521,9 @@ const tech = {
frequency: 3,
frequencyDefault: 3,
allowed() {
return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" || m.fieldUpgrades[m.fieldMode].name === "negative mass") && (build.isExperimentSelection || powerUps.research.count > 3)
return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" || m.fieldUpgrades[m.fieldMode].name === "negative mass") && (build.isExperimentSelection || powerUps.research.count > 3) && !tech.isEnergyHealth
},
requires: "perfect diamagnetism, negative mass, pilot wave",
requires: "perfect diamagnetism, negative mass, pilot wave, not mass energy",
effect() {
tech.isFieldHarmReduction = true
for (let i = 0; i < 2; i++) {
@@ -6710,7 +6772,7 @@ const tech = {
frequency: 3,
frequencyDefault: 3,
allowed() {
return (build.isExperimentSelection || powerUps.research.count > 0) && m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isMissileField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport || tech.isDronesTravel)
return (build.isExperimentSelection || powerUps.research.count > 0) && m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isMissileField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport)
},
requires: "molecular assembler, no other manufacturing, no drone tech",
effect() {
@@ -7732,7 +7794,7 @@ const tech = {
// },
{
name: "panpsychism",
description: "awaken all <strong class='color-block'>blocks</strong><br><strong class='color-block'>blocks</strong> have a chance to spawn random power ups",
description: "awaken all <strong class='color-block'>blocks</strong><br><strong class='color-block'>blocks</strong> have a chance to spawn power ups",
maxCount: 1,
count: 0,
frequency: 0,
@@ -9592,6 +9654,70 @@ const tech = {
},
remove() {}
},
// {
// name: "rule 90",
// maxCount: 1,
// count: 0,
// frequency: 0,
// isJunk: true,
// allowed() {
// return true
// },
// requires: "",
// effect() {},
// remove() {},
// state: [
// [false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false]
// ],
// rule(state, a, b, c) {
// if (state[a] && state[b] && state[c]) return false; // TTT => F
// if (state[a] && state[b] && !state[c]) return true; // TTF => T
// if (state[a] && !state[b] && state[c]) return false; //TFT => F
// if (state[a] && !state[b] && !state[c]) return true; //TFF => T
// if (!state[a] && state[b] && state[c]) return true; //FTT => T
// if (!state[a] && state[b] && !state[c]) return false; //FTF => F
// if (!state[a] && !state[b] && state[c]) return true; //FFT => T
// if (!state[a] && !state[b] && !state[c]) return false; //FFF => F
// },
// id: 0,
// descriptionFunction() {
// const loop = () => {
// if ((simulation.paused || simulation.isChoosing) && m.alive && !build.isExperimentSelection) { //&& (!simulation.isChoosing || this.count === 0)
// let b = []; //produce next row
// b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 1, 0, 1)); //left edge wrap around
// for (let i = 1; i < this.state[this.state.length - 1].length - 1; i++) { //apply rule to the rest of the array
// b.push(this.rule(this.state[this.state.length - 1], i - 1, i, i + 1));
// }
// b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 2, this.state[this.state.length - 1].length - 1, 0)); //right edge wrap around
// this.state.push(b)
// if (document.getElementById(`cellular-rule-id${this.id}`)) document.getElementById(`cellular-rule-id${this.id}`).innerHTML = this.outputText() //convert to squares and send HTML
// if (this.count && this.state.length < 120 && !(this.state.length % 10)) powerUps.spawn(m.pos.x - 50 + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "research");
// setTimeout(() => { loop() }, 400);
// }
// }
// setTimeout(() => { loop() }, 400);
// // if (this.id === 0) {
// // for (let i = 0; i < 29; i++) this.state[0][i] = Math.random() < 0.5 //randomize seed
// // }
// this.id++
// return `<span id = "cellular-rule-id${this.id}" style = "letter-spacing: 0px;font-size: 50%;line-height: normal;">${this.outputText()}</span>`
// },
// outputText() {
// let text = ""
// for (let j = 0; j < this.state.length; j++) {
// text += "<p style = 'margin-bottom: -11px;'>"
// for (let i = 0; i < this.state[j].length; i++) {
// if (this.state[j][i]) {
// text += "⬛" //"█" //"■"
// } else {
// text += "⬜" //"&nbsp;&nbsp;&nbsp;&nbsp;" //"□"
// }
// }
// text += "</p>"
// }
// return text
// },
// },
{
name: "rule 30",
maxCount: 1,
@@ -9607,7 +9733,8 @@ const tech = {
state: [
[false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
],
rule30(state, a, b, c) {
rule(state, a, b, c) {
//30
if (state[a] && state[b] && state[c]) return false; // TTT => F
if (state[a] && state[b] && !state[c]) return false; // TTF => F
if (state[a] && !state[b] && state[c]) return false; //TFT => F
@@ -9619,21 +9746,40 @@ const tech = {
},
id: 0,
descriptionFunction() {
if (this.id === 0 && Math.random() < 0.5) {
// for (let i = 0; i < 29; i++) this.state[0][i] = Math.random() < 0.5 //randomize seed
this.name = "rule 90"
this.link = `<a target="_blank" href='https://en.wikipedia.org/w/index.php?search=${encodeURIComponent(this.name).replace(/'/g, '%27')}&title=Special:Search' class="link">${this.name}</a>`
// console.log(this.name)
this.state[0] = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false]
this.rule = function(state, a, b, c) {
if (state[a] && state[b] && state[c]) return false; // TTT => F
if (state[a] && state[b] && !state[c]) return true; // TTF => T
if (state[a] && !state[b] && state[c]) return false; //TFT => F
if (state[a] && !state[b] && !state[c]) return true; //TFF => T
if (!state[a] && state[b] && state[c]) return true; //FTT => T
if (!state[a] && state[b] && !state[c]) return false; //FTF => F
if (!state[a] && !state[b] && state[c]) return true; //FFT => T
if (!state[a] && !state[b] && !state[c]) return false; //FFF => F
}
}
const loop = () => {
if ((simulation.paused || simulation.isChoosing) && m.alive && !build.isExperimentSelection) { //&& (!simulation.isChoosing || this.count === 0)
let b = []; //produce next row
b.push(this.rule30(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 1, 0, 1)); //left edge wrap around
b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 1, 0, 1)); //left edge wrap around
for (let i = 1; i < this.state[this.state.length - 1].length - 1; i++) { //apply rule to the rest of the array
b.push(this.rule30(this.state[this.state.length - 1], i - 1, i, i + 1));
b.push(this.rule(this.state[this.state.length - 1], i - 1, i, i + 1));
}
b.push(this.rule30(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 2, this.state[this.state.length - 1].length - 1, 0)); //right edge wrap around
b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 2, this.state[this.state.length - 1].length - 1, 0)); //right edge wrap around
this.state.push(b)
if (document.getElementById(`cellular-rule-id${this.id}`)) document.getElementById(`cellular-rule-id${this.id}`).innerHTML = this.outputText() //convert to squares and send HTML
if (this.count && this.state.length < 120 && !(this.state.length % 10)) powerUps.spawn(m.pos.x - 50 + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "research");
setTimeout(() => { loop() }, 500);
setTimeout(() => { loop() }, 400);
}
}
setTimeout(() => { loop() }, 500);
setTimeout(() => { loop() }, 400);
this.id++
return `<span id = "cellular-rule-id${this.id}" style = "letter-spacing: 0px;font-size: 50%;line-height: normal;">${this.outputText()}</span>`
},
@@ -10038,5 +10184,8 @@ const tech = {
isFoamBall: null,
isNoDraftPause: null,
isFoamPressure: null,
foamDamage: null
foamDamage: null,
implosion: null,
isClusterExplode: null,
isCircleExplode: null
}

View File

@@ -1,22 +1,51 @@
******************************************************** NEXT PATCH **************************************************
bremsstrahlung does extra damage to shields
grenade tech: flame test - grenades release a cluster of smaller explosions
grenade tech: pyrotechnics - grenades release a circle of smaller explosions
grenade tech: implosion - explosions pull things in, not out, +25% to grenade explosion damage and radius
chain reaction no longer requires vacuum bomb
bosses and mobs have much less knock back from explosions
invulnerable mobs have no knock back
alternator harpoon/grapple/railgun energy drain reduced by 100->60%
bots no longer unlock tech until you upgrade to a bot type
JUNK tech rule 30 is now sometimes rule 90 instead
disabled testing for why? mode
wave beam
amplitude 50->37% damage
propagation 50->37% damage
worms
annelids 10-120% -> about 37% damage
radiation
nuclear transmutation stacks 9x
gives 70->47% damage per stack
explosions
ammonium nitrate 27->24% damage and radius
bug fixes
******************************************************** TODO ********************************************************
tech: increase damage from all radioactive sources by 66%
apply to dots and to drones, neutron bomb, and radioactive explosions
buff early matter wave without phonon
some grenade tech made all the bosses go away and not drop anything
check: fireworks, vacuum, stun, chain reaction, implosion
more fireworks themed grenade tech
shotting star - fire a series of explosions higher and higher up, also increase radius with height
star burst - 5 explosions in star shape
delay - explosion in same place
pulse
30s of lasers
merge mines and grenades?
tech - neutron bombs deal 100% more damage, but finishes detonating much faster
tech - neutron bombs will explode into a small iridum explosion after it expires
tech: damage mobs in your last 10 seconds of history
field tech?
time dilation?
standing wave is weak vs. exploding bullets
add foam tech that makes foam stronger vs. shields
tech: eternalism - don't pause time during draft
bugs?
requirements change after draft is generated
@@ -26,6 +55,7 @@ tech expansion: should also make other fields do things
how to make the description work
change description based on your current field?
perfect diamagnetism moves forward when you hold down the shield
it's great, but maybe annoying?
maybe only with crouch?
time dilation drains 1/2 as much energy when paused
grow plasma torch as you hold it down