diff --git a/.DS_Store b/.DS_Store
index 49bafe2..6085f67 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/js/bullet.js b/js/bullet.js
index 7bc2a28..068f1af 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -4023,7 +4023,13 @@ const b = {
nextFireCycle: 0, //use to remember how longs its been since last fire, used to reset count
startingHoldCycle: 0,
chooseFireMethod() { //set in simulation.startGame
- if (tech.isRivets) {
+ if (tech.nailRecoil) {
+ if (tech.isRivets) {
+ this.fire = this.fireRecoilRivets
+ } else {
+ this.fire = this.fireRecoilNails
+ }
+ } else if (tech.isRivets) {
this.fire = this.fireRivets
} else if (tech.isNeedles) {
this.fire = this.fireNeedles
@@ -4036,8 +4042,37 @@ const b = {
}
},
do() {},
- fire() {
+ fire() {},
+ fireRecoilNails() {
+ if (this.nextFireCycle + 1 < m.cycle) this.startingHoldCycle = m.cycle //reset if not constantly firing
+ const CD = Math.max(11 - 0.08 * (m.cycle - this.startingHoldCycle), 1) //CD scales with cycles fire is held down
+ this.nextFireCycle = m.cycle + CD * b.fireCDscale //predict next fire cycle if the fire button is held down
+ m.fireCDcycle = m.cycle + Math.floor(CD * b.fireCDscale); // cool down
+ this.baseFire(m.angle + (Math.random() - 0.5) * (input.down ? 0.05 : 0.1) / CD, 43 + 8 * Math.random())
+ //very complex recoil system
+ if (m.onGround) {
+ if (input.down) {
+ const KNOCK = 0.01
+ player.force.x -= KNOCK * Math.cos(m.angle)
+ player.force.y -= KNOCK * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
+ Matter.Body.setVelocity(player, {
+ x: player.velocity.x * 0.5,
+ y: player.velocity.y * 0.5
+ });
+ } else {
+ const KNOCK = 0.05
+ player.force.x -= KNOCK * Math.cos(m.angle)
+ player.force.y -= KNOCK * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
+ Matter.Body.setVelocity(player, {
+ x: player.velocity.x * 0.8,
+ y: player.velocity.y * 0.8
+ });
+ }
+ } else {
+ if (Math.abs(player.velocity.x) < 12) player.force.x -= 0.04 * Math.cos(m.angle)
+ player.force.y -= 0.01 * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
+ }
},
fireNormal() {
if (this.nextFireCycle + 1 < m.cycle) this.startingHoldCycle = m.cycle //reset if not constantly firing
@@ -4118,21 +4153,98 @@ const b = {
}
};
b.muzzleFlash(30);
+ //very complex recoil system
+ if (m.onGround) {
+ if (input.down) {
+ const KNOCK = 0.01
+ player.force.x -= KNOCK * Math.cos(m.angle)
+ player.force.y -= KNOCK * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
+ } else {
+ const KNOCK = 0.02
+ player.force.x -= KNOCK * Math.cos(m.angle)
+ player.force.y -= KNOCK * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
+ }
+ } else {
+ const KNOCK = 0.01
+ player.force.x -= KNOCK * Math.cos(m.angle)
+ player.force.y -= KNOCK * Math.sin(m.angle) * 0.5 //reduce knock back in vertical direction to stop super jumps
+ }
},
- // fireNailFireRate() {
- // if (this.nextFireCycle + 1 < m.cycle) this.startingHoldCycle = m.cycle //reset if not constantly firing
- // const CD = Math.max(7.5 - 0.06 * (m.cycle - this.startingHoldCycle), 2) //CD scales with cycles fire is held down
- // this.nextFireCycle = m.cycle + CD * b.fireCDscale //predict next fire cycle if the fire button is held down
+ fireRecoilRivets() {
+ // m.fireCDcycle = m.cycle + Math.floor((input.down ? 25 : 17) * b.fireCDscale); // cool down
+ if (this.nextFireCycle + 1 < m.cycle) this.startingHoldCycle = m.cycle //reset if not constantly firing
+ const CD = Math.max(30 - 0.15 * (m.cycle - this.startingHoldCycle), 8) //CD scales with cycles fire is held down
+ this.nextFireCycle = m.cycle + CD * b.fireCDscale //predict next fire cycle if the fire button is held down
+ m.fireCDcycle = m.cycle + Math.floor(CD * b.fireCDscale); // cool down
- // m.fireCDcycle = m.cycle + Math.floor(CD * b.fireCDscale); // cool down
- // this.baseFire(m.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (input.down ? 1.35 : 3.2) / CD)
- // },
+ const me = bullet.length;
+ const size = tech.rivetSize * 8
+ bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle), m.pos.y + 35 * Math.sin(m.angle), 5 * size, size, b.fireAttributes(m.angle));
+ bullet[me].dmg = tech.isNailRadiation ? 0 : 2.75
+ Matter.Body.setDensity(bullet[me], 0.002);
+ Composite.add(engine.world, bullet[me]); //add bullet to world
+ const SPEED = input.down ? 60 : 50
+ Matter.Body.setVelocity(bullet[me], {
+ x: SPEED * Math.cos(m.angle),
+ y: SPEED * Math.sin(m.angle)
+ });
+ bullet[me].endCycle = simulation.cycle + 180
+ bullet[me].beforeDmg = function(who) { //beforeDmg is rewritten with ice crystal tech
+ if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.94) {
+ b.explosion(this.position, 300 + 30 * Math.random()); //makes bullet do explosive damage at end
+ }
+ if (tech.isNailRadiation) mobs.statusDoT(who, 7 * (tech.isFastRadiation ? 0.7 : 0.24), tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles
+ };
+
+ bullet[me].minDmgSpeed = 10
+ bullet[me].frictionAir = 0.006;
+ bullet[me].do = function() {
+ this.force.y += this.mass * 0.0008
+
+ //rotates bullet to face current velocity?
+ if (this.speed > 7) {
+ const facing = {
+ x: Math.cos(this.angle),
+ y: Math.sin(this.angle)
+ }
+ const mag = 0.002 * this.mass
+ if (Vector.cross(Vector.normalise(this.velocity), facing) < 0) {
+ this.torque += mag
+ } else {
+ this.torque -= mag
+ }
+ }
+ };
+ b.muzzleFlash(30);
+ //very complex recoil system
+ if (m.onGround) {
+ if (input.down) {
+ const KNOCK = 0.05
+ player.force.x -= KNOCK * Math.cos(m.angle)
+ player.force.y -= KNOCK * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
+ Matter.Body.setVelocity(player, {
+ x: player.velocity.x * 0.4,
+ y: player.velocity.y * 0.4
+ });
+ } else {
+ const KNOCK = 0.15
+ player.force.x -= KNOCK * Math.cos(m.angle)
+ player.force.y -= KNOCK * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
+ Matter.Body.setVelocity(player, {
+ x: player.velocity.x * 0.7,
+ y: player.velocity.y * 0.7
+ });
+ }
+ } else {
+ if (Math.abs(player.velocity.x) < 12) player.force.x -= 0.1 * Math.cos(m.angle)
+ player.force.y -= 0.03 * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
+ }
+ },
fireInstantFireRate() {
m.fireCDcycle = m.cycle + Math.floor(2 * b.fireCDscale); // cool down
this.baseFire(m.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (input.down ? 1.35 : 3.2) / 2)
},
- baseFire(angle) {
- const speed = 30 + 6 * Math.random()
+ baseFire(angle, speed = 30 + 6 * Math.random()) {
b.nail({
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
diff --git a/js/level.js b/js/level.js
index 60cc39e..7eb27f8 100644
--- a/js/level.js
+++ b/js/level.js
@@ -17,7 +17,9 @@ const level = {
// simulation.isHorizontalFlipped = true
// m.setField("plasma torch")
// b.giveGuns("nail gun")
- // tech.giveTech("negative friction")
+ // tech.giveTech("rotary cannon")
+ // tech.giveTech("pneumatic actuator")
+ // tech.giveTech("rivet gun")
// for (let i = 0; i < 2; i++) tech.giveTech("refractory metal")
// tech.giveTech("all-stars")
// for (let i = 0; i < 3; i++) tech.giveTech("overcharge")
@@ -2291,7 +2293,7 @@ const level = {
// for (let i = 0; i < 200; i++) powerUps.directSpawn(710 + 1000 * Math.random(), -710 + 1000 * Math.random(), "tech");
spawn.mapRect(2500, -1200, 200, 750); //right wall
- blockDoor(2585, -210)
+ // blockDoor(2585, -210)
spawn.mapRect(2500, -200, 200, 300); //right wall
spawn.mapRect(4500, -1200, 200, 650); //right wall
blockDoor(4585, -310)
@@ -2307,9 +2309,9 @@ const level = {
spawn.mapRect(5300, -275, 50, 175);
spawn.mapRect(5050, -100, 50, 150);
spawn.mapRect(4850, -275, 50, 175);
- // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
- // spawn.starter(1900, -500, 200) //big boy
- spawn.blockGroup(1900, -500)
+ level.difficultyIncrease(40) //30 is near max on hard //60 is near max on why
+ spawn.starter(1900, -500, 200) //big boy
+ // spawn.blockGroup(1900, -500)
// for (let i = 0; i < 10; ++i) spawn.bodyRect(1600 + 5, -500, 30, 40);
// spawn.laserBombingBoss(1900, -500)
// for (let i = 0; i < 5; i++) spawn.focuser(1900, -500)
diff --git a/js/spawn.js b/js/spawn.js
index 247a6a5..2424bb4 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -42,6 +42,11 @@ const spawn = {
const pick = this.pickList[Math.floor(Math.random() * this.pickList.length)];
this[pick](x, y);
}
+
+ if (tech.isMoreMobs) {
+ const pick = this.pickList[Math.floor(Math.random() * this.pickList.length)];
+ this[pick](x, y);
+ }
},
randomSmallMob(x, y,
num = Math.max(Math.min(Math.round(Math.random() * simulation.difficulty * 0.2), 4), 0),
@@ -53,6 +58,12 @@ const spawn = {
this[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) {
+ for (let i = 0; i < num; ++i) {
+ const pick = this.pickList[Math.floor(Math.random() * this.pickList.length)];
+ this[pick](x + Math.round((Math.random() - 0.5) * 20) + i * size * 2.5, y + Math.round((Math.random() - 0.5) * 20), size);
+ }
+ }
},
randomGroup(x, y, chance = 1) {
if (spawn.spawnChance(chance) && simulation.difficulty > 2 || chance === Infinity) {
diff --git a/js/tech.js b/js/tech.js
index 0896683..ce72025 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -3670,45 +3670,6 @@
}
}
},
- {
- name: "needle gun",
- description: "nail gun fires 3 mob piercing needles
requires 3 times more bullets",
- isGunTech: true,
- maxCount: 1,
- count: 0,
- frequency: 2,
- frequencyDefault: 2,
- allowed() {
- return tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.isIceCrystals && !tech.isRivets
- },
- requires: "nail gun, not ice crystal, rivets, or pneumatic actuator",
- effect() {
- tech.isNeedles = true
- for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
- if (b.guns[i].name === "nail gun") {
- b.guns[i].ammo = Math.ceil(b.guns[i].ammo / 3);
- b.guns[i].ammoPack = Math.ceil(b.guns[i].defaultAmmoPack / 3);
- b.guns[i].chooseFireMethod()
- simulation.updateGunHUD();
- break
- }
- }
- },
- remove() {
- if (tech.isNeedles) {
- tech.isNeedles = false
- for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
- if (b.guns[i].name === "nail gun") {
- b.guns[i].chooseFireMethod()
- b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 3);
- b.guns[i].ammoPack = b.guns[i].defaultAmmoPack;
- simulation.updateGunHUD();
- break
- }
- }
- }
- }
- },
{
name: "needle ice",
description: `when needles impact walls
they chip off 1-2 freezing ice IX crystals`,
@@ -3747,6 +3708,45 @@
tech.isNeedleShieldPierce = false
}
},
+ {
+ name: "needle gun",
+ description: "nail gun fires 3 mob piercing needles
requires 3 times more bullets",
+ isGunTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.isIceCrystals && !tech.isRivets && !tech.nailRecoil
+ },
+ requires: "nail gun, not ice crystal, rivets, or pneumatic actuator",
+ effect() {
+ tech.isNeedles = true
+ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
+ if (b.guns[i].name === "nail gun") {
+ b.guns[i].ammo = Math.ceil(b.guns[i].ammo / 3);
+ b.guns[i].ammoPack = Math.ceil(b.guns[i].defaultAmmoPack / 3);
+ b.guns[i].chooseFireMethod()
+ simulation.updateGunHUD();
+ break
+ }
+ }
+ },
+ remove() {
+ if (tech.isNeedles) {
+ tech.isNeedles = false
+ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
+ if (b.guns[i].name === "nail gun") {
+ b.guns[i].chooseFireMethod()
+ b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 3);
+ b.guns[i].ammoPack = b.guns[i].defaultAmmoPack;
+ simulation.updateGunHUD();
+ break
+ }
+ }
+ }
+ }
+ },
{
name: "rivet gun",
description: "nail gun slowly fires a heavy rivet",
@@ -3847,9 +3847,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles
+ return tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles && !tech.nailRecoil
},
- requires: "nail gun, not rivets or needles",
+ requires: "nail gun, not rotary cannon, rivets, or needles",
effect() {
tech.nailInstantFireRate = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -3865,33 +3865,33 @@
}
}
},
- // {
- // name: "powder-actuated",
- // description: "nail gun takes no time to ramp up
nails have a 30% faster muzzle speed",
- // isGunTech: true,
- // maxCount: 1,
- // count: 0,
- // frequency: 2,
- // frequencyDefault: 2,
- // allowed() {
- // return tech.haveGunCheck("nail gun") && tech.nailFireRate && !tech.isIceCrystals
- // },
- // requires: "nail gun and pneumatic actuator not ice crystal nucleation",
- // effect() {
- // tech.nailInstantFireRate = true
- // for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
- // if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod()
- // }
- // },
- // remove() {
- // if (tech.nailInstantFireRate) {
- // tech.nailInstantFireRate = false
- // for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
- // if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod()
- // }
- // }
- // }
- // },
+ {
+ name: "rotary cannon",
+ description: "nail gun has increased muzzle speed,
maximum fire rate, accuracy, and recoil",
+ isGunTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate
+ },
+ requires: "nail gun, not pneumatic actuator",
+ effect() {
+ tech.nailRecoil = true
+ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
+ if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod()
+ }
+ },
+ remove() {
+ if (tech.nailRecoil) {
+ tech.nailRecoil = false
+ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
+ if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod()
+ }
+ }
+ }
+ },
{
name: "supercritical fission",
description: "nails, needles, and rivets can explode
if they strike mobs near their center",
@@ -6776,6 +6776,25 @@
tech.removeMaxHealthOnKill = 0
}
},
+ {
+ name: "-parthenocarpy-",
+ description: "experiment: 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
@@ -6800,7 +6819,7 @@
// },
{
name: "negative friction",
- description: "when you touch walls you speed up instead of slowing down. It's actually pretty cool, seriously.",
+ description: "when you touch walls you speed up instead of slowing down. It's kinda fun.",
maxCount: 1,
count: 0,
frequency: 0,
@@ -6811,7 +6830,7 @@
},
requires: "",
effect() {
- player.friction = -0.5
+ player.friction = -0.4
},
remove() {
if (this.count) player.friction = 0.002
@@ -8624,5 +8643,7 @@
cloakDuplication: null,
extruderRange: null,
isRodAreaDamage: null,
- isForeverDrones: null
+ isForeverDrones: null,
+ isMoreMobs: null,
+ nailRecoil: null
}
\ No newline at end of file
diff --git a/todo.txt b/todo.txt
index b383e07..8cc7ac5 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,13 +1,19 @@
******************************************************** NEXT PATCH **************************************************
-perimeter defense and network effect each give 1% more bonus per bot (around an 18% increase for each tech)
-
-extra bosses spawned from parthenogenesis and apomixis have health increased by your duplication chance
- (if you have 50% duplication the extra boss have 50% more health)
-apomixis no longer costs 8 research
+tech: rotary cannon - nail gun (and rivet gun) have increased fire rate, muzzle speed, recoil, and accuracy
+experiment -parthenocarpy- spawn about 50% more mobs
******************************************************** TODO ********************************************************
+minigun: tech for nail gun - Its ramp-up time must not be removable. Recoil should be intense, enough that the player cannot walk forward quickly while using it.
+ nail gun gains: accuracy, bullet speed, huge recoil, fire rate
+ alternative to pnumatic that stops ramp up
+ maybe try to also apply to rivets?
+
+animate going to next level?
+ door fills in with color that climbs up vertically through the door graphic the longer you stand on door
+ hold crouch on door? or automatically
+
Plasma Burner: upgrade for plasma torch, basically just a jet engine. does high damage, but short range, mostly for player movement.
maybe reduce gravity to really low then apply a vector away from mouse direction