wormhole
mods ejected from Bayesian statistics can't duplicate the power up boss moves faster, has less health, it will eject one of your mods after a collision and two health power ups mod ammonium nitrate: increase explosion damage and area by 25% also other explosion mods have been rebalanced (damage buffed, but self damage is also higher) field: wormhole - teleport around, bullets teleport too, blocks and power ups get sucked in mobs don't do much in worm hole yet, but that is coming with future mods
This commit is contained in:
10
js/bullet.js
10
js/bullet.js
@@ -165,12 +165,13 @@ const b = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
explosion(where, radius) { // typically explode is used for some bullets with .onEnd
|
explosion(where, radius) { // typically explode is used for some bullets with .onEnd
|
||||||
|
radius *= mod.explosiveRadius
|
||||||
let dist, sub, knock;
|
let dist, sub, knock;
|
||||||
let dmg = radius * 0.013;
|
let dmg = radius * 0.013;
|
||||||
if (mod.isExplosionHarm) radius *= 1.43 // sqrt(2)radius for 2x more area
|
if (mod.isExplosionHarm) radius *= 1.8 // 1/sqrt(2) radius -> area
|
||||||
if (mod.isSmallExplosion) {
|
if (mod.isSmallExplosion) {
|
||||||
radius *= 0.5
|
radius *= 0.8
|
||||||
dmg *= 1.5
|
dmg *= 1.6
|
||||||
}
|
}
|
||||||
|
|
||||||
game.drawList.push({ //add dmg to draw queue
|
game.drawList.push({ //add dmg to draw queue
|
||||||
@@ -197,7 +198,7 @@ const b = {
|
|||||||
if (dist < radius) {
|
if (dist < radius) {
|
||||||
|
|
||||||
if (mod.isImmuneExplosion) {
|
if (mod.isImmuneExplosion) {
|
||||||
const mitigate = Math.min(1, Math.max(1 - mech.energy * 0.6, 0))
|
const mitigate = Math.min(1, Math.max(1 - mech.energy * 0.7, 0))
|
||||||
mech.damage(mitigate * radius * (mod.isExplosionHarm ? 0.0004 : 0.0001));
|
mech.damage(mitigate * radius * (mod.isExplosionHarm ? 0.0004 : 0.0001));
|
||||||
} else {
|
} else {
|
||||||
mech.damage(radius * (mod.isExplosionHarm ? 0.0004 : 0.0001));
|
mech.damage(radius * (mod.isExplosionHarm ? 0.0004 : 0.0001));
|
||||||
@@ -800,7 +801,6 @@ const b = {
|
|||||||
lockedOn: null,
|
lockedOn: null,
|
||||||
isFollowMouse: true,
|
isFollowMouse: true,
|
||||||
onDmg(who) {
|
onDmg(who) {
|
||||||
console.log(who.alive)
|
|
||||||
mobs.statusSlow(who, 60)
|
mobs.statusSlow(who, 60)
|
||||||
this.endCycle = game.cycle
|
this.endCycle = game.cycle
|
||||||
if (mod.isHeavyWater) mobs.statusDoT(who, 0.15, 300)
|
if (mod.isHeavyWater) mobs.statusDoT(who, 0.15, 300)
|
||||||
|
|||||||
26
js/engine.js
26
js/engine.js
@@ -85,16 +85,6 @@ function collisionChecks(event) {
|
|||||||
// if (obj.onWallHit) obj.onWallHit();
|
// if (obj.onWallHit) obj.onWallHit();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
//body + player collision
|
|
||||||
// if (game.isBodyDamage) {
|
|
||||||
// if (pairs[i].bodyA === playerBody || pairs[i].bodyA === playerHead) {
|
|
||||||
// collidePlayer(pairs[i].bodyB)
|
|
||||||
// } else if (pairs[i].bodyB === playerBody || pairs[i].bodyB === playerHead) {
|
|
||||||
// collidePlayer(pairs[i].bodyA)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function collidePlayer(obj) {
|
// function collidePlayer(obj) {
|
||||||
// //player dmg from hitting a body
|
// //player dmg from hitting a body
|
||||||
// if (obj.classType === "body" && obj.speed > 10 && mech.immuneCycle < mech.cycle) {
|
// if (obj.classType === "body" && obj.speed > 10 && mech.immuneCycle < mech.cycle) {
|
||||||
@@ -145,22 +135,8 @@ function collisionChecks(event) {
|
|||||||
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * game.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0
|
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * game.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0
|
||||||
if (mod.isPiezo) mech.energy = mech.maxEnergy;
|
if (mod.isPiezo) mech.energy = mech.maxEnergy;
|
||||||
mech.damage(dmg);
|
mech.damage(dmg);
|
||||||
if (mod.isBayesian) {
|
if (mod.isBayesian) powerUps.ejectMod()
|
||||||
const have = [] //find which mods you have
|
|
||||||
for (let i = 0; i < mod.mods.length; i++) {
|
|
||||||
if (mod.mods[i].count > 0) have.push(i)
|
|
||||||
}
|
|
||||||
const choose = have[Math.floor(Math.random() * have.length)]
|
|
||||||
game.makeTextLog(`<div class='circle mod'></div> <strong>${mod.mods[choose].name}</strong> ejected by Bayesian statistics`, 600) //message about what mod was lost
|
|
||||||
for (let i = 0; i < mod.mods[choose].count; i++) powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
|
|
||||||
mod.mods[choose].remove(); // remove a random mod form the list of mods you have
|
|
||||||
mod.mods[choose].count = 0;
|
|
||||||
mod.mods[choose].isLost = true;
|
|
||||||
game.updateModHUD();
|
|
||||||
mech.fieldCDcycle = mech.cycle + 30; //disable field so you can't pick up the ejected mod
|
|
||||||
}
|
|
||||||
if (mob[k].onHit) mob[k].onHit(k);
|
if (mob[k].onHit) mob[k].onHit(k);
|
||||||
|
|
||||||
//extra kick between player and mob //this section would be better with forces but they don't work...
|
//extra kick between player and mob //this section would be better with forces but they don't work...
|
||||||
let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x);
|
let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x);
|
||||||
Matter.Body.setVelocity(player, {
|
Matter.Body.setVelocity(player, {
|
||||||
|
|||||||
@@ -126,7 +126,6 @@ const game = {
|
|||||||
lastTimeStamp: 0, //tracks time stamps for measuring delta
|
lastTimeStamp: 0, //tracks time stamps for measuring delta
|
||||||
delta: 1000 / 60, //speed of game engine //looks like it has to be 16 to match player input
|
delta: 1000 / 60, //speed of game engine //looks like it has to be 16 to match player input
|
||||||
buttonCD: 0,
|
buttonCD: 0,
|
||||||
isBodyDamage: true,
|
|
||||||
levelsCleared: 0,
|
levelsCleared: 0,
|
||||||
difficultyMode: 1,
|
difficultyMode: 1,
|
||||||
isEasyMode: false,
|
isEasyMode: false,
|
||||||
@@ -472,6 +471,7 @@ const game = {
|
|||||||
mech.maxHealth = 1
|
mech.maxHealth = 1
|
||||||
mech.maxEnergy = 1
|
mech.maxEnergy = 1
|
||||||
mech.energy = 1
|
mech.energy = 1
|
||||||
|
mech.hole.isOn = false
|
||||||
game.paused = false;
|
game.paused = false;
|
||||||
engine.timing.timeScale = 1;
|
engine.timing.timeScale = 1;
|
||||||
game.fpsCap = game.fpsCapDefault;
|
game.fpsCap = game.fpsCapDefault;
|
||||||
@@ -559,7 +559,7 @@ const game = {
|
|||||||
if (game.isCommunityMaps) {
|
if (game.isCommunityMaps) {
|
||||||
level.levels.push("stronghold");
|
level.levels.push("stronghold");
|
||||||
level.levels.push("basement");
|
level.levels.push("basement");
|
||||||
level.levels.push("newLevel");
|
level.levels.push("detours");
|
||||||
level.levels.push("house");
|
level.levels.push("house");
|
||||||
}
|
}
|
||||||
level.levels = shuffle(level.levels); //shuffles order of maps
|
level.levels = shuffle(level.levels); //shuffles order of maps
|
||||||
@@ -607,6 +607,7 @@ const game = {
|
|||||||
|
|
||||||
mech.fireCDcycle = 0
|
mech.fireCDcycle = 0
|
||||||
mech.drop();
|
mech.drop();
|
||||||
|
mech.hole.isOn = false;
|
||||||
level.fill = [];
|
level.fill = [];
|
||||||
level.fillBG = [];
|
level.fillBG = [];
|
||||||
level.zones = [];
|
level.zones = [];
|
||||||
|
|||||||
12
js/index.js
12
js/index.js
@@ -871,7 +871,13 @@ document.body.addEventListener("wheel", (e) => {
|
|||||||
//**********************************************************************
|
//**********************************************************************
|
||||||
let localSettings = JSON.parse(localStorage.getItem("localSettings"));
|
let localSettings = JSON.parse(localStorage.getItem("localSettings"));
|
||||||
if (localSettings) {
|
if (localSettings) {
|
||||||
input.key = localSettings.key
|
if (localSettings.key) {
|
||||||
|
input.key = localSettings.key
|
||||||
|
} else {
|
||||||
|
input.setDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
game.isCommunityMaps = localSettings.isCommunityMaps
|
game.isCommunityMaps = localSettings.isCommunityMaps
|
||||||
document.getElementById("community-maps").checked = localSettings.isCommunityMaps
|
document.getElementById("community-maps").checked = localSettings.isCommunityMaps
|
||||||
game.difficultyMode = localSettings.difficultyMode
|
game.difficultyMode = localSettings.difficultyMode
|
||||||
@@ -883,15 +889,15 @@ if (localSettings) {
|
|||||||
}
|
}
|
||||||
document.getElementById("fps-select").value = localSettings.fpsCapDefault
|
document.getElementById("fps-select").value = localSettings.fpsCapDefault
|
||||||
} else {
|
} else {
|
||||||
input.setDefault()
|
|
||||||
localSettings = {
|
localSettings = {
|
||||||
isCommunityMaps: false,
|
isCommunityMaps: false,
|
||||||
difficultyMode: '1',
|
difficultyMode: '1',
|
||||||
fpsCapDefault: 'max',
|
fpsCapDefault: 'max',
|
||||||
runCount: 0,
|
runCount: 0,
|
||||||
levelsClearedLastGame: 0,
|
levelsClearedLastGame: 0,
|
||||||
key: input.key
|
key: undefined
|
||||||
};
|
};
|
||||||
|
input.setDefault()
|
||||||
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
|
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
|
||||||
document.getElementById("community-maps").checked = localSettings.isCommunityMaps
|
document.getElementById("community-maps").checked = localSettings.isCommunityMaps
|
||||||
game.isCommunityMaps = localSettings.isCommunityMaps
|
game.isCommunityMaps = localSettings.isCommunityMaps
|
||||||
|
|||||||
56
js/level.js
56
js/level.js
@@ -15,7 +15,7 @@ const level = {
|
|||||||
// game.zoomScale = 1000;
|
// game.zoomScale = 1000;
|
||||||
// game.setZoom();
|
// game.setZoom();
|
||||||
// mech.isCloak = true;
|
// mech.isCloak = true;
|
||||||
// mech.setField("perfect diamagnetism")
|
mech.setField("wormhole")
|
||||||
// b.giveGuns("nail gun")
|
// b.giveGuns("nail gun")
|
||||||
// for (let i = 0; i < 10; i++) {
|
// for (let i = 0; i < 10; i++) {
|
||||||
// mod.giveMod("laser-bot");
|
// mod.giveMod("laser-bot");
|
||||||
@@ -37,7 +37,7 @@ const level = {
|
|||||||
// level.office();
|
// level.office();
|
||||||
// level.bosses(); //only fighting, very simple map
|
// level.bosses(); //only fighting, very simple map
|
||||||
// level.house() //fan level
|
// level.house() //fan level
|
||||||
// level.newLevel() //fan level
|
// level.detours() //fan level
|
||||||
// level.basement(); //fan level
|
// level.basement(); //fan level
|
||||||
// level.stronghold() //fan level
|
// level.stronghold() //fan level
|
||||||
} else {
|
} else {
|
||||||
@@ -141,7 +141,7 @@ 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(1600, -500)
|
// spawn.starter(1600, -500)
|
||||||
// spawn.bomberBoss(2900, -500)
|
// spawn.bomberBoss(2900, -500)
|
||||||
// spawn.launcherBoss(1200, -500)
|
// spawn.launcherBoss(1200, -500)
|
||||||
// spawn.laserTargetingBoss(1600, -400)
|
// spawn.laserTargetingBoss(1600, -400)
|
||||||
@@ -151,7 +151,7 @@ const level = {
|
|||||||
// spawn.sniper(1800, -120)
|
// spawn.sniper(1800, -120)
|
||||||
// spawn.sniper(2200, -120)
|
// spawn.sniper(2200, -120)
|
||||||
// spawn.cellBossCulture(1600, -500)
|
// spawn.cellBossCulture(1600, -500)
|
||||||
// spawn.powerUpBoss(1600, -500)
|
spawn.powerUpBoss(1600, -500)
|
||||||
// spawn.shield(mob[mob.length - 1], 1200, -500, 1);
|
// spawn.shield(mob[mob.length - 1], 1200, -500, 1);
|
||||||
|
|
||||||
// spawn.nodeBoss(1200, -500, "launcher")
|
// spawn.nodeBoss(1200, -500, "launcher")
|
||||||
@@ -2821,7 +2821,7 @@ const level = {
|
|||||||
powerUps.spawn(3010, 1630, "mod");
|
powerUps.spawn(3010, 1630, "mod");
|
||||||
powerUps.spawn(3100, 1630, "heal");
|
powerUps.spawn(3100, 1630, "heal");
|
||||||
},
|
},
|
||||||
newLevel() {
|
detours() {
|
||||||
level.setPosToSpawn(0, 0); //lower start
|
level.setPosToSpawn(0, 0); //lower start
|
||||||
level.exit.y = 150;
|
level.exit.y = 150;
|
||||||
spawn.mapRect(level.enter.x, 45, 100, 20);
|
spawn.mapRect(level.enter.x, 45, 100, 20);
|
||||||
@@ -4365,33 +4365,33 @@ const level = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (body.length) {
|
// if (body.length) {
|
||||||
for (let i = 0, len = body.length; i < len; i++) {
|
for (let i = 0, len = body.length; i < len; i++) {
|
||||||
if (body[i] !== mech.holdingTarget) {
|
if (body[i] !== mech.holdingTarget) {
|
||||||
// body[i].bounds.max.x - body[i].bounds.min.x < 100 && body[i].bounds.max.y - body[i].bounds.min.y < 100
|
// body[i].bounds.max.x - body[i].bounds.min.x < 100 && body[i].bounds.max.y - body[i].bounds.min.y < 100
|
||||||
if (Matter.Query.collides(this, [body[i]]).length === 0) {
|
if (Matter.Query.collides(this, [body[i]]).length === 0) {
|
||||||
if (body[i].isInPortal === this) body[i].isInPortal = null
|
if (body[i].isInPortal === this) body[i].isInPortal = null
|
||||||
} else if (body[i].isInPortal !== this) {
|
} else if (body[i].isInPortal !== this) {
|
||||||
body[i].isInPortal = this.portalPair
|
body[i].isInPortal = this.portalPair
|
||||||
//teleport
|
//teleport
|
||||||
if (this.portalPair.angle % (Math.PI / 2)) { //if left, right up or down
|
if (this.portalPair.angle % (Math.PI / 2)) { //if left, right up or down
|
||||||
Matter.Body.setPosition(body[i], this.portalPair.portal.position);
|
Matter.Body.setPosition(body[i], this.portalPair.portal.position);
|
||||||
} else { //if at some odd angle
|
} else { //if at some odd angle
|
||||||
Matter.Body.setPosition(body[i], this.portalPair.position);
|
Matter.Body.setPosition(body[i], this.portalPair.position);
|
||||||
}
|
|
||||||
//rotate velocity
|
|
||||||
let mag
|
|
||||||
if (this.portalPair.angle !== 0 && this.portalPair.angle !== Math.PI) { //portal that fires the player up
|
|
||||||
mag = Math.max(10, Math.min(50, body[i].velocity.y * 0.8)) + 11
|
|
||||||
} else {
|
|
||||||
mag = Math.max(6, Math.min(50, Vector.magnitude(body[i].velocity)))
|
|
||||||
}
|
|
||||||
let v = Vector.mult(this.portalPair.unit, mag)
|
|
||||||
Matter.Body.setVelocity(body[i], v);
|
|
||||||
}
|
}
|
||||||
|
//rotate velocity
|
||||||
|
let mag
|
||||||
|
if (this.portalPair.angle !== 0 && this.portalPair.angle !== Math.PI) { //portal that fires the player up
|
||||||
|
mag = Math.max(10, Math.min(50, body[i].velocity.y * 0.8)) + 11
|
||||||
|
} else {
|
||||||
|
mag = Math.max(6, Math.min(50, Vector.magnitude(body[i].velocity)))
|
||||||
|
}
|
||||||
|
let v = Vector.mult(this.portalPair.unit, mag)
|
||||||
|
Matter.Body.setVelocity(body[i], v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
|
|
||||||
//remove block if touching
|
//remove block if touching
|
||||||
// if (body.length) {
|
// if (body.length) {
|
||||||
|
|||||||
41
js/mods.js
41
js/mods.js
@@ -403,8 +403,24 @@ const mod = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "trinitrotoluene",
|
name: "ammonium nitrate",
|
||||||
description: "increase <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>50%</strong><br>decrease <strong class='color-e'>explosive</strong> <strong>area</strong> by <strong>71%</strong>",
|
description: "increase <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>20%</strong><br>increase <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>20%</strong>",
|
||||||
|
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;
|
||||||
|
},
|
||||||
|
requires: "an explosive damage source",
|
||||||
|
effect: () => {
|
||||||
|
mod.explosiveRadius += 0.2;
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
mod.explosiveRadius = 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nitroglycerin",
|
||||||
|
description: "increase <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>60%</strong><br>decrease <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>20%</strong>",
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
allowed() {
|
allowed() {
|
||||||
@@ -419,8 +435,8 @@ const mod = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ammonium nitrate",
|
name: "acetone peroxide",
|
||||||
description: "increase <strong class='color-e'>explosive</strong> <strong>area</strong> by <strong>100%</strong>, but<br>you take <strong>400%</strong> more <strong class='color-harm'>harm</strong> from <strong class='color-e'>explosions</strong>",
|
description: "increase <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>80%</strong>, but<br>you take <strong>400%</strong> more <strong class='color-harm'>harm</strong> from <strong class='color-e'>explosions</strong>",
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
allowed() {
|
allowed() {
|
||||||
@@ -437,7 +453,7 @@ const mod = {
|
|||||||
{
|
{
|
||||||
name: "electric reactive armor",
|
name: "electric reactive armor",
|
||||||
// description: "<strong class='color-e'>explosions</strong> do no <strong class='color-harm'>harm</strong><br> while your <strong class='color-f'>energy</strong> is above <strong>98%</strong>",
|
// description: "<strong class='color-e'>explosions</strong> do no <strong class='color-harm'>harm</strong><br> while your <strong class='color-f'>energy</strong> is above <strong>98%</strong>",
|
||||||
description: "<strong class='color-harm'>harm</strong> from <strong class='color-e'>explosions</strong> is passively reduced<br>by <strong>6%</strong> for every <strong>10</strong> stored <strong class='color-f'>energy</strong>",
|
description: "<strong class='color-harm'>harm</strong> from <strong class='color-e'>explosions</strong> is passively reduced<br>by <strong>7%</strong> for every <strong>10</strong> stored <strong class='color-f'>energy</strong>",
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
allowed() {
|
allowed() {
|
||||||
@@ -1192,7 +1208,7 @@ const mod = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Bayesian statistics",
|
name: "Bayesian statistics",
|
||||||
description: "<strong>17%</strong> chance to <strong>duplicate</strong> spawned <strong>power ups</strong><br>after a <strong>collision</strong>, <strong>eject</strong> one of your <strong class='color-m'>mods</strong>",
|
description: "<strong>20%</strong> chance to <strong>duplicate</strong> spawned <strong>power ups</strong><br>after a <strong>collision</strong>, <strong>eject</strong> one of your <strong class='color-m'>mods</strong>",
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
allowed() {
|
allowed() {
|
||||||
@@ -1201,13 +1217,13 @@ const mod = {
|
|||||||
requires: "",
|
requires: "",
|
||||||
effect: () => {
|
effect: () => {
|
||||||
mod.isBayesian = true
|
mod.isBayesian = true
|
||||||
mod.duplicateChance += 0.17
|
mod.duplicateChance += 0.2
|
||||||
game.draw.powerUp = game.draw.powerUpBonus //change power up draw
|
game.draw.powerUp = game.draw.powerUpBonus //change power up draw
|
||||||
|
|
||||||
},
|
},
|
||||||
remove() {
|
remove() {
|
||||||
if (mod.isBayesian) {
|
if (mod.isBayesian) {
|
||||||
mod.duplicateChance -= 0.17
|
mod.duplicateChance -= 0.2
|
||||||
if (mod.duplicateChance < 0) mod.duplicateChance = 0
|
if (mod.duplicateChance < 0) mod.duplicateChance = 0
|
||||||
}
|
}
|
||||||
mod.isBayesian = false
|
mod.isBayesian = false
|
||||||
@@ -1226,12 +1242,12 @@ const mod = {
|
|||||||
effect() {
|
effect() {
|
||||||
mod.duplicateChance += 0.08
|
mod.duplicateChance += 0.08
|
||||||
game.draw.powerUp = game.draw.powerUpBonus //change power up draw
|
game.draw.powerUp = game.draw.powerUpBonus //change power up draw
|
||||||
this.description = `<strong>8%</strong> chance to <strong>duplicate</strong> spawned <strong>power ups</strong><br><em>chance to duplicate = ${mod.duplicateChance}</em>`
|
// this.description = `<strong>8%</strong> chance to <strong>duplicate</strong> spawned <strong>power ups</strong><br><em>chance to duplicate = ${mod.duplicateChance}</em>`
|
||||||
},
|
},
|
||||||
remove() {
|
remove() {
|
||||||
mod.duplicateChance -= 0.08 * this.count
|
mod.duplicateChance -= 0.08 * this.count
|
||||||
if (mod.duplicateChance === 0) game.draw.powerUp = game.draw.powerUpNormal
|
if (mod.duplicateChance === 0) game.draw.powerUp = game.draw.powerUpNormal
|
||||||
this.description = `<strong>8%</strong> chance to <strong>duplicate</strong> spawned <strong>power ups</strong><br><em>chance to duplicate = ${mod.duplicateChance}</em>`
|
// this.description = `<strong>8%</strong> chance to <strong>duplicate</strong> spawned <strong>power ups</strong><br><em>chance to duplicate = ${mod.duplicateChance}</em>`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1604,7 +1620,7 @@ const mod = {
|
|||||||
allowed() {
|
allowed() {
|
||||||
return mod.haveGunCheck("nail gun") && mod.nailFireRate && !mod.isIceCrystals
|
return mod.haveGunCheck("nail gun") && mod.nailFireRate && !mod.isIceCrystals
|
||||||
},
|
},
|
||||||
requires: "nail gun",
|
requires: "nail gun and pneumatic actuator",
|
||||||
effect() {
|
effect() {
|
||||||
mod.nailInstantFireRate = true
|
mod.nailInstantFireRate = true
|
||||||
},
|
},
|
||||||
@@ -3023,5 +3039,6 @@ const mod = {
|
|||||||
duplicateChance: null,
|
duplicateChance: null,
|
||||||
beamSplitter: null,
|
beamSplitter: null,
|
||||||
iceEnergy: null,
|
iceEnergy: null,
|
||||||
isPerfectBrake: null
|
isPerfectBrake: null,
|
||||||
|
explosiveRadius: null
|
||||||
}
|
}
|
||||||
258
js/player.js
258
js/player.js
@@ -107,7 +107,6 @@ const mech = {
|
|||||||
Sy: 0, //adds a smoothing effect to vertical only
|
Sy: 0, //adds a smoothing effect to vertical only
|
||||||
Vx: 0,
|
Vx: 0,
|
||||||
Vy: 0,
|
Vy: 0,
|
||||||
|
|
||||||
friction: {
|
friction: {
|
||||||
ground: 0.01,
|
ground: 0.01,
|
||||||
air: 0.0025
|
air: 0.0025
|
||||||
@@ -222,19 +221,18 @@ const mech = {
|
|||||||
},
|
},
|
||||||
buttonCD_jump: 0, //cool down for player buttons
|
buttonCD_jump: 0, //cool down for player buttons
|
||||||
groundControl() {
|
groundControl() {
|
||||||
|
//check for crouch or jump
|
||||||
if (mech.crouch) {
|
if (mech.crouch) {
|
||||||
if (!(input.down) && mech.checkHeadClear() && mech.hardLandCD < mech.cycle) mech.undoCrouch();
|
if (!(input.down) && mech.checkHeadClear() && mech.hardLandCD < mech.cycle) mech.undoCrouch();
|
||||||
} else if (input.down || mech.hardLandCD > mech.cycle) {
|
} else if (input.down || mech.hardLandCD > mech.cycle) {
|
||||||
mech.doCrouch(); //on ground && not crouched and pressing s or down
|
mech.doCrouch(); //on ground && not crouched and pressing s or down
|
||||||
} else if ((input.up) && mech.buttonCD_jump + 20 < mech.cycle && mech.yOffWhen.stand > 23) {
|
} else if ((input.up) && mech.buttonCD_jump + 20 < mech.cycle && mech.yOffWhen.stand > 23) {
|
||||||
mech.buttonCD_jump = mech.cycle; //can't jump again until 20 cycles pass
|
mech.buttonCD_jump = mech.cycle; //can't jump again until 20 cycles pass
|
||||||
|
|
||||||
//apply a fraction of the jump force to the body the player is jumping off of
|
//apply a fraction of the jump force to the body the player is jumping off of
|
||||||
Matter.Body.applyForce(mech.standingOn, mech.pos, {
|
Matter.Body.applyForce(mech.standingOn, mech.pos, {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: mech.jumpForce * 0.12 * Math.min(mech.standingOn.mass, 5)
|
y: mech.jumpForce * 0.12 * Math.min(mech.standingOn.mass, 5)
|
||||||
});
|
});
|
||||||
|
|
||||||
player.force.y = -mech.jumpForce; //player jump force
|
player.force.y = -mech.jumpForce; //player jump force
|
||||||
Matter.Body.setVelocity(player, { //zero player y-velocity for consistent jumps
|
Matter.Body.setVelocity(player, { //zero player y-velocity for consistent jumps
|
||||||
x: player.velocity.x,
|
x: player.velocity.x,
|
||||||
@@ -243,9 +241,6 @@ const mech = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (input.left) {
|
if (input.left) {
|
||||||
// if (game.mouseDownRight && mech.fieldCDcycle < mech.cycle && !mech.crouch) {
|
|
||||||
// blink(-1)
|
|
||||||
// } else {
|
|
||||||
if (player.velocity.x > -2) {
|
if (player.velocity.x > -2) {
|
||||||
player.force.x -= mech.Fx * 1.5
|
player.force.x -= mech.Fx * 1.5
|
||||||
} else {
|
} else {
|
||||||
@@ -253,15 +248,11 @@ const mech = {
|
|||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
} else if (input.right) {
|
} else if (input.right) {
|
||||||
// if (game.mouseDownRight && mech.fieldCDcycle < mech.cycle && !mech.crouch) {
|
|
||||||
// blink(1)
|
|
||||||
// } else {
|
|
||||||
if (player.velocity.x < 2) {
|
if (player.velocity.x < 2) {
|
||||||
player.force.x += mech.Fx * 1.5
|
player.force.x += mech.Fx * 1.5
|
||||||
} else {
|
} else {
|
||||||
player.force.x += mech.Fx
|
player.force.x += mech.Fx
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
} else {
|
} else {
|
||||||
const stoppingFriction = 0.92;
|
const stoppingFriction = 0.92;
|
||||||
Matter.Body.setVelocity(player, {
|
Matter.Body.setVelocity(player, {
|
||||||
@@ -728,6 +719,18 @@ const mech = {
|
|||||||
fieldFire: false,
|
fieldFire: false,
|
||||||
fieldHarmReduction: 1,
|
fieldHarmReduction: 1,
|
||||||
holdingMassScale: 0,
|
holdingMassScale: 0,
|
||||||
|
hole: {
|
||||||
|
isOn: false,
|
||||||
|
isReady: true,
|
||||||
|
pos1: {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
},
|
||||||
|
pos2: {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
},
|
||||||
|
},
|
||||||
fieldArc: 0,
|
fieldArc: 0,
|
||||||
fieldThreshold: 0,
|
fieldThreshold: 0,
|
||||||
calculateFieldThreshold() {
|
calculateFieldThreshold() {
|
||||||
@@ -739,7 +742,6 @@ const mech = {
|
|||||||
mech.fieldMeterColor = "#0cf"
|
mech.fieldMeterColor = "#0cf"
|
||||||
mech.fieldShieldingScale = 1;
|
mech.fieldShieldingScale = 1;
|
||||||
mech.fieldBlockCD = 10;
|
mech.fieldBlockCD = 10;
|
||||||
game.isBodyDamage = true;
|
|
||||||
mech.fieldHarmReduction = 1;
|
mech.fieldHarmReduction = 1;
|
||||||
mech.fieldDamage = 1
|
mech.fieldDamage = 1
|
||||||
mech.grabPowerUpRange2 = 156000;
|
mech.grabPowerUpRange2 = 156000;
|
||||||
@@ -757,6 +759,18 @@ const mech = {
|
|||||||
mech.isBodiesAsleep = true;
|
mech.isBodiesAsleep = true;
|
||||||
mech.wakeCheck();
|
mech.wakeCheck();
|
||||||
mech.setMaxEnergy();
|
mech.setMaxEnergy();
|
||||||
|
mech.hole = {
|
||||||
|
isOn: false,
|
||||||
|
isReady: true,
|
||||||
|
pos1: {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
},
|
||||||
|
pos2: {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setMaxEnergy() {
|
setMaxEnergy() {
|
||||||
mech.maxEnergy = 1 + mod.bonusEnergy + mod.healMaxEnergyBonus
|
mech.maxEnergy = 1 + mod.bonusEnergy + mod.healMaxEnergyBonus
|
||||||
@@ -996,8 +1010,8 @@ const mech = {
|
|||||||
if (dist2 < 5000 && !game.isChoosing) { //use power up if it is close enough
|
if (dist2 < 5000 && !game.isChoosing) { //use power up if it is close enough
|
||||||
powerUps.onPickUp(mech.pos);
|
powerUps.onPickUp(mech.pos);
|
||||||
Matter.Body.setVelocity(player, { //player knock back, after grabbing power up
|
Matter.Body.setVelocity(player, { //player knock back, after grabbing power up
|
||||||
x: player.velocity.x + ((powerUp[i].velocity.x * powerUp[i].mass) / player.mass) * 0.3,
|
x: player.velocity.x + powerUp[i].velocity.x / player.mass * 5,
|
||||||
y: player.velocity.y + ((powerUp[i].velocity.y * powerUp[i].mass) / player.mass) * 0.3
|
y: player.velocity.y + powerUp[i].velocity.y / player.mass * 5
|
||||||
});
|
});
|
||||||
powerUp[i].effect();
|
powerUp[i].effect();
|
||||||
Matter.World.remove(engine.world, powerUp[i]);
|
Matter.World.remove(engine.world, powerUp[i]);
|
||||||
@@ -1544,7 +1558,7 @@ const mech = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "plasma torch",
|
name: "plasma torch",
|
||||||
description: "use <strong class='color-f'>energy</strong> to emit short range <strong class='color-plasma'>plasma</strong><br><strong class='color-d'>damages</strong> mobs<br><strong>pushes</strong> mobs and blocks away",
|
description: "use <strong class='color-f'>energy</strong> to emit short range <strong class='color-plasma'>plasma</strong><br><strong class='color-d'>damages</strong> and <strong>pushes</strong> mobs away",
|
||||||
effect() {
|
effect() {
|
||||||
mech.fieldMeterColor = "#f0f"
|
mech.fieldMeterColor = "#f0f"
|
||||||
mech.hold = function () {
|
mech.hold = function () {
|
||||||
@@ -2069,7 +2083,6 @@ const mech = {
|
|||||||
description: "use <strong class='color-f'>energy</strong> to push <strong>blocks</strong> with your mouse<br>field <strong>radius</strong> decreases out of <strong>line of sight</strong>",
|
description: "use <strong class='color-f'>energy</strong> to push <strong>blocks</strong> with your mouse<br>field <strong>radius</strong> decreases out of <strong>line of sight</strong>",
|
||||||
effect: () => {
|
effect: () => {
|
||||||
game.replaceTextLog = true; //allow text over write
|
game.replaceTextLog = true; //allow text over write
|
||||||
game.isBodyDamage = false;
|
|
||||||
mech.fieldPhase = 0;
|
mech.fieldPhase = 0;
|
||||||
mech.fieldPosition = {
|
mech.fieldPosition = {
|
||||||
x: game.mouseInGame.x,
|
x: game.mouseInGame.x,
|
||||||
@@ -2225,5 +2238,220 @@ 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 the <strong class='color-worm'>wormholes</strong><br>blocks and power ups can't exit it",
|
||||||
|
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
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
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
|
||||||
|
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);
|
||||||
|
ctx.lineTo(edge2b.x, edge2b.y)
|
||||||
|
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.fillStyle = `rgba(255,255,255,${32 / mech.fieldRange})`
|
||||||
|
ctx.fill();
|
||||||
|
|
||||||
|
//suck power ups
|
||||||
|
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||||
|
//which hole is closer
|
||||||
|
const dxP1 = mech.hole.pos1.x - powerUp[i].position.x;
|
||||||
|
const dyP1 = mech.hole.pos1.y - powerUp[i].position.y;
|
||||||
|
const dxP2 = mech.hole.pos2.x - powerUp[i].position.x;
|
||||||
|
const dyP2 = mech.hole.pos2.y - powerUp[i].position.y;
|
||||||
|
let dxP, dyP, dist2
|
||||||
|
if (dxP1 * dxP1 + dyP1 * dyP1 < dxP2 * dxP2 + dyP2 * dyP2) {
|
||||||
|
dxP = dxP1
|
||||||
|
dyP = dyP1
|
||||||
|
} else {
|
||||||
|
dxP = dxP2
|
||||||
|
dyP = dyP2
|
||||||
|
}
|
||||||
|
dist2 = dxP * dxP + dyP * dyP;
|
||||||
|
if (dist2 < 600000 && !(mech.health === mech.maxHealth && powerUp[i].name === "heal")) {
|
||||||
|
powerUp[i].force.x += 4 * (dxP / dist2) * powerUp[i].mass; // float towards hole
|
||||||
|
powerUp[i].force.y += 4 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * game.g; //negate gravity
|
||||||
|
Matter.Body.setVelocity(powerUp[i], { //extra friction
|
||||||
|
x: powerUp[i].velocity.x * 0.05,
|
||||||
|
y: powerUp[i].velocity.y * 0.05
|
||||||
|
});
|
||||||
|
if (dist2 < 1000 && !game.isChoosing) { //use power up if it is close enough
|
||||||
|
mech.fieldRange *= 0.8
|
||||||
|
powerUps.onPickUp(powerUp[i].position);
|
||||||
|
powerUp[i].effect();
|
||||||
|
Matter.World.remove(engine.world, powerUp[i]);
|
||||||
|
powerUp.splice(i, 1);
|
||||||
|
break; //because the array order is messed up after splice
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//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
|
||||||
|
const shrinkScale = 0.97;
|
||||||
|
const slowScale = 0.9
|
||||||
|
for (let i = 0, len = body.length; i < len; i++) {
|
||||||
|
if (!body[i].isNotHoldable) {
|
||||||
|
const dist1 = Vector.magnitude(Vector.sub(mech.hole.pos1, body[i].position))
|
||||||
|
const dist2 = Vector.magnitude(Vector.sub(mech.hole.pos2, body[i].position))
|
||||||
|
if (dist1 < dist2) {
|
||||||
|
if (dist1 < suckRange) {
|
||||||
|
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos1, body[i].position)), 1)
|
||||||
|
const slow = Vector.mult(body[i].velocity, slowScale)
|
||||||
|
Matter.Body.setVelocity(body[i], Vector.add(slow, pull));
|
||||||
|
//shrink
|
||||||
|
if (Vector.magnitude(Vector.sub(mech.hole.pos1, body[i].position)) < shrinkRange) {
|
||||||
|
Matter.Body.scale(body[i], shrinkScale, shrinkScale);
|
||||||
|
if (body[i].mass < 0.05) {
|
||||||
|
Matter.World.remove(engine.world, body[i]);
|
||||||
|
body.splice(i, 1);
|
||||||
|
mech.fieldRange *= 0.8
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (dist2 < suckRange) {
|
||||||
|
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos2, body[i].position)), 1)
|
||||||
|
const slow = Vector.mult(body[i].velocity, slowScale)
|
||||||
|
Matter.Body.setVelocity(body[i], Vector.add(slow, pull));
|
||||||
|
//shrink
|
||||||
|
if (Vector.magnitude(Vector.sub(mech.hole.pos2, body[i].position)) < shrinkRange) {
|
||||||
|
Matter.Body.scale(body[i], shrinkScale, shrinkScale);
|
||||||
|
if (body[i].mass < 0.05) {
|
||||||
|
Matter.World.remove(engine.world, body[i]);
|
||||||
|
body.splice(i, 1);
|
||||||
|
mech.fieldRange *= 0.8
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//mobs get sucked in
|
||||||
|
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)) < suckRange) {
|
||||||
|
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos1, mob[i].position)), 0.05)
|
||||||
|
const slow = Vector.mult(mob[i].velocity, 0.99)
|
||||||
|
Matter.Body.setVelocity(mob[i], Vector.add(slow, pull));
|
||||||
|
}
|
||||||
|
if (Vector.magnitude(Vector.sub(mech.hole.pos2, mob[i].position)) < suckRange) {
|
||||||
|
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos2, mob[i].position)), 0.05)
|
||||||
|
const slow = Vector.mult(mob[i].velocity, 0.99)
|
||||||
|
Matter.Body.setVelocity(mob[i], Vector.add(slow, 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)
|
||||||
|
) {
|
||||||
|
const sub = Vector.sub(game.mouseInGame, mech.pos)
|
||||||
|
const mag = Vector.magnitude(sub)
|
||||||
|
const drain = 0.005 * Math.sqrt(mag)
|
||||||
|
if (mech.energy > drain && mag > 150) {
|
||||||
|
mech.energy -= drain
|
||||||
|
mech.hole.isReady = false;
|
||||||
|
mech.fieldRange = 0
|
||||||
|
Matter.Body.setPosition(player, game.mouseInGame);
|
||||||
|
const velocity = Vector.mult(Vector.normalise(sub), 18)
|
||||||
|
Matter.Body.setVelocity(player, {
|
||||||
|
x: velocity.x,
|
||||||
|
y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer
|
||||||
|
});
|
||||||
|
mech.immuneCycle = mech.cycle + 15; //player is immune to collision damage for 30 cycles
|
||||||
|
// move bots to follow player
|
||||||
|
for (let i = 0; i < bullet.length; i++) {
|
||||||
|
if (bullet[i].botType) {
|
||||||
|
Matter.Body.setPosition(bullet[i], Vector.add(player.position, {
|
||||||
|
x: 250 * (Math.random() - 0.5),
|
||||||
|
y: 250 * (Math.random() - 0.5)
|
||||||
|
}));
|
||||||
|
Matter.Body.setVelocity(bullet[i], {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//set holes
|
||||||
|
mech.hole.isOn = true;
|
||||||
|
mech.hole.pos1.x = mech.pos.x
|
||||||
|
mech.hole.pos1.y = mech.pos.y
|
||||||
|
mech.hole.pos2.x = player.position.x
|
||||||
|
mech.hole.pos2.y = player.position.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 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 {
|
||||||
|
mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
|
||||||
|
mech.hole.isReady = true;
|
||||||
|
}
|
||||||
|
mech.drawFieldMeter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@@ -541,6 +541,27 @@ const powerUps = {
|
|||||||
powerUps.spawnRandomPowerUp(x, y);
|
powerUps.spawnRandomPowerUp(x, y);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
ejectMod() {
|
||||||
|
//find which mods you have
|
||||||
|
const have = []
|
||||||
|
for (let i = 0; i < mod.mods.length; i++) {
|
||||||
|
if (mod.mods[i].count > 0) have.push(i)
|
||||||
|
}
|
||||||
|
if (have.length) {
|
||||||
|
const choose = have[Math.floor(Math.random() * have.length)]
|
||||||
|
game.makeTextLog(`<div class='circle mod'></div> <strong>${mod.mods[choose].name}</strong> ejected by Bayesian statistics`, 600) //message about what mod was lost
|
||||||
|
for (let i = 0; i < mod.mods[choose].count; i++) {
|
||||||
|
powerUps.directSpawn(mech.pos.x, mech.pos.y, "mod");
|
||||||
|
powerUp[powerUp.length - 1].isBonus = true
|
||||||
|
}
|
||||||
|
// remove a random mod from the list of mods you have
|
||||||
|
mod.mods[choose].remove();
|
||||||
|
mod.mods[choose].count = 0;
|
||||||
|
mod.mods[choose].isLost = true;
|
||||||
|
game.updateModHUD();
|
||||||
|
mech.fieldCDcycle = mech.cycle + 30; //disable field so you can't pick up the ejected mod
|
||||||
|
}
|
||||||
|
},
|
||||||
directSpawn(x, y, target, moving = true, mode = null, size = powerUps[target].size()) {
|
directSpawn(x, y, target, moving = true, mode = null, size = powerUps[target].size()) {
|
||||||
let index = powerUp.length;
|
let index = powerUp.length;
|
||||||
target = powerUps[target];
|
target = powerUps[target];
|
||||||
|
|||||||
65
js/spawn.js
65
js/spawn.js
@@ -231,13 +231,13 @@ const spawn = {
|
|||||||
mobs.spawn(x, y, vertices, radius, "transparent");
|
mobs.spawn(x, y, vertices, radius, "transparent");
|
||||||
let me = mob[mob.length - 1];
|
let me = mob[mob.length - 1];
|
||||||
me.isBoss = true;
|
me.isBoss = true;
|
||||||
me.frictionAir = 0.025
|
me.frictionAir = 0.01
|
||||||
me.seeAtDistance2 = 9000000;
|
me.seeAtDistance2 = 9000000;
|
||||||
me.accelMag = 0.0005 * game.accelScale;
|
me.accelMag = 0.00062 * game.accelScale;
|
||||||
Matter.Body.setDensity(me, 0.002); //normal is 0.001
|
Matter.Body.setDensity(me, 0.001); //normal is 0.001
|
||||||
me.collisionFilter.mask = cat.bullet | cat.player
|
me.collisionFilter.mask = cat.bullet | cat.player
|
||||||
me.memory = Infinity;
|
me.memory = Infinity;
|
||||||
me.seePlayerFreq = 85 + Math.floor(10 * Math.random())
|
me.seePlayerFreq = 60
|
||||||
|
|
||||||
me.lockedOn = null;
|
me.lockedOn = null;
|
||||||
if (vertices === 9) {
|
if (vertices === 9) {
|
||||||
@@ -248,7 +248,11 @@ const spawn = {
|
|||||||
} else if (!mech.isCloak) {
|
} else if (!mech.isCloak) {
|
||||||
me.foundPlayer();
|
me.foundPlayer();
|
||||||
}
|
}
|
||||||
|
me.onHit = function () { //run this function on hitting player
|
||||||
|
powerUps.ejectMod()
|
||||||
|
powerUps.spawn(mech.pos.x, mech.pos.y, "heal");
|
||||||
|
powerUps.spawn(mech.pos.x, mech.pos.y, "heal");
|
||||||
|
};
|
||||||
me.onDeath = function () {
|
me.onDeath = function () {
|
||||||
this.leaveBody = false;
|
this.leaveBody = false;
|
||||||
this.dropPowerUp = false;
|
this.dropPowerUp = false;
|
||||||
@@ -276,6 +280,55 @@ const spawn = {
|
|||||||
this.checkStatus();
|
this.checkStatus();
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
// powerUpBoss(x, y, vertices = 9, radius = 130) {
|
||||||
|
// mobs.spawn(x, y, vertices, radius, "transparent");
|
||||||
|
// let me = mob[mob.length - 1];
|
||||||
|
// me.isBoss = true;
|
||||||
|
// me.frictionAir = 0.025
|
||||||
|
// me.seeAtDistance2 = 9000000;
|
||||||
|
// me.accelMag = 0.0005 * game.accelScale;
|
||||||
|
// Matter.Body.setDensity(me, 0.002); //normal is 0.001
|
||||||
|
// me.collisionFilter.mask = cat.bullet | cat.player
|
||||||
|
// me.memory = Infinity;
|
||||||
|
// me.seePlayerFreq = 85 + Math.floor(10 * Math.random())
|
||||||
|
|
||||||
|
// me.lockedOn = null;
|
||||||
|
// if (vertices === 9) {
|
||||||
|
// //on primary spawn
|
||||||
|
// powerUps.spawnBossPowerUp(me.position.x, me.position.y)
|
||||||
|
// powerUps.spawn(me.position.x, me.position.y, "heal");
|
||||||
|
// powerUps.spawn(me.position.x, me.position.y, "ammo");
|
||||||
|
// } else if (!mech.isCloak) {
|
||||||
|
// me.foundPlayer();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// me.onDeath = function () {
|
||||||
|
// this.leaveBody = false;
|
||||||
|
// this.dropPowerUp = false;
|
||||||
|
|
||||||
|
// if (vertices > 3) spawn.powerUpBoss(this.position.x, this.position.y, vertices - 1)
|
||||||
|
// for (let i = 0; i < powerUp.length; i++) {
|
||||||
|
// powerUp[i].collisionFilter.mask = cat.map | cat.powerUp
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// me.do = function () {
|
||||||
|
// this.stroke = `hsl(0,0%,${80+25*Math.sin(game.cycle*0.01)}%)`
|
||||||
|
|
||||||
|
// //steal all power ups
|
||||||
|
// for (let i = 0; i < Math.min(powerUp.length, this.vertices.length); i++) {
|
||||||
|
// powerUp[i].collisionFilter.mask = 0
|
||||||
|
// Matter.Body.setPosition(powerUp[i], this.vertices[i])
|
||||||
|
// Matter.Body.setVelocity(powerUp[i], {
|
||||||
|
// x: 0,
|
||||||
|
// y: 0
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// this.seePlayerCheckByDistance();
|
||||||
|
// this.attraction();
|
||||||
|
// this.checkStatus();
|
||||||
|
// };
|
||||||
|
// },
|
||||||
// healer(x, y, radius = 20) {
|
// healer(x, y, radius = 20) {
|
||||||
// mobs.spawn(x, y, 3, radius, "rgba(50,255,200,0.4)");
|
// mobs.spawn(x, y, 3, radius, "rgba(50,255,200,0.4)");
|
||||||
// let me = mob[mob.length - 1];
|
// let me = mob[mob.length - 1];
|
||||||
@@ -1654,7 +1707,7 @@ const spawn = {
|
|||||||
this.explode(this.mass * 10);
|
this.explode(this.mass * 10);
|
||||||
};
|
};
|
||||||
me.onDeath = function () {
|
me.onDeath = function () {
|
||||||
if (game.difficulty > 7) {
|
if (game.difficulty > 4) {
|
||||||
spawn.bullet(this.position.x, this.position.y, this.radius / 3, 5);
|
spawn.bullet(this.position.x, this.position.y, this.radius / 3, 5);
|
||||||
spawn.bullet(this.position.x, this.position.y, this.radius / 3, 5);
|
spawn.bullet(this.position.x, this.position.y, this.radius / 3, 5);
|
||||||
spawn.bullet(this.position.x, this.position.y, this.radius / 3, 5);
|
spawn.bullet(this.position.x, this.position.y, this.radius / 3, 5);
|
||||||
|
|||||||
@@ -488,9 +488,7 @@ em {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.color-plasma {
|
.color-plasma {
|
||||||
/* opacity: 0.5; */
|
|
||||||
color: #c0e;
|
color: #c0e;
|
||||||
/* color: #000; */
|
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
background-color: rgba(132, 0, 255, 0.04);
|
background-color: rgba(132, 0, 255, 0.04);
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
@@ -498,6 +496,12 @@ em {
|
|||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.color-worm {
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0px 0px 3px #357;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
.color-harm {
|
.color-harm {
|
||||||
/* color: */
|
/* color: */
|
||||||
/* text-shadow: #FC0 1px 0 10px; */
|
/* text-shadow: #FC0 1px 0 10px; */
|
||||||
|
|||||||
50
todo.txt
50
todo.txt
@@ -1,32 +1,48 @@
|
|||||||
|
|
||||||
|
mods ejected from Bayesian statistics can't duplicate
|
||||||
|
|
||||||
ice IX thermoelectric energy 66% -> 100%, heal 3%->4%
|
the power up boss moves faster, has less health,
|
||||||
|
it will eject one of your mods after a collision
|
||||||
|
and two health power ups
|
||||||
|
|
||||||
new key press detection system
|
mod ammonium nitrate: increase explosion damage and area by 25%
|
||||||
I rewrote some fundamental systems so there may be some bugs
|
also other explosion mods have been rebalanced (damage buffed, but self damage is also higher)
|
||||||
testing mode death is now shift X (was x+z)
|
|
||||||
|
|
||||||
you can now change your keys with the controls settings
|
field: wormhole - teleport around, bullets teleport too, blocks and power ups get sucked in
|
||||||
this is probably buggy too
|
mobs don't do much in worm hole yet, but that is coming with future mods
|
||||||
|
|
||||||
************** TODO - n-gon **************
|
************** TODO - n-gon **************
|
||||||
|
|
||||||
laser portal field
|
add an ending to the game
|
||||||
teleport to blocks and map elements in line of sight (like the how the laser works)
|
revamp the boss level, or add a new final level
|
||||||
do damage to mobs in the path of your teleportation
|
final level requires you to kill something, not skip content
|
||||||
go immune to damage for 1 second after teleportation
|
around level 15
|
||||||
after jumping into the portal you can send things back to your old location, like bullets and blocks, and mobs
|
game never ends if you have used cheats
|
||||||
|
|
||||||
add testing key for spawn boss mob
|
field wormhole
|
||||||
|
mobs are protected from bullets when stuck in a hole
|
||||||
|
mobs should destabilize holes, or take damage
|
||||||
|
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: cosmic string: do damage, like a laser for any mob that passes between the two portals, near the bezier curves
|
||||||
|
mod: extend immunity cycle after a teleport //mech.immuneCycle = mech.cycle + 15;
|
||||||
|
mod: reduce energy cost of teleportation
|
||||||
|
|
||||||
look for mods that could update description text with count and mod.is information
|
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>`
|
this.description = `<strong>8%</strong> chance to <strong>duplicate</strong> spawned <strong>power ups</strong><br><em>chance to duplicate = ${mod.duplicateChance}</em>`
|
||||||
|
|
||||||
give the power up boss the ability to eject your mobs if it hits you
|
mod (drones or spores) explode after 10 seconds
|
||||||
|
|
||||||
mouse event e.which is deprecated
|
mouse event e.which is deprecated
|
||||||
|
|
||||||
time dilation mod rework brain storm
|
time dilation mod rework (time dilation is cool, but it can feel like a chore)
|
||||||
|
redistribute effects
|
||||||
take no damage
|
take no damage
|
||||||
can fire
|
can fire
|
||||||
2x move jump fire while field is active
|
2x move jump fire while field is active
|
||||||
@@ -37,12 +53,6 @@ vacuum bomb applies status effect to mobs that makes blocks attracted to them
|
|||||||
mod: take less harm if you are moving fast
|
mod: take less harm if you are moving fast
|
||||||
require squirrel cage rotor
|
require squirrel cage rotor
|
||||||
|
|
||||||
getting stuck above a mob can immobilize player
|
|
||||||
just allow player to jump on mobs again?
|
|
||||||
occurs with Pauli exclusion, and time dilation field immunity - mod time-like world line
|
|
||||||
add a knock to player mob collisions even while player is immune to damage
|
|
||||||
keep the knock very small
|
|
||||||
|
|
||||||
bug - mine spawned one new mine every second
|
bug - mine spawned one new mine every second
|
||||||
after sticking to the top right corner of a wall
|
after sticking to the top right corner of a wall
|
||||||
notes: had only gun mine, mod mine reclamation, field plasma,
|
notes: had only gun mine, mod mine reclamation, field plasma,
|
||||||
|
|||||||
Reference in New Issue
Block a user