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:
landgreen
2020-10-20 17:23:47 -07:00
parent fb13945879
commit 0c2285b1c7
8 changed files with 221 additions and 142 deletions

View File

@@ -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() {},

View File

@@ -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,

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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