wave beam damage works better vs. high mass mobs
  also more damage and ammo

mod plasma torch: extruder - plasma torch ejects a thin hot wire, does more damage, but drains more energy

mod: Bose Einstein condensate - freeze mobs inside your field
  pilot wave, negative mass field, time dilation field

difficulty - after you clear the finalBoss, difficulty increase per level is now lower
  but, when the finalBoss dies difficulty immediately increases greatly

  difficulty used to work like this:
  (+1 per level) 0,1,2,3,4,5,6,7,8,9,10, (final boss dies)
  (+2,3,4 per level) 12,14,16,19,22,25,29,33,37,41, (final boss dies)
  (+4 per level) 44,48,52,56 ...

  difficulty works like this now:
  (+1 per level) 0,1,2,3,4,5,6,7,8,9,10, (final boss dies +5)
  (+2 per level) 17,19,21,23,25,27,29,31,33,35, (final boss dies +5)
  (+3 per level) 43,46,49,52 ...

  difficulty mode scales these numbers
  easy: x1,  normal: x2,  hard: x4,  why: x6

  each time difficulty increases:
    game.dmgScale = 0.38 * game.difficulty //damage done by mobs increases each level
    b.dmgScale *= 0.93; // your damage goes down
    game.healScale = 1 / (1 + game.difficulty * 0.06) //healing goes down
    if (game.accelScale < 5) game.accelScale *= 1.02 //mob acceleration increases each level, but is capped
    if (game.lookFreqScale > 0.2) game.lookFreqScale *= 0.98 //mob cycles between looks decreases each level, but is capped
    if (game.CDScale > 0.2) game.CDScale *= 0.97 //mob ability cooldown time decreases each level, but is capped
This commit is contained in:
landgreen
2020-12-13 14:41:07 -08:00
parent b6cf21dee9
commit 92c5670369
6 changed files with 435 additions and 229 deletions

View File

