diff --git a/js/bullet.js b/js/bullet.js
index 4de5348..4fa4ded 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -475,7 +475,7 @@ const b = {
friction: 0,
frictionAir: 0.025,
thrust: mod.isFastSpores ? 0.001 : 0.0004,
- dmg: 2.8, //damage done in addition to the damage from momentum
+ dmg: mod.isMutualism ? 5.6 : 2.8, //2x bonus damage from mod.isMutualism
lookFrequency: 97 + Math.floor(117 * Math.random()),
classType: "bullet",
collisionFilter: {
@@ -491,7 +491,18 @@ const b = {
onDmg() {
this.endCycle = 0; //bullet ends cycle after doing damage
},
- onEnd() {},
+ onEnd() {
+ if (mod.isMutualism && this.isMutualismActive) {
+ if (mod.isEnergyHealth) {
+ mech.energy += 0.01;
+ } else {
+ mech.health += 0.01
+ if (mech.health > mech.maxHealth) mech.health = mech.maxHealth;
+ mod.onHealthChange();
+ mech.displayHealth();
+ }
+ }
+ },
do() {
if (!(game.cycle % this.lookFrequency)) { //find mob targets
this.closestTarget = null;
@@ -535,6 +546,20 @@ const b = {
y: SPEED * Math.sin(ANGLE)
});
World.add(engine.world, bullet[bIndex]); //add bullet to world
+
+ if (mod.isMutualism) {
+ if (mod.isEnergyHealth) {
+ if (mech.energy > 0.02) {
+ mech.energy -= 0.01; //energy takes an extra 25% damage for balancing purposes
+ bullet[bIndex].isMutualismActive = true
+ }
+ } else if (mech.health > 0.02) {
+ mech.health -= 0.01
+ mod.onHealthChange();
+ mech.displayHealth();
+ bullet[bIndex].isMutualismActive = true
+ }
+ }
},
iceIX(speed = 0, spread = 2 * Math.PI) {
const me = bullet.length;
@@ -1306,42 +1331,72 @@ const b = {
name: "flechettes",
description: "fire a volley of uranium-235 needles
does damage over 3 seconds",
ammo: 0,
- ammoPack: 23,
- defaultAmmoPack: 23,
+ ammoPack: 30,
+ defaultAmmoPack: 30,
have: false,
isStarterGun: true,
isEasyToAim: false,
count: 0, //used to track how many shots are in a volley before a big CD
lastFireCycle: 0, //use to remember how longs its been since last fire, used to reset count
fire() {
- const CD = (mech.crouch) ? 50 : 30
- if (this.lastFireCycle + CD < mech.cycle) this.count = 0 //reset count if it cycles past the CD
- this.lastFireCycle = mech.cycle
- if (this.count > ((mech.crouch) ? 6 : 1)) {
- this.count = 0
- mech.fireCDcycle = mech.cycle + Math.floor(CD * mod.fireRate); // cool down
- } else {
- this.count++
- mech.fireCDcycle = mech.cycle + Math.floor(3 * mod.fireRate); // cool down
- }
-
function makeFlechette(angle = mech.angle) {
const me = bullet.length;
bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(mech.angle), mech.pos.y + 40 * Math.sin(mech.angle), 45, 1.4, b.fireAttributes(angle));
- // Matter.Body.setDensity(bullet[me], 0.0001); //0.001 is normal
+ bullet[me].collisionFilter.mask = cat.body; //cat.mobShield | //cat.map | cat.body |
+ Matter.Body.setDensity(bullet[me], 0.00001); //0.001 is normal
bullet[me].endCycle = game.cycle + 180;
bullet[me].dmg = 0;
- bullet[me].onDmg = function (who) {
- if (mod.isDotFlechette) {
- mobs.statusDoT(who, 0.33, 360) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds)
- } else {
- mobs.statusDoT(who, 0.33, 180) // (2.3) / 6 ticks (3 seconds)
+ bullet[me].immuneList = []
+ bullet[me].do = function () {
+ const whom = Matter.Query.collides(this, mob)
+ if (whom.length && this.speed > 20) { //if touching a mob
+ who = whom[0].bodyA
+ if (who) {
+
+ function hit(that) {
+ who.foundPlayer();
+ if (mod.isDotFlechette) {
+ mobs.statusDoT(who, 0.5, 360)
+ } else {
+ mobs.statusDoT(who, 0.5, 180)
+ }
+ game.drawList.push({ //add dmg to draw queue
+ x: that.position.x,
+ y: that.position.y,
+ radius: 40,
+ color: "rgba(0,80,80,0.3)",
+ time: game.drawTime
+ });
+ }
+
+ if (mod.pierce) {
+ let immune = false
+ for (let i = 0; i < this.immuneList.length; i++) {
+ if (this.immuneList[i] === who.id) immune = true
+ }
+ if (!immune) {
+ this.immuneList.push(who.id)
+ hit(this)
+ }
+ } else {
+ this.endCycle = 0;
+ hit(this)
+ }
+ }
+ } else if (Matter.Query.collides(this, map).length) { //stick in walls
+ this.collisionFilter.mask = 0;
+ Matter.Body.setAngularVelocity(this, 0)
+ Matter.Body.setVelocity(this, {
+ x: 0,
+ y: 0
+ });
+ this.do = function () {}
+ } else if (this.speed < 30) {
+ this.force.y += this.mass * 0.0007; //no gravity until it slows down to improve aiming
}
};
- bullet[me].do = function () {
- if (this.speed < 10) this.force.y += this.mass * 0.0003; //no gravity until it slows don to improve aiming
- };
+
const SPEED = 50
Matter.Body.setVelocity(bullet[me], {
x: mech.Vx / 2 + SPEED * Math.cos(angle),
@@ -1351,9 +1406,46 @@ const b = {
}
makeFlechette()
if (mod.isFlechetteMultiShot) {
- makeFlechette(mech.angle + 0.01 + 0.01 * Math.random())
- makeFlechette(mech.angle - 0.01 - 0.01 * Math.random())
+ makeFlechette(mech.angle + 0.02 + 0.005 * Math.random())
+ makeFlechette(mech.angle - 0.02 - 0.005 * Math.random())
}
+
+ const CD = (mech.crouch) ? 60 : 30
+ if (this.lastFireCycle + CD < mech.cycle) this.count = 0 //reset count if it cycles past the CD
+ this.lastFireCycle = mech.cycle
+ if (this.count > ((mech.crouch) ? 7 : 1)) {
+ this.count = 0
+ mech.fireCDcycle = mech.cycle + Math.floor(CD * mod.fireRate); // cool down
+
+ const who = bullet[bullet.length - 1]
+ Matter.Body.setDensity(who, 0.00001);
+ // who.onDmg = function (who) {
+ // if (mod.isDotFlechette) {
+ // mobs.statusDoT(who, 0.33, 360) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds)
+ // mobs.statusSlow(who, 120) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds)
+ // } else {
+ // mobs.statusDoT(who, 0.33, 180) // (2.3) / 6 ticks (3 seconds)
+ // mobs.statusSlow(who, 60) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds)
+ // }
+ // this.endCycle = 0;
+ // };
+
+ // who.onEnd = function () {
+ // b.explosion(this.position, 220); //makes bullet do explosive damage at end
+ // }
+ // who.do = function () {
+ // if (this.speed < 10) this.force.y += this.mass * 0.0003; //no gravity until it slows don to improve aiming
+ // if (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length) {
+ // this.endCycle = 0; //explode if touching map or blocks
+ // }
+ // }
+
+ } else {
+ this.count++
+ mech.fireCDcycle = mech.cycle + Math.floor(3 * mod.fireRate); // cool down
+ }
+
+
}
},
{
@@ -1956,7 +2048,7 @@ const b = {
},
{
name: "spores",
- description: "fire a sporangium that discharges spores",
+ description: "fire a sporangium that discharges spores
spores seek out nearby mobs",
ammo: 0,
ammoPack: 5,
have: false,
@@ -2069,7 +2161,6 @@ const b = {
b.spore(this)
}
}
-
}
},
{
diff --git a/js/engine.js b/js/engine.js
index 2f344cd..dfc4a65 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -208,6 +208,7 @@ function collisionChecks(event) {
if (mod.isCrit && !mob[k].seePlayer.recall && !mob[k].shield) dmg *= 5
mob[k].foundPlayer();
mob[k].damage(dmg);
+ // console.log(dmg)
obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn
game.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x,
diff --git a/js/game.js b/js/game.js
index 9394731..c4eb2e7 100644
--- a/js/game.js
+++ b/js/game.js
@@ -644,6 +644,21 @@ const game = {
}
}
+ if (mod.isMutualism) {
+ for (let i = 0; i < bullet.length; i++) {
+ if (bullet[i].isMutualismActive) {
+ if (mod.isEnergyHealth) {
+ mech.energy += 0.01;
+ } else {
+ mech.health += 0.01
+ if (mech.health > mech.maxHealth) mech.health = mech.maxHealth;
+ mod.onHealthChange();
+ mech.displayHealth();
+ }
+ }
+ }
+ }
+
//if player is holding something this remembers it before it gets deleted
let holdTarget;
if (mech.holdingTarget) {
diff --git a/js/level.js b/js/level.js
index dff58af..1e15812 100644
--- a/js/level.js
+++ b/js/level.js
@@ -17,9 +17,9 @@ const level = {
// game.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(9)
// mech.setField("time dilation field")
- // mod.giveMod("brushless motor");
+ // mod.giveMod("mutualism");
// b.giveGuns("drones")
- // b.giveGuns("mine")
+ // b.giveGuns("spores")
// mech.setField("pilot wave")
// mech.setField("phase decoherence field")
@@ -60,10 +60,10 @@ const level = {
// if (level.isBuildRun) num++
for (let i = 0; i < num; i++) {
game.difficulty++
- game.dmgScale += 0.205; //damage done by mobs increases each level
+ game.dmgScale += 0.21; //damage done by mobs increases each level
b.dmgScale *= 0.91; //damage done by player decreases each level
- game.accelScale *= 1.024 //mob acceleration increases each level
- game.lookFreqScale *= 0.976 //mob cycles between looks decreases each level
+ game.accelScale *= 1.027 //mob acceleration increases each level
+ game.lookFreqScale *= 0.974 //mob cycles between looks decreases each level
game.CDScale *= 0.964 //mob CD time decreases each level
}
game.healScale = 1 / (1 + game.difficulty * 0.09) //a higher denominator makes for lower heals // mech.health += heal * game.healScale;
@@ -71,11 +71,11 @@ const level = {
difficultyDecrease(num = 1) { //used in easy mode for game.reset()
for (let i = 0; i < num; i++) {
game.difficulty--
- game.dmgScale -= 0.205; //damage done by mobs increases each level
+ game.dmgScale -= 0.21; //damage done by mobs increases each level
if (game.dmgScale < 0.1) game.dmgScale = 0.1;
b.dmgScale /= 0.91; //damage done by player decreases each level
- game.accelScale /= 1.024 //mob acceleration increases each level
- game.lookFreqScale /= 0.976 //mob cycles between looks decreases each level
+ game.accelScale /= 1.027 //mob acceleration increases each level
+ game.lookFreqScale /= 0.974 //mob cycles between looks decreases each level
game.CDScale /= 0.964 //mob CD time decreases each level
}
if (game.difficulty < 1) game.difficulty = 0;
@@ -187,6 +187,8 @@ const level = {
// spawn.laserTargetingBoss(1600, -400)
// spawn.spawner(1600, -500)
spawn.sniper(1700, -120)
+ // spawn.sniper(1600, -120)
+ // spawn.sniper(1800, -120)
// spawn.cellBossCulture(1600, -500)
// spawn.shooter(1600, -500)
// spawn.striker(1600, -500)
diff --git a/js/mods.js b/js/mods.js
index 74ea71e..ddc0279 100644
--- a/js/mods.js
+++ b/js/mods.js
@@ -374,29 +374,29 @@ const mod = {
},
remove() {}
},
- {
- name: "ablative mines",
- description: "rebuild your broken parts as a mine
chance to occur after being harmed",
- maxCount: 1,
- count: 0,
- allowed() {
- return true
- },
- requires: "",
- effect() {
- mod.isMineOnDamage = true;
- b.mine({
- x: mech.pos.x,
- y: mech.pos.y - 80
- }, {
- x: 0,
- y: 0
- })
- },
- remove() {
- mod.isMineOnDamage = false;
- }
- },
+ // {
+ // name: "ablative mines",
+ // description: "rebuild your broken parts as a mine
chance to occur after being harmed",
+ // maxCount: 1,
+ // count: 0,
+ // allowed() {
+ // return true
+ // },
+ // requires: "",
+ // effect() {
+ // mod.isMineOnDamage = true;
+ // b.mine({
+ // x: mech.pos.x,
+ // y: mech.pos.y - 80
+ // }, {
+ // x: 0,
+ // y: 0
+ // })
+ // },
+ // remove() {
+ // mod.isMineOnDamage = false;
+ // }
+ // },
{
name: "ablative drones",
description: "rebuild your broken parts as drones
chance to occur after being harmed",
@@ -767,7 +767,7 @@ const mod = {
},
{
name: "catabolism",
- description: "gain ammo when you fire while out of ammo
drains 3% of current remaining health",
+ description: "gain ammo when you fire while out of ammo
drains 3% of current remaining health",
maxCount: 1,
count: 0,
allowed() {
@@ -1143,6 +1143,22 @@ const mod = {
mod.isDotFlechette = false;
}
},
+ {
+ name: "piercing needles",
+ description: "needles penetrate mobs
potentially hitting multiple targets",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return mod.haveGunCheck("flechettes")
+ },
+ requires: "flechettes",
+ effect() {
+ mod.pierce = true;
+ },
+ remove() {
+ mod.pierce = false;
+ }
+ },
{
name: "wave packet",
description: "wave beam emits two oscillating particles
wave particles do 40% less damage",
@@ -1421,6 +1437,22 @@ const mod = {
mod.isSporeFollow = false
}
},
+ {
+ name: "mutualism",
+ description: "spores do 2x damage
spores borrow 1% health until they die",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return mod.haveGunCheck("spores") || mod.sporesOnDeath > 0 || mod.isSporeField
+ },
+ requires: "spores",
+ effect() {
+ mod.isMutualism = true
+ },
+ remove() {
+ mod.isMutualism = false
+ }
+ },
{
name: "brushless motor",
description: "drones accelerate 50% faster",
@@ -1785,7 +1817,7 @@ const mod = {
isImmuneExplosion: null,
isExplodeMob: null,
isDroneOnDamage: null,
- isMineOnDamage: null,
+ // isMineOnDamage: null,
acidDmg: null,
isAcidDmg: null,
isAnnihilation: null,
diff --git a/js/player.js b/js/player.js
index 89b3ffb..b3b41da 100644
--- a/js/player.js
+++ b/js/player.js
@@ -478,15 +478,15 @@ const mech = {
if (Math.random() < 0.5) b.drone() //spawn drone
}
}
- if (mod.isMineOnDamage && dmg > 0.004 + 0.05 * Math.random()) {
- b.mine({
- x: mech.pos.x,
- y: mech.pos.y - 80
- }, {
- x: 0,
- y: 0
- })
- }
+ // if (mod.isMineOnDamage && dmg > 0.004 + 0.05 * Math.random()) {
+ // b.mine({
+ // x: mech.pos.x,
+ // y: mech.pos.y - 80
+ // }, {
+ // x: 0,
+ // y: 0
+ // })
+ // }
dmg *= mech.harmReduction()
if (mod.isEnergyHealth) {
@@ -543,15 +543,14 @@ const mech = {
return;
}
}
+ mod.onHealthChange();
+ mech.displayHealth();
+ document.getElementById("dmg").style.transition = "opacity 0s";
+ document.getElementById("dmg").style.opacity = 0.1 + Math.min(0.6, dmg * 4);
}
if (dmg > 0.2 * mech.holdingMassScale) mech.drop(); //drop block if holding
- mod.onHealthChange();
- mech.displayHealth();
- document.getElementById("dmg").style.transition = "opacity 0s";
- document.getElementById("dmg").style.opacity = 0.1 + Math.min(0.6, dmg * 4);
-
const normalFPS = function () {
if (mech.defaultFPSCycle < mech.cycle) { //back to default values
game.fpsCap = game.fpsCapDefault
@@ -698,10 +697,10 @@ const mech = {
fieldMode: 0, //basic field mode before upgrades
maxEnergy: 1, //can be increased by a mod
holdingTarget: null,
- fieldShieldingScale: 1,
timeSkipLastCycle: 0,
// these values are set on reset by setHoldDefaults()
fieldRange: 155,
+ fieldShieldingScale: 1,
energy: 0,
fieldRegen: 0,
fieldMode: 0,
@@ -1220,9 +1219,10 @@ const mech = {
},
{
name: "standing wave harmonics",
- description: "three oscillating shields are permanently active
energy regenerates while field is active",
+ description: "three oscillating shields are permanently active
reduce harm by 33%",
isEasyToAim: true,
effect: () => {
+ mech.fieldHarmReduction = 0.67;
mech.fieldBlockCD = 0;
mech.hold = function () {
if (mech.isHolding) {
@@ -1510,11 +1510,10 @@ const mech = {
},
{
name: "plasma torch",
- description: "use energy to emit damaging plasma
reduce harm by 20%",
+ description: "use energy to emit short range plasma
plasma damages and pushes mobs",
isEasyToAim: false,
effect: () => {
mech.fieldMeterColor = "#f0f"
- mech.fieldHarmReduction = 0.80;
mech.hold = function () {
if (mech.isHolding) {
diff --git a/js/powerup.js b/js/powerup.js
index 2295d71..11f46aa 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -389,20 +389,22 @@ const powerUps = {
}
},
spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades
- if (game.difficultyMode > 1 || Math.random() < 0.66) { //easy and normal have only a 66% chance for a power up
- spawnPowerUps()
- if (game.difficultyMode > 2 && level.levelsCleared % 2 == 0) spawnPowerUps() //why? has an extra power up on even numbered levels
- } else {
- if (mech.health < 0.65 && !mod.isEnergyHealth) {
- powerUps.spawn(x, y, "heal");
- powerUps.spawn(x, y, "heal");
- if (Math.random() < mod.bayesian) {
+ if (level.levelsCleared < 20 || level.levelsCleared % 2 == 0) { //drop only on even levels above level 20
+ if (game.difficultyMode > 1 || Math.random() < 0.66) { //easy and normal have only a 66% chance for a power up
+ spawnPowerUps()
+ if (game.difficultyMode > 2 && level.levelsCleared % 2 == 0) spawnPowerUps() //why? has an extra power up on even numbered levels
+ } else {
+ if (mech.health < 0.65 && !mod.isEnergyHealth) {
powerUps.spawn(x, y, "heal");
powerUps.spawn(x, y, "heal");
+ if (Math.random() < mod.bayesian) {
+ powerUps.spawn(x, y, "heal");
+ powerUps.spawn(x, y, "heal");
+ }
+ } else if (!mod.bayesian) {
+ powerUps.spawn(x, y, "ammo");
+ powerUps.spawn(x, y, "ammo");
}
- } else if (!mod.bayesian) {
- powerUps.spawn(x, y, "ammo");
- powerUps.spawn(x, y, "ammo");
}
}
diff --git a/js/spawn.js b/js/spawn.js
index f01158f..4d107be 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -83,8 +83,7 @@ const spawn = {
},
randomLevelBoss(x, y) {
// other bosses: suckerBoss, laserBoss, tetherBoss, snakeBoss //all need a particular level to work so they are not included
- // "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss",
- const options = ["laserTargetingBoss"] // , "timeSkipBoss"
+ const options = ["shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss"] // , "timeSkipBoss"
spawn[options[Math.floor(Math.random() * options.length)]](x, y)
},
//mob templates *********************************************************************************************
@@ -893,17 +892,17 @@ const spawn = {
};
}
},
- laserTargetingBoss(x, y, radius = 70) {
+ laserTargetingBoss(x, y, radius = 65) {
const color = "#05f"
mobs.spawn(x, y, 3, radius, color);
let me = mob[mob.length - 1];
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
- me.accelMag = 0.0006 * game.accelScale;
+ me.accelMag = 0.0005 * game.accelScale;
me.seePlayerFreq = Math.floor(25 * game.lookFreqScale);
me.memory = 600;
me.restitution = 1;
- me.frictionAir = 0.06;
+ me.frictionAir = 0.05;
me.frictionStatic = 0;
me.friction = 0;
@@ -913,7 +912,7 @@ const spawn = {
x: 0,
y: 0
}
- Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger
+ Matter.Body.setDensity(me, 0.025); //extra dense //normal is 0.001 //makes effective life much larger
spawn.shield(me, x, y, 1);
me.onHit = function () {
//run this function on hitting player
diff --git a/todo.txt b/todo.txt
index 2e7d2cb..f70def1 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,19 +1,21 @@
-harmonic field now has no cooldown after blocking
-negative mass field accelerates slower, but with a higher top speed
-negative mass field harm reduction is now 60% and always on
-mod degenerate matter increases the damage reduction from 60% to 80%
-
-falling damage and damage from blocks have been removed
-(I'm trying it out, let me know if you want it back)
+above level 20 boss power ups only drop on even levels
+removed mod ablative mines (was buggy, and too similar to ablative drones)
+flechettes get stuck in walls
+flechettes do no damage to mobs on hit
+flechettes do more damage over time, and have more ammo
+mod - flechettes pierce mobs
+mod - mutualism: each spore does 2x damage but they borrow 1% life from player
************** TODO - n-gon **************
+shrink font on small screens (so you can see 5 options on power ups)
+
+graphic idea: bezier curve that moves smoothly from mob to mob
+ loops around player
+
add air control check box
set mech.airSpeedLimit to 0? to disable
-on damage mines mod needs a nerf
- spawns 2 mines every time... (from on dmg effects)
-
give rail gun projectile a trail
only draw above speed 5
track previous positions?
@@ -32,13 +34,6 @@ movement fluidity
wall grab?
maybe remove falling damage and block damage?
-rays can have width, how to use this?
- Matter.Query.ray(bodies, startPoint, endPoint, [rayWidth])
- wide lasers?
-
-new type of mob vision that uses ray query with thickness
- maybe use for bosses
-
bug - mines spawn extra mines when fired at thin map wall while jumping
what about a neutron bomb mod, that causes the bomb to activate right after you fire and slowly move forward with no gravity