worm hole mods
mod: critical bifurcation - nail gun does 400% more damage if it hits very close to the center of a mob mod: supercritical fission - flechettes explode if they hit very close to the center of a mob mod: transdimensional spores - after wormholes eat blocks, they disturb spores mod: traversable geodesics - your bullets can go through worm holes scrap bots now only last only 30 seconds, but they have a 20% chance to spawn from a kill (was 11%) the difficulty should feel a bit harder after clearing the boss level (a bit more more damage taken, and fewer mod drops)
This commit is contained in:
76
js/bullet.js
76
js/bullet.js
@@ -108,7 +108,7 @@ const b = {
|
||||
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
|
||||
},
|
||||
minDmgSpeed: 10,
|
||||
onDmg() {}, //this.endCycle = 0 //triggers despawn
|
||||
beforeDmg() {}, //this.endCycle = 0 //triggers despawn
|
||||
onEnd() {}
|
||||
};
|
||||
} else {
|
||||
@@ -125,7 +125,7 @@ const b = {
|
||||
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
|
||||
},
|
||||
minDmgSpeed: 10,
|
||||
onDmg() {}, //this.endCycle = 0 //triggers despawn
|
||||
beforeDmg() {}, //this.endCycle = 0 //triggers despawn
|
||||
onEnd() {}
|
||||
};
|
||||
}
|
||||
@@ -276,13 +276,13 @@ const b = {
|
||||
}
|
||||
}
|
||||
},
|
||||
missile(where, dir, speed, size = 1, spawn = 0) {
|
||||
missile(where, angle, speed, size = 1, spawn = 0) {
|
||||
const me = bullet.length;
|
||||
bullet[me] = Bodies.rectangle(where.x, where.y, 30 * size, 4 * size, b.fireAttributes(dir));
|
||||
bullet[me] = Bodies.rectangle(where.x, where.y, 30 * size, 4 * size, b.fireAttributes(angle));
|
||||
const thrust = 0.00417 * bullet[me].mass;
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: mech.Vx / 2 + speed * Math.cos(dir),
|
||||
y: mech.Vy / 2 + speed * Math.sin(dir)
|
||||
x: mech.Vx / 2 + speed * Math.cos(angle),
|
||||
y: mech.Vy / 2 + speed * Math.sin(angle)
|
||||
});
|
||||
World.add(engine.world, bullet[me]); //add bullet to world
|
||||
bullet[me].frictionAir = 0.023
|
||||
@@ -300,7 +300,7 @@ const b = {
|
||||
}
|
||||
}
|
||||
}
|
||||
bullet[me].onDmg = function () {
|
||||
bullet[me].beforeDmg = function () {
|
||||
this.tryToLockOn();
|
||||
this.endCycle = 0; //bullet ends cycle after doing damage // also triggers explosion
|
||||
};
|
||||
@@ -557,7 +557,7 @@ const b = {
|
||||
endCycle: Infinity,
|
||||
lookFrequency: 0,
|
||||
range: 700,
|
||||
onDmg() {},
|
||||
beforeDmg() {},
|
||||
do() {
|
||||
this.force.y += this.mass * 0.002; //extra gravity
|
||||
let collide = Matter.Query.collides(this, map) //check if collides with map
|
||||
@@ -686,7 +686,7 @@ const b = {
|
||||
x: 100 * (Math.random() - 0.5),
|
||||
y: 100 * (Math.random() - 0.5)
|
||||
},
|
||||
onDmg(who) {
|
||||
beforeDmg(who) {
|
||||
this.endCycle = 0; //bullet ends cycle after doing damage
|
||||
if (this.isFreeze) mobs.statusSlow(who, 60)
|
||||
},
|
||||
@@ -800,7 +800,7 @@ const b = {
|
||||
minDmgSpeed: 0,
|
||||
lockedOn: null,
|
||||
isFollowMouse: true,
|
||||
onDmg(who) {
|
||||
beforeDmg(who) {
|
||||
mobs.statusSlow(who, 60)
|
||||
this.endCycle = game.cycle
|
||||
if (mod.isHeavyWater) mobs.statusDoT(who, 0.15, 300)
|
||||
@@ -877,7 +877,7 @@ const b = {
|
||||
isFollowMouse: true,
|
||||
deathCycles: 110 + RADIUS * 5,
|
||||
isImproved: false,
|
||||
onDmg(who) {
|
||||
beforeDmg(who) {
|
||||
//move away from target after hitting
|
||||
const unit = Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), -20)
|
||||
Matter.Body.setVelocity(this, {
|
||||
@@ -1002,7 +1002,7 @@ const b = {
|
||||
target: null,
|
||||
targetVertex: null,
|
||||
targetRelativePosition: null,
|
||||
onDmg(who) {
|
||||
beforeDmg(who) {
|
||||
if (!this.target && who.alive) {
|
||||
this.target = who;
|
||||
if (who.radius < 20) {
|
||||
@@ -1154,15 +1154,14 @@ const b = {
|
||||
},
|
||||
nail(pos, velocity, dmg = 0) {
|
||||
const me = bullet.length;
|
||||
// bullet[me] = Bodies.rectangle(pos.x, pos.y, 25, 2, b.fireAttributes(Math.atan2(velocity.y, velocity.x)));
|
||||
bullet[me] = Bodies.rectangle(pos.x, pos.y, 25 * mod.biggerNails, 2 * mod.biggerNails, b.fireAttributes(Math.atan2(velocity.y, velocity.x)));
|
||||
|
||||
Matter.Body.setVelocity(bullet[me], velocity);
|
||||
World.add(engine.world, bullet[me]); //add bullet to world
|
||||
bullet[me].endCycle = game.cycle + 60 + 18 * Math.random();
|
||||
bullet[me].dmg = dmg
|
||||
bullet[me].onDmg = function (who) {
|
||||
bullet[me].beforeDmg = function (who) {
|
||||
if (mod.isNailPoison) mobs.statusDoT(who, dmg * 0.22, 120) // one tick every 30 cycles
|
||||
if (mod.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.99) this.dmg *= 5 //crit if hit near center
|
||||
};
|
||||
bullet[me].do = function () {};
|
||||
},
|
||||
@@ -1227,7 +1226,7 @@ const b = {
|
||||
mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield
|
||||
},
|
||||
lockedOn: null,
|
||||
onDmg() {
|
||||
beforeDmg() {
|
||||
this.lockedOn = null
|
||||
},
|
||||
onEnd() {},
|
||||
@@ -1283,7 +1282,7 @@ const b = {
|
||||
mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield
|
||||
},
|
||||
lockedOn: null,
|
||||
onDmg() {
|
||||
beforeDmg() {
|
||||
this.lockedOn = null
|
||||
},
|
||||
onEnd() {},
|
||||
@@ -1342,7 +1341,7 @@ const b = {
|
||||
mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield
|
||||
},
|
||||
lockedOn: null,
|
||||
onDmg() {
|
||||
beforeDmg() {
|
||||
this.lockedOn = null
|
||||
},
|
||||
onEnd() {},
|
||||
@@ -1452,7 +1451,7 @@ const b = {
|
||||
},
|
||||
lockedOn: null,
|
||||
explode: 0,
|
||||
onDmg() {
|
||||
beforeDmg() {
|
||||
if (this.lockedOn) {
|
||||
const explosionRadius = Math.min(170 + 140 * this.isUpgraded, Vector.magnitude(Vector.sub(this.position, mech.pos)) - 30)
|
||||
if (explosionRadius > 60) {
|
||||
@@ -1528,7 +1527,7 @@ const b = {
|
||||
mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield
|
||||
},
|
||||
lockedOn: null,
|
||||
onDmg() {
|
||||
beforeDmg() {
|
||||
this.lockedOn = null
|
||||
},
|
||||
onEnd() {},
|
||||
@@ -1706,7 +1705,7 @@ const b = {
|
||||
category: cat.bullet,
|
||||
mask: 0 //cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield
|
||||
},
|
||||
onDmg() {},
|
||||
beforeDmg() {},
|
||||
onEnd() {},
|
||||
range: 190 + 50 * mod.isOrbitBotUpgrade, //range is set in bot upgrade too! //150 + (80 + 100 * mod.isOrbitBotUpgrade) * Math.random(), // + 5 * mod.orbitBotCount,
|
||||
orbitalSpeed: 0,
|
||||
@@ -1850,7 +1849,7 @@ const b = {
|
||||
y: mech.Vy / 2 + speed * Math.sin(angle)
|
||||
}, dmg) //position, velocity, damage
|
||||
if (mod.isIceCrystals) {
|
||||
bullet[bullet.length - 1].onDmg = function (who) {
|
||||
bullet[bullet.length - 1].beforeDmg = function (who) {
|
||||
mobs.statusSlow(who, 30)
|
||||
if (mod.isNailPoison) mobs.statusDoT(who, dmg * 0.22, 120) // one tick every 30 cycles
|
||||
};
|
||||
@@ -1957,7 +1956,7 @@ const b = {
|
||||
bullet[me].do = function () {
|
||||
this.force.y += this.mass * 0.001;
|
||||
};
|
||||
bullet[me].onDmg = function (who) {
|
||||
bullet[me].beforeDmg = function (who) {
|
||||
mobs.statusStun(who, 180) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds)
|
||||
};
|
||||
} else {
|
||||
@@ -2031,6 +2030,11 @@ const b = {
|
||||
}
|
||||
} else {
|
||||
this.endCycle = 0;
|
||||
if (mod.isFlechetteExplode && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.98) {
|
||||
// mobs.statusStun(who, 120)
|
||||
this.explodeRad = 250 + 30 * Math.random();
|
||||
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
|
||||
}
|
||||
who.foundPlayer();
|
||||
if (mod.isFastDot) {
|
||||
mobs.statusDoT(who, 3.78, 30)
|
||||
@@ -2120,7 +2124,7 @@ const b = {
|
||||
category: 0,
|
||||
mask: 0, //cat.mob | cat.mobBullet | cat.mobShield
|
||||
},
|
||||
onDmg() {},
|
||||
beforeDmg() {},
|
||||
onEnd() {},
|
||||
do() {
|
||||
if (!mech.isBodiesAsleep) {
|
||||
@@ -2309,7 +2313,7 @@ const b = {
|
||||
bullet[me].onEnd = function () {
|
||||
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
|
||||
}
|
||||
bullet[me].onDmg = function () {
|
||||
bullet[me].beforeDmg = function () {
|
||||
this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion
|
||||
};
|
||||
bullet[me].do = function () {
|
||||
@@ -2335,7 +2339,7 @@ const b = {
|
||||
if (mod.grenadeFragments) b.targetedNail(this.position, mod.grenadeFragments)
|
||||
}
|
||||
bullet[me].minDmgSpeed = 1;
|
||||
bullet[me].onDmg = function () {
|
||||
bullet[me].beforeDmg = function () {
|
||||
this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion
|
||||
};
|
||||
|
||||
@@ -2401,7 +2405,7 @@ const b = {
|
||||
if (dist < this.explodeRad) mech.energy = 0 //remove player energy
|
||||
}
|
||||
}
|
||||
bullet[me].onDmg = function () {
|
||||
bullet[me].beforeDmg = function () {
|
||||
// this.endCycle = 0; //bullet ends cycle after doing damage //this triggers explosion
|
||||
};
|
||||
bullet[me].radius = 22; //used from drawing timer
|
||||
@@ -2510,7 +2514,7 @@ const b = {
|
||||
bullet[me].maxDamageRadius = (435 + 150 * Math.random()) * (mod.isNeutronImmune ? 1.2 : 1)
|
||||
bullet[me].stuckTo = null;
|
||||
bullet[me].stuckToRelativePosition = null;
|
||||
bullet[me].onDmg = function () {};
|
||||
bullet[me].beforeDmg = function () {};
|
||||
bullet[me].stuck = function () {};
|
||||
bullet[me].do = function () {
|
||||
function onCollide(that) {
|
||||
@@ -2682,7 +2686,7 @@ const b = {
|
||||
bullet[me].minDmgSpeed = 0;
|
||||
bullet[me].totalSpores = 8 + 2 * mod.isFastSpores + 2 * mod.isSporeFreeze
|
||||
bullet[me].stuck = function () {};
|
||||
bullet[me].onDmg = function () {};
|
||||
bullet[me].beforeDmg = function () {};
|
||||
bullet[me].do = function () {
|
||||
function onCollide(that) {
|
||||
that.collisionFilter.mask = 0; //non collide with everything
|
||||
@@ -2850,7 +2854,7 @@ const b = {
|
||||
name: "rail gun",
|
||||
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,
|
||||
ammoPack: 3.5,
|
||||
have: false,
|
||||
fire() {
|
||||
if (mod.isCapacitor) {
|
||||
@@ -2871,7 +2875,7 @@ const b = {
|
||||
},
|
||||
minDmgSpeed: 5,
|
||||
endCycle: game.cycle + 140,
|
||||
onDmg(who) {
|
||||
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
|
||||
@@ -2880,10 +2884,10 @@ const b = {
|
||||
}
|
||||
}
|
||||
Matter.Body.setVelocity(this, {
|
||||
x: -0.1 * this.velocity.x,
|
||||
y: -0.1 * this.velocity.y
|
||||
x: -0.5 * this.velocity.x,
|
||||
y: -0.5 * this.velocity.y
|
||||
});
|
||||
Matter.Body.setDensity(this, 0.001);
|
||||
// Matter.Body.setDensity(this, 0.001);
|
||||
}
|
||||
if (mod.isRailNails && this.speed > 10) {
|
||||
b.targetedNail(this.position, (Math.min(40, this.speed) - 10) * 0.6) // 0.6 as many nails as the normal rail gun
|
||||
@@ -2980,7 +2984,7 @@ const b = {
|
||||
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
|
||||
},
|
||||
minDmgSpeed: 5,
|
||||
onDmg(who) {
|
||||
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
|
||||
@@ -3472,7 +3476,7 @@ const b = {
|
||||
// },
|
||||
// minDmgSpeed: 5,
|
||||
// range: 0,
|
||||
// onDmg() {
|
||||
// beforeDmg() {
|
||||
// this.endCycle = 0;
|
||||
// }, //this.endCycle = 0 //triggers despawn
|
||||
// onEnd() {},
|
||||
|
||||
@@ -173,11 +173,11 @@ function collisionChecks(event) {
|
||||
}
|
||||
//mob + bullet collisions
|
||||
if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) {
|
||||
obj.beforeDmg(mob[k]); //some bullets do actions when they hits things, like despawn //forces don't seem to work here
|
||||
let dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)))
|
||||
if (mod.isCrit && mob[k].isStunned) dmg *= 4
|
||||
mob[k].foundPlayer();
|
||||
mob[k].damage(dmg);
|
||||
obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn //forces don't seem to work here
|
||||
game.drawList.push({ //add dmg to draw queue
|
||||
x: pairs[i].activeContacts[0].vertex.x,
|
||||
y: pairs[i].activeContacts[0].vertex.y,
|
||||
|
||||
17
js/level.js
17
js/level.js
@@ -15,12 +15,12 @@ const level = {
|
||||
// game.zoomScale = 1000;
|
||||
// game.setZoom();
|
||||
// mech.isCloak = true;
|
||||
mech.setField("wormhole")
|
||||
// b.giveGuns("nail gun")
|
||||
// mech.setField("wormhole")
|
||||
// b.giveGuns("flechettes")
|
||||
// for (let i = 0; i < 10; i++) {
|
||||
// mod.giveMod("laser-bot");
|
||||
// }
|
||||
mod.giveMod("cosmic string")
|
||||
// mod.giveMod("supercritical fission")
|
||||
|
||||
|
||||
level.intro(); //starting level
|
||||
@@ -149,10 +149,10 @@ const level = {
|
||||
// spawn.sniper(1700, -120, 50)
|
||||
// spawn.bomberBoss(1400, -500)
|
||||
// spawn.sniper(1800, -120)
|
||||
// spawn.sniper(2200, -120)
|
||||
// spawn.cellBossCulture(1600, -500)
|
||||
spawn.powerUpBoss(1600, -500)
|
||||
// spawn.shield(mob[mob.length - 1], 1200, -500, 1);
|
||||
// spawn.powerUpBoss(1600, -500)
|
||||
spawn.sniper(1200, -500)
|
||||
spawn.shield(mob[mob.length - 1], 1200, -500, 1);
|
||||
|
||||
// spawn.nodeBoss(1200, -500, "launcher")
|
||||
// spawn.snakeBoss(1200, -500)
|
||||
@@ -3841,7 +3841,7 @@ const level = {
|
||||
difficultyIncrease(num = 1) {
|
||||
for (let i = 0; i < num; i++) {
|
||||
game.difficulty++
|
||||
game.dmgScale += 0.37; //damage done by mobs increases each level
|
||||
game.dmgScale += 0.38; //damage done by mobs increases each level
|
||||
b.dmgScale *= 0.93; //damage done by player decreases each level
|
||||
if (game.accelScale < 5) game.accelScale *= 1.02 //mob acceleration increases each level
|
||||
if (game.lookFreqScale > 0.2) game.lookFreqScale *= 0.98 //mob cycles between looks decreases each level
|
||||
@@ -3852,7 +3852,7 @@ const level = {
|
||||
difficultyDecrease(num = 1) { //used in easy mode for game.reset()
|
||||
for (let i = 0; i < num; i++) {
|
||||
game.difficulty--
|
||||
game.dmgScale -= 0.37; //damage done by mobs increases each level
|
||||
game.dmgScale -= 0.38; //damage done by mobs increases each level
|
||||
if (game.dmgScale < 0.1) game.dmgScale = 0.1;
|
||||
b.dmgScale /= 0.93; //damage done by player decreases each level
|
||||
if (game.accelScale > 0.2) game.accelScale /= 1.02 //mob acceleration increases each level
|
||||
@@ -3887,6 +3887,7 @@ const level = {
|
||||
if (level.onLevel > level.levels.length - 1) level.onLevel = 0;
|
||||
level.difficultyIncrease(game.difficultyMode) //increase difficulty based on modes
|
||||
if (level.levelsCleared > level.levels.length) level.difficultyIncrease(game.difficultyMode)
|
||||
if (level.levelsCleared > level.levels.length * 1.25) level.difficultyIncrease(game.difficultyMode)
|
||||
if (level.levelsCleared > level.levels.length * 1.5) level.difficultyIncrease(game.difficultyMode)
|
||||
if (level.levelsCleared > level.levels.length * 2) level.difficultyIncrease(game.difficultyMode)
|
||||
if (game.isEasyMode && level.levelsCleared % 2) level.difficultyDecrease(1);
|
||||
|
||||
@@ -1043,7 +1043,10 @@ const mobs = {
|
||||
b.spore(this.position)
|
||||
}
|
||||
}
|
||||
if (Math.random() < mod.isBotSpawner) b.randomBot(this.position, false)
|
||||
if (Math.random() < mod.isBotSpawner) {
|
||||
b.randomBot(this.position, false)
|
||||
bullet[bullet.length - 1].endCycle = game.cycle + 1500 + Math.floor(600 * Math.random())
|
||||
}
|
||||
if (mod.isExplodeMob) b.explosion(this.position, Math.min(550, Math.sqrt(this.mass + 2.5) * 50))
|
||||
if (mod.nailsDeathMob) b.targetedNail(this.position, mod.nailsDeathMob, 40 + 7 * Math.random())
|
||||
} else if (mod.isShieldAmmo && this.shield) {
|
||||
|
||||
93
js/mods.js
93
js/mods.js
@@ -408,7 +408,7 @@ const mod = {
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField || mod.boomBotCount > 1;
|
||||
return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField || mod.boomBotCount > 1 || mod.isFlechetteExplode
|
||||
},
|
||||
requires: "an explosive damage source",
|
||||
effect: () => {
|
||||
@@ -424,7 +424,7 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField || mod.boomBotCount > 1;
|
||||
return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField || mod.boomBotCount > 1 || mod.isFlechetteExplode
|
||||
},
|
||||
requires: "an explosive damage source",
|
||||
effect: () => {
|
||||
@@ -440,7 +440,7 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField
|
||||
return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField || mod.isFlechetteExplode
|
||||
},
|
||||
requires: "an explosive damage source",
|
||||
effect: () => {
|
||||
@@ -457,7 +457,7 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.isMissileField || mod.isExplodeMob
|
||||
return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.isMissileField || mod.isExplodeMob || mod.isFlechetteExplode
|
||||
},
|
||||
requires: "an explosive damage source",
|
||||
effect: () => {
|
||||
@@ -469,15 +469,15 @@ const mod = {
|
||||
},
|
||||
{
|
||||
name: "scrap bots",
|
||||
description: "<strong>11%</strong> chance to build a <strong>bot</strong> after killing a mob<br>the bot only functions until the end of the level",
|
||||
maxCount: 6,
|
||||
description: "<strong>19%</strong> chance to build a <strong>bot</strong> after killing a mob<br>the bot last for about <strong>30</strong> seconds",
|
||||
maxCount: 3,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.totalBots() > 0
|
||||
},
|
||||
requires: "a bot",
|
||||
effect() {
|
||||
mod.isBotSpawner += 0.11;
|
||||
mod.isBotSpawner += 0.19;
|
||||
},
|
||||
remove() {
|
||||
mod.isBotSpawner = 0;
|
||||
@@ -1596,6 +1596,22 @@ const mod = {
|
||||
mod.isDamageFromBulletCount = false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "critical bifurcation",
|
||||
description: "<strong>nails</strong> do <strong>400%</strong> more <strong class='color-d'>damage</strong><br>when they strike near the <strong>center</strong> of a mob",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("nail gun")
|
||||
},
|
||||
requires: "nail gun",
|
||||
effect() {
|
||||
mod.isNailCrit = true
|
||||
},
|
||||
remove() {
|
||||
mod.isNailCrit = false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "pneumatic actuator",
|
||||
description: "<strong>nail gun</strong> takes <strong>45%</strong> less time to ramp up<br>to it's shortest <strong>delay</strong> after firing",
|
||||
@@ -1843,15 +1859,31 @@ const mod = {
|
||||
mod.isFastDot = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "supercritical fission",
|
||||
description: "<strong>flechettes</strong> can <strong class='color-e'>explode</strong><br>if they strike mobs near their <strong>center</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("flechettes") && !mod.pierce
|
||||
},
|
||||
requires: "flechettes and not piercing needles",
|
||||
effect() {
|
||||
mod.isFlechetteExplode = true
|
||||
},
|
||||
remove() {
|
||||
mod.isFlechetteExplode = false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "piercing needles",
|
||||
description: "<strong>needles</strong> penetrate <strong>mobs</strong> and <strong>blocks</strong><br>potentially hitting <strong>multiple</strong> targets",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("flechettes")
|
||||
return mod.haveGunCheck("flechettes") && !mod.isFlechetteExplode
|
||||
},
|
||||
requires: "flechettes",
|
||||
requires: "flechettes and not supercritical fission",
|
||||
effect() {
|
||||
mod.pierce = true;
|
||||
},
|
||||
@@ -2807,7 +2839,7 @@ const mod = {
|
||||
},
|
||||
{
|
||||
name: "cosmic string",
|
||||
description: "when you <strong> tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-d'>damage</strong> mobs between the <strong>endpoints</strong>",
|
||||
description: "when you <strong> tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br>mobs between the <strong>endpoints</strong> take <strong class='color-d'>damage</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -2823,7 +2855,7 @@ const mod = {
|
||||
},
|
||||
{
|
||||
name: "Penrose process",
|
||||
description: "after a <strong>block</strong> falls into a <strong class='color-worm'>wormhole</strong><br>overfill your <strong class='color-f'>energy</strong> to <strong>300%</strong> of your maximum<br> ",
|
||||
description: "after a <strong>block</strong> falls into a <strong class='color-worm'>wormhole</strong><br>your <strong class='color-f'>energy</strong> overfills to <strong>300%</strong> of the maximum",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -2837,6 +2869,39 @@ const mod = {
|
||||
mod.isWormholeEnergy = false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "transdimensional spores",
|
||||
description: "when <strong>blocks</strong> fall into a <strong class='color-worm'>wormhole</strong><br>higher dimension <strong class='color-p' style='letter-spacing: 2px;'>spores</strong> are summoned",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mech.fieldUpgrades[mech.fieldMode].name === "wormhole"
|
||||
},
|
||||
requires: "wormhole",
|
||||
effect() {
|
||||
mod.isWormSpores = true
|
||||
},
|
||||
remove() {
|
||||
mod.isWormSpores = false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "traversable geodesics",
|
||||
description: "your <strong>bullets</strong> can traverse <strong class='color-worm'>wormholes</strong><br>spawn a <strong class='color-g'>gun</strong> power up",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mech.fieldUpgrades[mech.fieldMode].name === "wormhole"
|
||||
},
|
||||
requires: "wormhole",
|
||||
effect() {
|
||||
mod.isWormBullets = true
|
||||
powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
|
||||
},
|
||||
remove() {
|
||||
mod.isWormBullets = false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "heals",
|
||||
description: "spawn <strong>6</strong> <strong class='color-h'>heal</strong> power ups",
|
||||
@@ -3074,5 +3139,9 @@ const mod = {
|
||||
isPerfectBrake: null,
|
||||
explosiveRadius: null,
|
||||
isWormholeEnergy: null,
|
||||
isWormholeDamage: null
|
||||
isWormholeDamage: null,
|
||||
isNailCrit: null,
|
||||
isFlechetteExplode: null,
|
||||
isWormSpores: null,
|
||||
isWormBullets: null
|
||||
}
|
||||
113
js/player.js
113
js/player.js
@@ -2240,37 +2240,27 @@ const mech = {
|
||||
},
|
||||
{
|
||||
name: "wormhole",
|
||||
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br>bullets may also traverse <strong class='color-worm'>wormholes</strong><br>blocks and power ups can't <strong>exit</strong>",
|
||||
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract blocks and power ups", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
|
||||
effect: () => {
|
||||
game.replaceTextLog = true; //allow text over write
|
||||
mech.drop();
|
||||
// mech.hole = { //this is reset with each new field, but I'm leaving it here for reference
|
||||
// isOn: false,
|
||||
// isReady: true,
|
||||
// pos1: {
|
||||
// x: 0,
|
||||
// y: 0
|
||||
// },
|
||||
// pos2: {
|
||||
// x: 0,
|
||||
// y: 0
|
||||
// },
|
||||
// pos1: {x: 0,y: 0},
|
||||
// pos2: {x: 0,y: 0},
|
||||
// angle: 0,
|
||||
// unit:{x:0,y:0},
|
||||
// }
|
||||
mech.hold = function () {
|
||||
|
||||
if (mech.hole.isOn) {
|
||||
// draw holes
|
||||
mech.fieldRange = 0.97 * mech.fieldRange + 0.03 * (50 + 10 * Math.sin(game.cycle * 0.025))
|
||||
|
||||
//draw bezier curves between the portals
|
||||
const semiMajorAxis = mech.fieldRange + 30
|
||||
const sub = Vector.sub(mech.hole.pos1, mech.hole.pos2)
|
||||
const unit = Vector.perp(Vector.normalise(sub))
|
||||
const edge1a = Vector.add(Vector.mult(unit, semiMajorAxis), mech.hole.pos1)
|
||||
const edge1b = Vector.add(Vector.mult(unit, -semiMajorAxis), mech.hole.pos1)
|
||||
const edge2a = Vector.add(Vector.mult(unit, semiMajorAxis), mech.hole.pos2)
|
||||
const edge2b = Vector.add(Vector.mult(unit, -semiMajorAxis), mech.hole.pos2)
|
||||
// const opacity = 200 / mech.fieldRange / mech.fieldRange
|
||||
const edge1a = Vector.add(Vector.mult(mech.hole.unit, semiMajorAxis), mech.hole.pos1)
|
||||
const edge1b = Vector.add(Vector.mult(mech.hole.unit, -semiMajorAxis), mech.hole.pos1)
|
||||
const edge2a = Vector.add(Vector.mult(mech.hole.unit, semiMajorAxis), mech.hole.pos2)
|
||||
const edge2b = Vector.add(Vector.mult(mech.hole.unit, -semiMajorAxis), mech.hole.pos2)
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(edge1a.x, edge1a.y)
|
||||
ctx.bezierCurveTo(mech.hole.pos1.x, mech.hole.pos1.y, mech.hole.pos2.x, mech.hole.pos2.y, edge2a.x, edge2a.y);
|
||||
@@ -2278,10 +2268,9 @@ const mech = {
|
||||
ctx.bezierCurveTo(mech.hole.pos2.x, mech.hole.pos2.y, mech.hole.pos1.x, mech.hole.pos1.y, edge1b.x, edge1b.y);
|
||||
ctx.fillStyle = `rgba(255,255,255,${200 / mech.fieldRange / mech.fieldRange})` //"rgba(0,0,0,0.1)"
|
||||
ctx.fill();
|
||||
const angle = Math.atan2(sub.y, sub.x)
|
||||
ctx.beginPath();
|
||||
ctx.ellipse(mech.hole.pos1.x, mech.hole.pos1.y, mech.fieldRange, semiMajorAxis, angle, 0, 2 * Math.PI)
|
||||
ctx.ellipse(mech.hole.pos2.x, mech.hole.pos2.y, mech.fieldRange, semiMajorAxis, angle, 0, 2 * Math.PI)
|
||||
ctx.ellipse(mech.hole.pos1.x, mech.hole.pos1.y, mech.fieldRange, semiMajorAxis, mech.hole.angle, 0, 2 * Math.PI)
|
||||
ctx.ellipse(mech.hole.pos2.x, mech.hole.pos2.y, mech.fieldRange, semiMajorAxis, mech.hole.angle, 0, 2 * Math.PI)
|
||||
ctx.fillStyle = `rgba(255,255,255,${32 / mech.fieldRange})`
|
||||
ctx.fill();
|
||||
|
||||
@@ -2318,20 +2307,6 @@ const mech = {
|
||||
}
|
||||
}
|
||||
}
|
||||
//teleport bullets
|
||||
for (let i = 0, len = bullet.length; i < len; ++i) { //teleport bullets from hole1 to hole2
|
||||
if (!bullet[i].botType && !bullet[i].isInHole) { //don't teleport bots
|
||||
if (Vector.magnitude(Vector.sub(mech.hole.pos1, bullet[i].position)) < mech.fieldRange) { //find if bullet is touching hole1
|
||||
Matter.Body.setPosition(bullet[i], Vector.add(mech.hole.pos2, Vector.sub(mech.hole.pos1, bullet[i].position)));
|
||||
mech.fieldRange += 5
|
||||
bullet[i].isInHole = true
|
||||
} else if (Vector.magnitude(Vector.sub(mech.hole.pos2, bullet[i].position)) < mech.fieldRange) { //find if bullet is touching hole1
|
||||
Matter.Body.setPosition(bullet[i], Vector.add(mech.hole.pos1, Vector.sub(mech.hole.pos2, bullet[i].position)));
|
||||
mech.fieldRange += 5
|
||||
bullet[i].isInHole = true
|
||||
}
|
||||
}
|
||||
}
|
||||
//suck and shrink blocks
|
||||
const suckRange = 500
|
||||
const shrinkRange = 100
|
||||
@@ -2354,6 +2329,13 @@ const mech = {
|
||||
body.splice(i, 1);
|
||||
mech.fieldRange *= 0.8
|
||||
if (mod.isWormholeEnergy && mech.energy < mech.maxEnergy * 3) mech.energy = mech.maxEnergy * 3
|
||||
if (mod.isWormSpores) { //pandimensionalspermia
|
||||
b.spore(Vector.add(mech.hole.pos2, Vector.rotate({
|
||||
x: mech.fieldRange,
|
||||
y: 0
|
||||
}, 2 * Math.PI * Math.random())))
|
||||
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(mech.hole.unit, -Math.PI / 2), 15));
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -2370,15 +2352,37 @@ const mech = {
|
||||
body.splice(i, 1);
|
||||
mech.fieldRange *= 0.8
|
||||
if (mod.isWormholeEnergy && mech.energy < mech.maxEnergy * 3) mech.energy = mech.maxEnergy * 3
|
||||
if (mod.isWormSpores) { //pandimensionalspermia
|
||||
b.spore(Vector.add(mech.hole.pos1, Vector.rotate({
|
||||
x: mech.fieldRange,
|
||||
y: 0
|
||||
}, 2 * Math.PI * Math.random())))
|
||||
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(mech.hole.unit, Math.PI / 2), 15));
|
||||
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//mobs get pushed away
|
||||
if (mod.isWormBullets) {
|
||||
//teleport bullets
|
||||
for (let i = 0, len = bullet.length; i < len; ++i) { //teleport bullets from hole1 to hole2
|
||||
if (!bullet[i].botType && !bullet[i].isInHole) { //don't teleport bots
|
||||
if (Vector.magnitude(Vector.sub(mech.hole.pos1, bullet[i].position)) < mech.fieldRange) { //find if bullet is touching hole1
|
||||
Matter.Body.setPosition(bullet[i], Vector.add(mech.hole.pos2, Vector.sub(mech.hole.pos1, bullet[i].position)));
|
||||
mech.fieldRange += 5
|
||||
bullet[i].isInHole = true
|
||||
} else if (Vector.magnitude(Vector.sub(mech.hole.pos2, bullet[i].position)) < mech.fieldRange) { //find if bullet is touching hole1
|
||||
Matter.Body.setPosition(bullet[i], Vector.add(mech.hole.pos1, Vector.sub(mech.hole.pos2, bullet[i].position)));
|
||||
mech.fieldRange += 5
|
||||
bullet[i].isInHole = true
|
||||
}
|
||||
}
|
||||
}
|
||||
// mobs get pushed away
|
||||
for (let i = 0, len = mob.length; i < len; i++) {
|
||||
// if (!mob[i].shield && !mob[i].isShielded) {
|
||||
if (Vector.magnitude(Vector.sub(mech.hole.pos1, mob[i].position)) < 200) {
|
||||
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos1, mob[i].position)), -0.07)
|
||||
Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
|
||||
@@ -2387,28 +2391,19 @@ const mech = {
|
||||
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos2, mob[i].position)), -0.07)
|
||||
Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mech.isHolding) {
|
||||
mech.drawHold(mech.holdingTarget);
|
||||
mech.holding();
|
||||
mech.throwBlock();
|
||||
} else if ((input.field && mech.fieldCDcycle < mech.cycle)) { //not hold but field button is pressed
|
||||
// Matter.Query.ray(map, jumpSensor.position, game.mouseInGame).length === 0 ||
|
||||
if (
|
||||
mech.hole.isReady && !mech.holdingTarget &&
|
||||
(
|
||||
// Matter.Query.ray(map, player.position, game.mouseInGame).length === 0 &&
|
||||
Matter.Query.ray(map, mech.pos, game.mouseInGame).length === 0 &&
|
||||
Matter.Query.ray(map, mech.pos, Vector.add(Vector.mult(Vector.normalise(Vector.sub(game.mouseInGame, mech.pos)), 50), game.mouseInGame)).length === 0
|
||||
)
|
||||
if (input.field && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed
|
||||
if (mech.hole.isReady &&
|
||||
(Matter.Query.ray(map, mech.pos, game.mouseInGame).length === 0 &&
|
||||
Matter.Query.ray(map, mech.pos, Vector.add(Vector.mult(Vector.normalise(Vector.sub(game.mouseInGame, mech.pos)), 50), game.mouseInGame)).length === 0)
|
||||
) {
|
||||
const sub = Vector.sub(game.mouseInGame, mech.pos)
|
||||
const mag = Vector.magnitude(sub)
|
||||
const drain = 0.06 + 0.007 * Math.sqrt(mag)
|
||||
if (mech.energy > drain && mag > 150) {
|
||||
if (mech.energy > drain && mag > 300) {
|
||||
mech.energy -= drain
|
||||
mech.hole.isReady = false;
|
||||
mech.fieldRange = 0
|
||||
@@ -2439,6 +2434,8 @@ const mech = {
|
||||
mech.hole.pos1.y = mech.pos.y
|
||||
mech.hole.pos2.x = player.position.x
|
||||
mech.hole.pos2.y = player.position.y
|
||||
mech.hole.angle = Math.atan2(sub.y, sub.x)
|
||||
mech.hole.unit = Vector.perp(Vector.normalise(sub))
|
||||
|
||||
if (mod.isWormholeDamage) {
|
||||
who = Matter.Query.ray(mob, mech.pos, game.mouseInGame, 60)
|
||||
@@ -2457,14 +2454,12 @@ const mech = {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mech.grabPowerUp();
|
||||
}
|
||||
} else {
|
||||
mech.grabPowerUp();
|
||||
}
|
||||
// mech.grabPowerUp();
|
||||
// mech.lookForPickUp(); can't pick things up with this field
|
||||
// if (mech.energy > 0.05) { //can't use shield
|
||||
// mech.drawField();
|
||||
// mech.pushMobsFacing();
|
||||
// }
|
||||
} else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
|
||||
mech.pickUp();
|
||||
} else {
|
||||
|
||||
@@ -461,8 +461,8 @@ const powerUps = {
|
||||
},
|
||||
randomPowerUpCounter: 0,
|
||||
spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades
|
||||
// if (game.difficultyMode === 4) powerUps.spawn(x, y, "mod") //why mode gets a free mod
|
||||
powerUps.randomPowerUpCounter++;
|
||||
if (game.difficultyMode === 4) powerUps.spawn(x, y, "mod") //why mode gets a free mod
|
||||
const chanceToFail = Math.max(level.levelsCleared, 10) * 0.1 //1 until level 10, then 1.1, 1.2, 1.3, ...
|
||||
if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) {
|
||||
powerUps.randomPowerUpCounter = 0;
|
||||
@@ -470,6 +470,16 @@ const powerUps = {
|
||||
} else {
|
||||
spawnHealthAmmo()
|
||||
}
|
||||
if (game.difficultyMode === 4) {
|
||||
powerUps.randomPowerUpCounter++;
|
||||
const chanceToFail = Math.max(level.levelsCleared, 10) * 0.1 //1 until level 10, then 1.1, 1.2, 1.3, ...
|
||||
if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) {
|
||||
powerUps.randomPowerUpCounter = 0;
|
||||
spawnPowerUps()
|
||||
} else {
|
||||
spawnHealthAmmo()
|
||||
}
|
||||
}
|
||||
|
||||
function spawnHealthAmmo() {
|
||||
if (mech.health < 0.65 && !mod.isEnergyHealth) {
|
||||
@@ -511,7 +521,7 @@ const powerUps = {
|
||||
//bonus power ups for clearing runs in the last game
|
||||
if (level.levelsCleared === 0 && !game.isCheating) {
|
||||
for (let i = 0; i < localSettings.levelsClearedLastGame / 4 - 1; i++) {
|
||||
powerUps.spawn(mech.pos.x, mech.pos.y, "mod", false); //spawn a mod for every 5 levels cleared in last game
|
||||
powerUps.spawn(mech.pos.x, mech.pos.y, "mod", false); //spawn a mod for levels cleared in last game
|
||||
}
|
||||
localSettings.levelsClearedLastGame = 0 //after getting bonus power ups reset run history
|
||||
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
|
||||
|
||||
29
todo.txt
29
todo.txt
@@ -1,33 +1,30 @@
|
||||
some wormhole bug fixes
|
||||
wormhole mod: cosmic string - damage mobs when you teleport through them
|
||||
wormhole mod: Penrose process - overfill energy to 300% of max, with a block gets sucked into a hole
|
||||
|
||||
mod: critical bifurcation - nail gun does 400% more damage if it hits very close to the center of a mob
|
||||
mod: supercritical fission - flechettes explode if they hit very close to the center of a mob
|
||||
|
||||
mod: transdimensional spores - after wormholes eat blocks, they disturb spores
|
||||
mod: traversable geodesics - your bullets can go through worm holes
|
||||
|
||||
scrap bots now only last only 30 seconds, but they have a 20% chance to spawn from a kill (was 11%)
|
||||
the difficulty should feel a bit harder after clearing the boss level
|
||||
(a bit more more damage taken, and fewer mod drops)
|
||||
|
||||
************** TODO - n-gon **************
|
||||
|
||||
set mouse 4 and 5 for gun switch
|
||||
mod - after a mob or shield dies, remaining dots look for a new nearby host
|
||||
|
||||
add an ending to the game
|
||||
revamp the boss level, or add a new final level
|
||||
final level requires you to kill something, not skip content
|
||||
final level requires you to kill something
|
||||
so skipping content is only smart if you are strong enough to beat the final boss
|
||||
around level 15
|
||||
game never ends if you have used cheats
|
||||
|
||||
field wormhole
|
||||
store constant info about the holes: unit, angle to save processing
|
||||
maybe bullets should be able to enter and exit multiple times
|
||||
or bullets shouldn't get stuck at all?
|
||||
maybe give bullets an attraction to holes
|
||||
player: drain energy when near a hole, does damage if no energy
|
||||
mod: Hawking radiation: do damage, to mobs that get near the end points
|
||||
this is good because it explains why mobs don't teleport
|
||||
mod: extend immunity cycle after a teleport //mech.immuneCycle = mech.cycle + 15;
|
||||
|
||||
look for mods that could update description text with count and mod.is information
|
||||
can only use variables that change in effect() and remove()
|
||||
this.description = `<strong>8%</strong> chance to <strong>duplicate</strong> spawned <strong>power ups</strong><br><em>chance to duplicate = ${mod.duplicateChance}</em>`
|
||||
|
||||
mod (drones or spores) explode after 10 seconds
|
||||
mod self destruct - drones explode when they die, but they last 1/2 as long
|
||||
|
||||
mouse event e.which is deprecated
|
||||
|
||||
|
||||
Reference in New Issue
Block a user