@@ -678,6 +678,262 @@ const b = {
}); });
World.add(engine.world, bullet[me]); //add bullet to world World.add(engine.world, bullet[me]); //add bullet to world
}, },
lastAngle: 0,
extruder() {
const color = "#f07"
const DRAIN = 0.00014 + mech.fieldRegen
if (mech.energy > DRAIN) {
mech.energy -= DRAIN
if (mech.energy < 0) {
mech.fieldCDcycle = mech.cycle + 120;
mech.energy = 0;
}
ctx.lineWidth = 5;
ctx.strokeStyle = color
ctx.beginPath(); //draw all the wave bullets
for (let i = 0, len = bullet.length; i < len; i++) {
if (bullet[i].isBranch) {
ctx.stroke();
ctx.beginPath(); //draw all the wave bullets
} else if (bullet[i].isWave) ctx.lineTo(bullet[i].position.x, bullet[i].position.y)
}
ctx.lineTo(mech.pos.x + 15 * Math.cos(mech.angle), mech.pos.y + 15 * Math.sin(mech.angle))
ctx.stroke();
} else {
mech.fireCDcycle = mech.cycle + 60; // cool down
for (let i = 0, len = bullet.length; i < len; i++) { //remove all bullets
if (bullet[i].isWave) {
bullet[i].isWave = false
bullet[i].endCycle = 0
}
}
return
}
const SPEED = 13
const me = bullet.length;
const where = Vector.add(mech.pos, player.velocity)
bullet[me] = Bodies.polygon(where.x + 20 * Math.cos(mech.angle), where.y + 20 * Math.sin(mech.angle), 3, 0.01, {
cycle: -0.5,
isWave: true,
endCycle: game.cycle + 50 * mod.isPlasmaRange,
inertia: Infinity,
frictionAir: 0,
isInHole: true, //this keeps the bullet from entering wormholes
minDmgSpeed: 0,
dmg: b.dmgScale * 1.4, //damage also changes when you divide by mob.mass on in .do()
isJustReflected: false,
classType: "bullet",
isBranch: false,
restitution: 0,
collisionFilter: {
// category: 0,
// mask: 0, //cat.mob | cat.mobBullet | cat.mobShield
category: cat.bullet,
mask: cat.map, //cat.mob | cat.mobBullet | cat.mobShield
},
beforeDmg() {},
onEnd() {},
do() {
mech.fireCDcycle = mech.cycle //this is here to trigger cloaking field
if (!input.field) {
this.endCycle = 0;
this.isWave = false
return
}
if (!mech.isBodiesAsleep) {
if (this.endCycle < game.cycle + 1) this.isWave = false
if (Matter.Query.point(map, this.position).length) { //check if inside map
this.isBranch = true;
// for (let i = 0, len = bullet.length; i < len; i++) { //remove all bullets
// if (bullet[i].isWave && bullet[i].cycle > this.cycle) {
// bullet[i].isWave = false
// bullet[i].endCycle = 0
// }
// }
} else { //check if inside a body
const q = Matter.Query.point(mob, this.position)
for (let i = 0; i < q.length; i++) {
Matter.Body.setVelocity(q[i], {
x: q[i].velocity.x * 0.7,
y: q[i].velocity.y * 0.7
});
Matter.Body.setPosition(this, Vector.add(this.position, q[i].velocity)) //move with the medium
let dmg = this.dmg / Math.min(10, q[i].mass)
q[i].damage(dmg);
q[i].foundPlayer();
game.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: Math.log(2 * dmg + 1.4) * 40,
color: color,
time: game.drawTime
});
}
}
this.cycle++
const wiggleMag = (mech.crouch ? 6 : 12) * Math.cos(game.cycle * 0.09)
const wiggle = Vector.mult(transverse, wiggleMag * Math.cos(this.cycle * 0.36)) //+ wiggleMag * Math.cos(game.cycle * 0.3))
const velocity = Vector.mult(player.velocity, 0.3) //move with player
Matter.Body.setPosition(this, Vector.add(velocity, Vector.add(this.position, wiggle)))
// Matter.Body.setPosition(this, Vector.add(this.position, wiggle))
}
}
});
World.add(engine.world, bullet[me]); //add bullet to world
Matter.Body.setVelocity(bullet[me], {
x: SPEED * Math.cos(mech.angle),
y: SPEED * Math.sin(mech.angle)
});
const transverse = Vector.normalise(Vector.perp(bullet[me].velocity))
const angleDifference = 180 - Math.abs(Math.abs(b.lastAngle - mech.angle) - 180); //find the difference between current and previous angle
b.lastAngle = mech.angle
if (angleDifference > 0.5) { //don't draw stroke for this bullet
bullet[me].isBranch = true;
// for (let i = 0, len = bullet.length; i < len; i++) { //remove all bullets
// if (bullet[i].isWave) {
// bullet[i].isWave = false
// bullet[i].endCycle = 0
// }
// }
// return
}
},
plasma() {
const DRAIN = 0.00008 + mech.fieldRegen
if (mech.energy > DRAIN) {
mech.energy -= DRAIN;
if (mech.energy < 0) {
mech.fieldCDcycle = mech.cycle + 120;
mech.energy = 0;
}
//calculate laser collision
let best;
let range = mod.isPlasmaRange * (120 + (mech.crouch ? 400 : 300) * Math.sqrt(Math.random())) //+ 100 * Math.sin(mech.cycle * 0.3);
// const dir = mech.angle // + 0.04 * (Math.random() - 0.5)
const path = [{
x: mech.pos.x + 20 * Math.cos(mech.angle),
y: mech.pos.y + 20 * Math.sin(mech.angle)
},
{
x: mech.pos.x + range * Math.cos(mech.angle),
y: mech.pos.y + range * Math.sin(mech.angle)
}
];
const vertexCollision = function(v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices;
const len = vertices.length - 1;
for (let j = 0; j < len; j++) {
results = game.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
if (results.onLine1 && results.onLine2) {
const dx = v1.x - results.x;
const dy = v1.y - results.y;
const dist2 = dx * dx + dy * dy;
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
best = {
x: results.x,
y: results.y,
dist2: dist2,
who: domain[i],
v1: vertices[j],
v2: vertices[j + 1]
};
}
}
}
results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
if (results.onLine1 && results.onLine2) {
const dx = v1.x - results.x;
const dy = v1.y - results.y;
const dist2 = dx * dx + dy * dy;
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
best = {
x: results.x,
y: results.y,
dist2: dist2,
who: domain[i],
v1: vertices[0],
v2: vertices[len]
};
}
}
}
};
//check for collisions
best = {
x: null,
y: null,
dist2: Infinity,
who: null,
v1: null,
v2: null
};
vertexCollision(path[0], path[1], mob);
vertexCollision(path[0], path[1], map);
vertexCollision(path[0], path[1], body);
if (best.dist2 != Infinity) { //if hitting something
path[path.length - 1] = {
x: best.x,
y: best.y
};
if (best.who.alive) {
const dmg = 0.8 * b.dmgScale; //********** SCALE DAMAGE HERE *********************
best.who.damage(dmg);
best.who.locatePlayer();
//push mobs away
const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.01 * Math.min(5, best.who.mass))
Matter.Body.applyForce(best.who, path[1], force)
Matter.Body.setVelocity(best.who, { //friction
x: best.who.velocity.x * 0.7,
y: best.who.velocity.y * 0.7
});
//draw mob damage circle
game.drawList.push({
x: path[1].x,
y: path[1].y,
radius: Math.sqrt(dmg) * 50,
color: "rgba(255,0,255,0.2)",
time: game.drawTime * 4
});
} else if (!best.who.isStatic) {
//push blocks away
const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.007 * Math.sqrt(Math.sqrt(best.who.mass)))
Matter.Body.applyForce(best.who, path[1], force)
}
}
//draw blowtorch laser beam
ctx.strokeStyle = "rgba(255,0,255,0.1)"
ctx.lineWidth = 14
ctx.beginPath();
ctx.moveTo(path[0].x, path[0].y);
ctx.lineTo(path[1].x, path[1].y);
ctx.stroke();
ctx.strokeStyle = "#f0f";
ctx.lineWidth = 2
ctx.stroke();
//draw electricity
const Dx = Math.cos(mech.angle);
const Dy = Math.sin(mech.angle);
let x = mech.pos.x + 20 * Dx;
let y = mech.pos.y + 20 * Dy;
ctx.beginPath();
ctx.moveTo(x, y);
const step = Vector.magnitude(Vector.sub(path[0], path[1])) / 10
for (let i = 0; i < 8; i++) {
x += step * (Dx + 1.5 * (Math.random() - 0.5))
y += step * (Dy + 1.5 * (Math.random() - 0.5))
ctx.lineTo(x, y);
}
ctx.lineWidth = 2 * Math.random();
ctx.stroke();
}
},
laser(where = { laser(where = {
x: mech.pos.x + 20 * Math.cos(mech.angle), x: mech.pos.x + 20 * Math.cos(mech.angle),
y: mech.pos.y + 20 * Math.sin(mech.angle) y: mech.pos.y + 20 * Math.sin(mech.angle)
@@ -2565,7 +2821,7 @@ const b = {
frictionAir: 0, frictionAir: 0,
slow: 0, slow: 0,
minDmgSpeed: 0, minDmgSpeed: 0,
dmg: 0, dmg: b.dmgScale * (mod.waveHelix === 1 ? 0.6 : 0.75), //control damage also when you divide by mob.mass
isJustReflected: false, isJustReflected: false,
classType: "bullet", classType: "bullet",
collisionFilter: { collisionFilter: {
@@ -2580,7 +2836,7 @@ const b = {
// check if inside a mob // check if inside a mob
q = Matter.Query.point(mob, this.position) q = Matter.Query.point(mob, this.position)
for (let i = 0; i < q.length; i++) { for (let i = 0; i < q.length; i++) {
let dmg = b.dmgScale * 0.4 / Math.sqrt(q[i].mass) * (mod.waveHelix === 1 ? 1 : 0.8) //1 - 0.4 = 0.6 for helix mod 40% damage reduction let dmg = this.dmg / Math.min(10, q[i].mass)
q[i].damage(dmg); q[i].damage(dmg);
q[i].foundPlayer(); q[i].foundPlayer();
game.drawList.push({ //add dmg to draw queue game.drawList.push({ //add dmg to draw queue
@@ -2613,7 +2869,7 @@ const b = {
for (let i = 0; i < q.length; i++) { for (let i = 0; i < q.length; i++) {
slowCheck = 0.3; slowCheck = 0.3;
Matter.Body.setPosition(this, Vector.add(this.position, q[i].velocity)) //move with the medium Matter.Body.setPosition(this, Vector.add(this.position, q[i].velocity)) //move with the medium
let dmg = b.dmgScale * 0.4 / Math.sqrt(q[i].mass) * (mod.waveHelix === 1 ? 1 : 0.8) //1 - 0.4 = 0.6 for helix mod 40% damage reduction let dmg = this.dmg / Math.min(10, q[i].mass)
q[i].damage(dmg); q[i].damage(dmg);
q[i].foundPlayer(); q[i].foundPlayer();
game.drawList.push({ //add dmg to draw queue game.drawList.push({ //add dmg to draw queue
@@ -2632,6 +2888,8 @@ const b = {
} }
} }
this.cycle++ this.cycle++
//6 * Math.cos(this.cycle * 0.1) +
// Math.cos(game.cycle * 0.09) *
const wiggle = Vector.mult(transverse, wiggleMag * Math.cos(this.cycle * 0.35) * ((i % 2) ? -1 : 1)) const wiggle = Vector.mult(transverse, wiggleMag * Math.cos(this.cycle * 0.35) * ((i % 2) ? -1 : 1))
Matter.Body.setPosition(this, Vector.add(this.position, wiggle)) Matter.Body.setPosition(this, Vector.add(this.position, wiggle))
} }

View File

@@ -13,15 +13,15 @@ const level = {
start() { start() {
if (level.levelsCleared === 0) { //this code only runs on the first level if (level.levelsCleared === 0) { //this code only runs on the first level
// game.enableConstructMode() //used to build maps in testing mode // game.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(99) // level.difficultyIncrease(19)
// game.zoomScale = 1000; // game.zoomScale = 1000;
// game.setZoom(); // game.setZoom();
// mech.setField("wormhole") // mech.setField("plasma torch")
// b.giveGuns("grenades") // b.giveGuns("wave beam")
// mod.isIncendiary = true // mod.giveMod("micro-extruder")
// mod.is3Missiles = true // for (let i = 0; i < 15; i++) mod.giveMod("supply chain")
// mod.giveMod("neutron bomb")
// mod.giveMod("causality bombs")
level.intro(); //starting level level.intro(); //starting level
// level.testing(); //not in rotation // level.testing(); //not in rotation
@@ -155,8 +155,8 @@ const level = {
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
// spawn.boost(1500, 0, 900); // spawn.boost(1500, 0, 900);
// spawn.starter(1900, -500, 320) spawn.starter(1900, -500, 200)
spawn.exploder(2900, -500) // spawn.exploder(2900, -500)
// spawn.launcherBoss(1200, -500) // spawn.launcherBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400) // spawn.laserTargetingBoss(1600, -400)
// spawn.striker(1600, -500) // spawn.striker(1600, -500)
@@ -3805,11 +3805,12 @@ const level = {
}, },
nextLevel() { nextLevel() {
if (level.bossKilled) level.levelsCleared++; if (level.bossKilled) level.levelsCleared++;
level.difficultyIncrease(game.difficultyMode) //increase difficulty based on modes // 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) //difficulty is increased 5 times when finalBoss dies
if (level.levelsCleared > level.levels.length * 1.5) level.difficultyIncrease(game.difficultyMode) const len = level.levelsCleared / level.levels.length //add 1 extra difficulty step for each time you have cleared all the levels
if (level.levelsCleared > level.levels.length * 2) level.difficultyIncrease(game.difficultyMode) for (let i = 0; i < len; i++) level.difficultyIncrease(game.difficultyMode)
level.onLevel++; //cycles map to next level level.onLevel++; //cycles map to next level
if (level.onLevel > level.levels.length - 1) level.onLevel = 0; if (level.onLevel > level.levels.length - 1) level.onLevel = 0;
//reset lost mod display //reset lost mod display

View File

@@ -6,6 +6,12 @@ const mod = {
mod.mods[i].isLost = false mod.mods[i].isLost = false
mod.mods[i].count = 0 mod.mods[i].count = 0
} }
// mod.nailBotCount = 0;
// mod.foamBotCount = 0;
// mod.boomBotCount = 0;
// mod.laserBotCount = 0;
// mod.orbitalBotCount = 0;
// mod.plasmaBotCount = 0;
mod.armorFromPowerUps = 0; mod.armorFromPowerUps = 0;
mod.totalCount = 0; mod.totalCount = 0;
game.updateModHUD(); game.updateModHUD();
@@ -46,6 +52,14 @@ const mod = {
game.updateModHUD(); game.updateModHUD();
} }
}, },
setModToNonRefundable(name) {
for (let i = 0; i < mod.mods.length; i++) {
if (mod.mods.name === name) {
mod.mods[i].isNonRefundable = true;
return
}
}
},
// giveBasicMod(index = 'random') { // giveBasicMod(index = 'random') {
// // if (isNaN(index)) { //find index by name // // if (isNaN(index)) { //find index by name
// // let found = false; // // let found = false;
@@ -92,7 +106,7 @@ const mod = {
if (mod.isEnergyLoss) dmg *= 1.5; if (mod.isEnergyLoss) dmg *= 1.5;
if (mod.isAcidDmg && mech.health > 1) dmg *= 1.4; if (mod.isAcidDmg && mech.health > 1) dmg *= 1.4;
if (mod.restDamage > 1 && player.speed < 1) dmg *= mod.restDamage if (mod.restDamage > 1 && player.speed < 1) dmg *= mod.restDamage
if (mod.isEnergyDamage) dmg *= 1 + mech.energy / 7; if (mod.isEnergyDamage) dmg *= 1 + mech.energy / 8;
if (mod.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.0038 if (mod.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.0038
if (mod.isRerollDamage) dmg *= 1 + 0.04 * powerUps.reroll.rerolls if (mod.isRerollDamage) dmg *= 1 + 0.04 * powerUps.reroll.rerolls
if (mod.isOneGun && b.inventory.length < 2) dmg *= 1.25 if (mod.isOneGun && b.inventory.length < 2) dmg *= 1.25
@@ -109,7 +123,7 @@ const mod = {
}, },
mods: [{ mods: [{
name: "capacitor", name: "capacitor",
description: "increase <strong class='color-d'>damage</strong> by <strong>1%</strong><br>for every <strong>7</strong> stored <strong class='color-f'>energy</strong>", description: "increase <strong class='color-d'>damage</strong> by <strong>1%</strong><br>for every <strong>8</strong> stored <strong class='color-f'>energy</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
@@ -1028,7 +1042,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return mod.isStunField || mod.isPulseStun || mod.oneSuperBall || mod.isHarmFreeze || mod.isIceField || mod.isIceCrystals || mod.isSporeFreeze || mod.isAoESlow || mod.isFreezeMobs || mod.isPilotFreeze || mod.haveGunCheck("ice IX") || mod.isCloakStun || mod.orbitBotCount > 1 || mod.isWormholeDamage return mod.isStunField || mod.isPulseStun || mod.oneSuperBall || mod.isHarmFreeze || mod.isIceField || mod.isIceCrystals || mod.isSporeFreeze || mod.isAoESlow || mod.isFreezeMobs || mod.haveGunCheck("ice IX") || mod.isCloakStun || mod.orbitBotCount > 1 || mod.isWormholeDamage
}, },
requires: "a freezing or stunning effect", requires: "a freezing or stunning effect",
effect() { effect() {
@@ -1145,7 +1159,7 @@ const mod = {
allowed() { allowed() {
return !mod.isEnergyLoss && !mod.isPiezo && !mod.isRewindAvoidDeath && !mod.isSpeedHarm && mech.fieldUpgrades[mech.fieldMode].name !== "negative mass field" return !mod.isEnergyLoss && !mod.isPiezo && !mod.isRewindAvoidDeath && !mod.isSpeedHarm && mech.fieldUpgrades[mech.fieldMode].name !== "negative mass field"
}, },
requires: "not piezoelectricity, acute stress response, 1st law, negative mass field", requires: "not exothermic process, piezoelectricity, CPT, 1st law, negative mass field",
effect: () => { effect: () => {
mech.health = 0 mech.health = 0
// mech.displayHealth(); // mech.displayHealth();
@@ -1428,9 +1442,9 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return mod.duplicationChance() > 0 && !mod.isDeterminism return !mod.isDeterminism
}, },
requires: "a chance to duplicate power ups, not determinism", requires: "not determinism",
effect() { effect() {
mod.isCancelDuplication = true mod.isCancelDuplication = true
mod.cancelCount = 0 mod.cancelCount = 0
@@ -1823,7 +1837,6 @@ const mod = {
//remove active bullets //to get rid of bots //remove active bullets //to get rid of bots
for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]); for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]);
bullet = []; bullet = [];
let count = 0 //count mods let count = 0 //count mods
for (let i = 0, len = mod.mods.length; i < len; i++) { // spawn new mods power ups for (let i = 0, len = mod.mods.length; i < len; i++) { // spawn new mods power ups
if (!mod.mods[i].isNonRefundable) count += mod.mods[i].count if (!mod.mods[i].isNonRefundable) count += mod.mods[i].count
@@ -2304,7 +2317,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return mod.haveGunCheck("wave beam") return mod.haveGunCheck("wave beam") && !mod.isExtruder
}, },
requires: "wave beam", requires: "wave beam",
effect() { effect() {
@@ -2320,7 +2333,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return mod.haveGunCheck("wave beam") && !mod.isWaveReflect return mod.haveGunCheck("wave beam") && !mod.isWaveReflect && !mod.isExtruder
}, },
requires: "wave beam", requires: "wave beam",
effect() { effect() {
@@ -2338,7 +2351,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return mod.haveGunCheck("wave beam") && mod.waveSpeedMap !== 3 return mod.haveGunCheck("wave beam") && mod.waveSpeedMap !== 3 && !mod.isExtruder
}, },
requires: "wave beam", requires: "wave beam",
effect() { effect() {
@@ -3128,36 +3141,46 @@ const mod = {
mech.energy = 0.01; mech.energy = 0.01;
//fill array of available bots //fill array of available bots
const notUpgradedBots = [] const notUpgradedBots = []
if (!mod.isNailBotUpgrade) { if (!mod.isNailBotUpgrade) notUpgradedBots.push(() => {
notUpgradedBots.push(() => { mod.giveMod("nail-bot upgrade")
mod.giveMod("nail-bot upgrade") mod.setModToNonRefundable("nail-bot upgrade")
for (let i = 0; i < 2; i++) mod.giveMod("nail-bot") for (let i = 0; i < 2; i++) {
}) b.nailBot()
} mod.nailBotCount++;
if (!mod.isFoamBotUpgrade) { }
notUpgradedBots.push(() => { })
mod.giveMod("foam-bot upgrade") if (!mod.isFoamBotUpgrade) notUpgradedBots.push(() => {
for (let i = 0; i < 2; i++) mod.giveMod("foam-bot") mod.giveMod("foam-bot upgrade")
}) mod.setModToNonRefundable("foam-bot upgrade")
} for (let i = 0; i < 2; i++) {
if (!mod.isBoomBotUpgrade) { b.foamBot()
notUpgradedBots.push(() => { mod.foamBotCount++;
mod.giveMod("boom-bot upgrade") }
for (let i = 0; i < 2; i++) mod.giveMod("boom-bot") })
}) if (!mod.isBoomBotUpgrade) notUpgradedBots.push(() => {
} mod.giveMod("boom-bot upgrade")
if (!mod.isLaserBotUpgrade) { mod.setModToNonRefundable("boom-bot upgrade")
notUpgradedBots.push(() => { for (let i = 0; i < 2; i++) {
mod.giveMod("laser-bot upgrade") b.boomBot()
for (let i = 0; i < 2; i++) mod.giveMod("laser-bot") mod.boomBotCount++;
}) }
} })
if (!mod.isOrbitBotUpgrade) { if (!mod.isLaserBotUpgrade) notUpgradedBots.push(() => {
notUpgradedBots.push(() => { mod.giveMod("laser-bot upgrade")
mod.giveMod("orbital-bot upgrade") mod.setModToNonRefundable("laser-bot upgrade")
for (let i = 0; i < 2; i++) mod.giveMod("orbital-bot") for (let i = 0; i < 2; i++) {
}) b.laserBot()
} mod.laserBotCount++;
}
})
if (!mod.isOrbitBotUpgrade) notUpgradedBots.push(() => {
mod.giveMod("orbital-bot upgrade")
mod.setModToNonRefundable("orbital-bot upgrade")
for (let i = 0; i < 2; i++) {
b.orbitalBot()
mod.orbitalBotCount++;
}
})
//choose random function from the array and run it //choose random function from the array and run it
notUpgradedBots[Math.floor(Math.random() * notUpgradedBots.length)]() notUpgradedBots[Math.floor(Math.random() * notUpgradedBots.length)]()
}, },
@@ -3225,7 +3248,6 @@ const mod = {
}, },
remove() { remove() {
mod.isHarmReduce = false; mod.isHarmReduce = false;
// if (mech.fieldUpgrades[mech.fieldMode].name === "negative mass field") mech.setField("negative mass field") //reset harm reduction
} }
}, },
{ {
@@ -3245,19 +3267,19 @@ const mod = {
} }
}, },
{ {
name: "negative temperature", name: "Bose Einstein condensate",
description: "<strong>negative mass field</strong> uses <strong class='color-f'>energy</strong><br>to <strong class='color-s'>freeze</strong> each mob caught in it's effect", description: "<strong>mobs</strong> inside your <strong class='color-f'>field</strong> are <strong class='color-s'>frozen</strong><br><em style = 'font-size: 100%'>pilot wave, negative mass, time dilation</em>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return mech.fieldUpgrades[mech.fieldMode].name === "negative mass field" return mech.fieldUpgrades[mech.fieldMode].name === "pilot wave" || mech.fieldUpgrades[mech.fieldMode].name === "negative mass field" || mech.fieldUpgrades[mech.fieldMode].name === "time dilation field"
}, },
requires: "negative mass field", requires: "pilot wave, negative mass field, time dilation field",
effect() { effect() {
mod.isFreezeMobs = true; mod.isFreezeMobs = true
}, },
remove() { remove() {
mod.isFreezeMobs = false; mod.isFreezeMobs = false
} }
}, },
{ {
@@ -3293,6 +3315,22 @@ const mod = {
mod.plasmaBotCount = 0; mod.plasmaBotCount = 0;
} }
}, },
{
name: "micro-extruder",
description: "<strong class='color-plasma'>plasma</strong> torch ejects a thin <strong class='color-plasma'>hot</strong> wire<br>increases <strong class='color-d'>damage</strong>, and <strong class='color-f'>energy</strong> drain",
maxCount: 1,
count: 0,
allowed() {
return mech.fieldUpgrades[mech.fieldMode].name === "plasma torch"
},
requires: "plasma torch",
effect() {
mod.isExtruder = true;
},
remove() {
mod.isExtruder = false;
}
},
{ {
name: "timelike world line", name: "timelike world line",
description: "<strong>time dilation</strong> doubles your relative time <strong>rate</strong><br>and makes you <strong>immune</strong> to <strong class='color-harm'>harm</strong>", description: "<strong>time dilation</strong> doubles your relative time <strong>rate</strong><br>and makes you <strong>immune</strong> to <strong class='color-harm'>harm</strong>",
@@ -3401,22 +3439,6 @@ const mod = {
b.setFireCD(); b.setFireCD();
} }
}, },
{
name: "Bose Einstein condensate",
description: "<strong>mobs</strong> in superposition with the <strong>pilot wave</strong><br>are <strong class='color-s'>frozen</strong> for <strong>2</strong> seconds",
maxCount: 1,
count: 0,
allowed() {
return mech.fieldUpgrades[mech.fieldMode].name === "pilot wave"
},
requires: "pilot wave",
effect() {
mod.isPilotFreeze = true
},
remove() {
mod.isPilotFreeze = false
}
},
{ {
name: "cosmic string", name: "cosmic string",
description: "<strong>stun</strong> and do <strong class='color-p'>radioactive</strong> <strong class='color-d'>damage</strong> to <strong>mobs</strong><br>if you tunnel through them with a <strong class='color-worm'>wormhole</strong>", description: "<strong>stun</strong> and do <strong class='color-p'>radioactive</strong> <strong class='color-d'>damage</strong> to <strong>mobs</strong><br>if you tunnel through them with a <strong class='color-worm'>wormhole</strong>",
@@ -3647,7 +3669,6 @@ const mod = {
isNailPoison: null, isNailPoison: null,
isEnergyHealth: null, isEnergyHealth: null,
isPulseStun: null, isPulseStun: null,
isPilotFreeze: null,
restDamage: null, restDamage: null,
isRPG: null, isRPG: null,
is3Missiles: null, is3Missiles: null,
@@ -3750,5 +3771,6 @@ const mod = {
isMaxEnergyMod: null, isMaxEnergyMod: null,
isLowEnergyDamage: null, isLowEnergyDamage: null,
isRewindBot: null, isRewindBot: null,
isRewindGrenade: null isRewindGrenade: null,
isExtruder: null
} }

View File

@@ -491,7 +491,7 @@ const mech = {
}, },
rewind(steps) { rewind(steps) {
if (mod.isRewindGrenade) { if (mod.isRewindGrenade) {
for (let i = 1, len = Math.floor(1.5 + steps / 40); i < len; i++) { for (let i = 1, len = Math.floor(2 + steps / 40); i < len; i++) {
b.grenade(Vector.add(mech.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -i * Math.PI / len) //fire different angles for each grenade b.grenade(Vector.add(mech.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -i * Math.PI / len) //fire different angles for each grenade
const who = bullet[bullet.length - 1] const who = bullet[bullet.length - 1]
if (mod.isVacuumBomb) { if (mod.isVacuumBomb) {
@@ -1163,6 +1163,8 @@ const mech = {
} else { } else {
mech.drawHold(who); mech.drawHold(who);
} }
// if (mod.isFreezeMobs) mobs.statusSlow(who, 60) //this works but doesn't have a fun effect
// mech.holdingTarget = null // mech.holdingTarget = null
//knock backs //knock backs
if (mech.fieldShieldingScale > 0) { if (mech.fieldShieldingScale > 0) {
@@ -1293,7 +1295,14 @@ const mech = {
} }
} }
} }
wake(mob); if (mod.isFreezeMobs) {
for (let i = 0, len = mob.length; i < len; ++i) {
Matter.Sleeping.set(mob[i], false)
mobs.statusSlow(mob[i], 60)
}
} else {
wake(mob);
}
wake(body); wake(body);
wake(bullet); wake(bullet);
for (let i = 0, len = cons.length; i < len; i++) { for (let i = 0, len = cons.length; i < len; i++) {
@@ -1396,10 +1405,6 @@ const mech = {
effect: () => { effect: () => {
mech.fieldShieldingScale = 0; mech.fieldShieldingScale = 0;
mech.grabPowerUpRange2 = 10000000 mech.grabPowerUpRange2 = 10000000
// mech.holdingMassScale = 0.03; //can hold heavier blocks with lower cost to jumping
// mech.fieldMeterColor = "#0af"
// mech.fieldArc = 0.3; //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
// mech.calculateFieldThreshold();
mech.hold = function() { mech.hold = function() {
const wave = Math.sin(mech.cycle * 0.022); const wave = Math.sin(mech.cycle * 0.022);
mech.fieldRange = 170 + 12 * wave mech.fieldRange = 170 + 12 * wave
@@ -1643,137 +1648,10 @@ const mech = {
} else if (input.field && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed } else if (input.field && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed
mech.grabPowerUp(); mech.grabPowerUp();
mech.lookForPickUp(); mech.lookForPickUp();
const DRAIN = 0.0012 if (mod.isExtruder) {
if (mech.energy > DRAIN) { b.extruder();
mech.energy -= DRAIN; } else {
if (mech.energy < 0) { b.plasma();
mech.fieldCDcycle = mech.cycle + 120;
mech.energy = 0;
}
//calculate laser collision
let best;
let range = mod.isPlasmaRange * (120 + (mech.crouch ? 400 : 300) * Math.sqrt(Math.random())) //+ 100 * Math.sin(mech.cycle * 0.3);
// const dir = mech.angle // + 0.04 * (Math.random() - 0.5)
const path = [{
x: mech.pos.x + 20 * Math.cos(mech.angle),
y: mech.pos.y + 20 * Math.sin(mech.angle)
},
{
x: mech.pos.x + range * Math.cos(mech.angle),
y: mech.pos.y + range * Math.sin(mech.angle)
}
];
const vertexCollision = function(v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices;
const len = vertices.length - 1;
for (let j = 0; j < len; j++) {
results = game.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
if (results.onLine1 && results.onLine2) {
const dx = v1.x - results.x;
const dy = v1.y - results.y;
const dist2 = dx * dx + dy * dy;
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
best = {
x: results.x,
y: results.y,
dist2: dist2,
who: domain[i],
v1: vertices[j],
v2: vertices[j + 1]
};
}
}
}
results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
if (results.onLine1 && results.onLine2) {
const dx = v1.x - results.x;
const dy = v1.y - results.y;
const dist2 = dx * dx + dy * dy;
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
best = {
x: results.x,
y: results.y,
dist2: dist2,
who: domain[i],
v1: vertices[0],
v2: vertices[len]
};
}
}
}
};
//check for collisions
best = {
x: null,
y: null,
dist2: Infinity,
who: null,
v1: null,
v2: null
};
vertexCollision(path[0], path[1], mob);
vertexCollision(path[0], path[1], map);
vertexCollision(path[0], path[1], body);
if (best.dist2 != Infinity) { //if hitting something
path[path.length - 1] = {
x: best.x,
y: best.y
};
if (best.who.alive) {
const dmg = 0.8 * b.dmgScale; //********** SCALE DAMAGE HERE *********************
best.who.damage(dmg);
best.who.locatePlayer();
//push mobs away
const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.01 * Math.min(5, best.who.mass))
Matter.Body.applyForce(best.who, path[1], force)
Matter.Body.setVelocity(best.who, { //friction
x: best.who.velocity.x * 0.7,
y: best.who.velocity.y * 0.7
});
//draw mob damage circle
game.drawList.push({
x: path[1].x,
y: path[1].y,
radius: Math.sqrt(dmg) * 50,
color: "rgba(255,0,255,0.2)",
time: game.drawTime * 4
});
} else if (!best.who.isStatic) {
//push blocks away
const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.007 * Math.sqrt(Math.sqrt(best.who.mass)))
Matter.Body.applyForce(best.who, path[1], force)
}
}
//draw blowtorch laser beam
ctx.strokeStyle = "rgba(255,0,255,0.1)"
ctx.lineWidth = 14
ctx.beginPath();
ctx.moveTo(path[0].x, path[0].y);
ctx.lineTo(path[1].x, path[1].y);
ctx.stroke();
ctx.strokeStyle = "#f0f";
ctx.lineWidth = 2
ctx.stroke();
//draw electricity
const Dx = Math.cos(mech.angle);
const Dy = Math.sin(mech.angle);
let x = mech.pos.x + 20 * Dx;
let y = mech.pos.y + 20 * Dy;
ctx.beginPath();
ctx.moveTo(x, y);
const step = Vector.magnitude(Vector.sub(path[0], path[1])) / 10
for (let i = 0; i < 8; i++) {
x += step * (Dx + 1.5 * (Math.random() - 0.5))
y += step * (Dy + 1.5 * (Math.random() - 0.5))
ctx.lineTo(x, y);
}
ctx.lineWidth = 2 * Math.random();
ctx.stroke();
} }
} else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released } else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
mech.pickUp(); mech.pickUp();
@@ -2270,7 +2148,7 @@ const mech = {
} }
} }
if (mod.isPilotFreeze) { if (mod.isFreezeMobs) {
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
if (Vector.magnitude(Vector.sub(mob[i].position, mech.fieldPosition)) < mech.fieldRadius) { if (Vector.magnitude(Vector.sub(mob[i].position, mech.fieldPosition)) < mech.fieldRadius) {
mobs.statusSlow(mob[i], 120) mobs.statusSlow(mob[i], 120)

View File

@@ -101,6 +101,16 @@ const spawn = {
level.bossKilled = true; level.bossKilled = true;
level.exit.x = 5500; level.exit.x = 5500;
level.exit.y = -330; level.exit.y = -330;
//pull in particles
for (let i = 0, len = body.length; i < len; ++i) { //push blocks away horizontally
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, body[i].position)), 65)
const pushUp = Vector.add(velocity, { x: 0, y: -0.3 })
Matter.Body.setVelocity(body[i], Vector.add(body[i].velocity, pushUp));
}
//ramp up damage
for (let i = 0; i < 5; i++) level.difficultyIncrease(game.difficultyMode)
}; };
me.onDamage = function() {}; me.onDamage = function() {};
me.cycle = 420; me.cycle = 420;
@@ -132,7 +142,7 @@ const spawn = {
Matter.Body.scale(this, 10, 10); Matter.Body.scale(this, 10, 10);
Matter.Body.setDensity(me, density); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, density); //extra dense //normal is 0.001 //makes effective life much larger
if (!this.isShielded) spawn.shield(this, x, y, 1); // regen shield to also prevent stun if (!this.isShielded) spawn.shield(this, x, y, 1); // regen shield to also prevent stun
for (let i = 0, len = body.length; i < len; ++i) { for (let i = 0, len = body.length; i < len; ++i) { //push blocks away horizontally
if (body[i].position.x > this.position.x) { if (body[i].position.x > this.position.x) {
body[i].force.x = 0.5 body[i].force.x = 0.5
} else { } else {

View File

@@ -1,17 +1,43 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** NEXT PATCH ********************************************************
catabolism - 2% (was 2.3%) of max health removed wave beam damage works better vs. high mass mobs
many worlds - spawns 2 rerolls (was 1) also more damage and ammo
pilot wave field- now has access to several mods that normally require other fields
this plus the fragmenting block mod are a big buff for late game pilot wave mod plasma torch: extruder - plasma torch ejects a thin hot wire, does more damage, but drains more energy
let me know if it is too strong
mod: Bose Einstein condensate - freeze mobs inside your field
pilot wave, negative mass field, time dilation field
difficulty - after you clear the finalBoss, difficulty increase per level is now lower
but, when the finalBoss dies difficulty immediately increases greatly
difficulty used to work like this:
(+1 per level) 0,1,2,3,4,5,6,7,8,9,10, (final boss dies)
(+2,3,4 per level) 12,14,16,19,22,25,29,33,37,41, (final boss dies)
(+4 per level) 44,48,52,56 ...
difficulty works like this now:
(+1 per level) 0,1,2,3,4,5,6,7,8,9,10, (final boss dies +5)
(+2 per level) 17,19,21,23,25,27,29,31,33,35, (final boss dies +5)
(+3 per level) 43,46,49,52 ...
difficulty mode scales these numbers
easy: x1, normal: x2, hard: x4, why: x6
each time difficulty increases:
game.dmgScale = 0.38 * game.difficulty //damage done by mobs increases each level
b.dmgScale *= 0.93; // your damage goes down
game.healScale = 1 / (1 + game.difficulty * 0.06) //healing goes down
if (game.accelScale < 5) game.accelScale *= 1.02 //mob acceleration increases each level, but is capped
if (game.lookFreqScale > 0.2) game.lookFreqScale *= 0.98 //mob cycles between looks decreases each level, but is capped
if (game.CDScale > 0.2) game.CDScale *= 0.97 //mob ability cooldown time decreases each level, but is capped
mod nano-scale: bot prototypes - upgrade a bot type and build 2 of that bot
mod nano-scale: bot manufacturing - build 3 random bots
these mods don't show up in custom
******************************************************** BUGS ******************************************************** ******************************************************** BUGS ********************************************************
entering custom, after dieing makes all mods look white (not disabled)
this goes away after clicking something so it seems to be only a graphical issue
(not able to reproduce, might be fixed) possible bug with neutron rewind (not able to reproduce, might be fixed) possible bug with neutron rewind
status doesn't apply correctly for spawned neutron bombs that are stuck to a shield status doesn't apply correctly for spawned neutron bombs that are stuck to a shield
also saw neutron bombs bounce off shield, for normal bullets also saw neutron bombs bounce off shield, for normal bullets
@@ -42,6 +68,17 @@ mod and mob are too similar
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
mod plasma torch: extruder speed is improved
color/highlight field or gun mods in selection menu (or custom)
to show that they are special
mechanic - Your energy regen is only active when field and gun have not been used for 5 seconds.
divide supercapacitator into 2-3 stacks
smaller effect for stack 1, but overall bigger effect at 3
be able to open up custom mode in the normal game be able to open up custom mode in the normal game
might need to be rebuilt from scratch might need to be rebuilt from scratch
while in through testing mode? while in through testing mode?