diff --git a/js/game.js b/js/game.js
index bcf5c10..8223c00 100644
--- a/js/game.js
+++ b/js/game.js
@@ -510,6 +510,9 @@ const game = {
input.endKeySensing();
b.removeAllGuns();
game.isNoPowerUps = false;
+ for (let i = 0; i < mod.mods.length; i++) {
+ if (mod.mods[i].isLost) mod.mods[i].isLost = false;
+ }
mod.setupAllMods(); //sets mods to default values
b.setFireCD();
game.updateModHUD();
diff --git a/js/index.js b/js/index.js
index c07f963..fbdae21 100644
--- a/js/index.js
+++ b/js/index.js
@@ -275,7 +275,7 @@ const build = {
for (let i = 0, len = mod.mods.length; i < len; i++) {
const modID = document.getElementById("mod-" + i)
if (!mod.mods[i].isCustomHide) {
- if (mod.mods[i].allowed() || isAllowed) {
+ if (mod.mods[i].allowed() || isAllowed || mod.mods[i].count > 0) {
if (mod.mods[i].count > 1) {
modID.innerHTML = `
${mod.mods[i].name} (${mod.mods[i].count}x)
${mod.mods[i].description}`
} else {
@@ -480,7 +480,7 @@ document.getElementById("build-button").addEventListener("click", () => { //setu
for (let i = 0, len = mod.mods.length; i < len; i++) {
const modID = document.getElementById("mod-" + i)
if (!mod.mods[i].isCustomHide) {
- if (mod.mods[i].allowed() || mod.mods[i].count > 1) {
+ if (mod.mods[i].allowed() || mod.mods[i].count > 0) {
if (mod.mods[i].count > 1) {
modID.innerHTML = ` ${mod.mods[i].name} (${mod.mods[i].count}x)
${mod.mods[i].description}`
} else {
diff --git a/js/mods.js b/js/mods.js
index 37e7e2b..28b3247 100644
--- a/js/mods.js
+++ b/js/mods.js
@@ -104,7 +104,7 @@ const mod = {
return dmg * mod.slowFire * mod.aimDamage
},
duplicationChance() {
- return (mod.isBayesian ? 0.16 : 0) + mod.cancelCount * 0.04 + mod.duplicateChance
+ return (mod.isBayesian ? 0.16 : 0) + mod.cancelCount * 0.04 + mod.duplicateChance + mech.duplicateChance
},
totalBots() {
return mod.foamBotCount + mod.nailBotCount + mod.laserBotCount + mod.boomBotCount + mod.plasmaBotCount + mod.orbitBotCount
@@ -1448,7 +1448,7 @@ const mod = {
requires: "at least 1 mod, a chance to duplicate power ups",
effect: () => {
const chanceStore = mod.duplicateChance
- mod.duplicateChance = (mod.isBayesian ? 0.16 : 0) + mod.cancelCount * 0.04 + mod.duplicateChance * 2 //increase duplication chance to simulate doubling all 3 sources of duplication chance
+ mod.duplicateChance = (mod.isBayesian ? 0.16 : 0) + mod.cancelCount * 0.04 + mech.duplicateChance + mod.duplicateChance * 2 //increase duplication chance to simulate doubling all 3 sources of duplication chance
powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
mod.duplicateChance = chanceStore
},
@@ -1686,6 +1686,25 @@ const mod = {
mod.renormalization = false;
}
},
+ {
+ name: "erase",
+ description: "permanently remove rerolled mods
spawn 4 rerolls",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return (powerUps.reroll.rerolls > 5 || build.isCustomSelection) && !mod.isDeterminism
+ },
+ requires: "not determinism, at least 4 rerolls",
+ effect() {
+ mod.isBanish = true
+ for (let i = 0; i < 4; i++) {
+ powerUps.spawn(mech.pos.x, mech.pos.y, "reroll", false);
+ }
+ },
+ remove() {
+ mod.isBanish = false
+ }
+ },
{
name: "quantum immortality",
description: "after dying, continue in an alternate reality
spawn 4 rerolls",
@@ -3614,5 +3633,6 @@ const mod = {
isCancelDuplication: null,
cancelCount: null,
isCancelRerolls: null,
- isBotDamage: null
+ isBotDamage: null,
+ isBanish: null
}
\ No newline at end of file
diff --git a/js/player.js b/js/player.js
index eaab009..7adb37c 100644
--- a/js/player.js
+++ b/js/player.js
@@ -775,6 +775,7 @@ const mech = {
fieldRange: 155,
fieldShieldingScale: 1,
fieldDamage: 1,
+ duplicateChance: 0,
energy: 0,
fieldRegen: 0,
fieldMode: 0,
@@ -806,6 +807,8 @@ const mech = {
mech.fieldBlockCD = 10;
mech.fieldHarmReduction = 1;
mech.fieldDamage = 1
+ mech.duplicateChance = 0
+ if (mod.duplicationChance() === 0) game.draw.powerUp = game.draw.powerUpNormal
mech.grabPowerUpRange2 = 156000;
mech.fieldRange = 155;
mech.fieldFire = false;
@@ -1284,7 +1287,7 @@ const mech = {
},
fieldUpgrades: [{
name: "field emitter",
- description: "use energy to block mobs
throw blocks to damage mobs
pick up power ups",
+ description: "using the field drains energy
block mobs, grab power ups
pick up and throw blocks",
effect: () => {
game.replaceTextLog = true; //allow text over write
mech.hold = function() {
@@ -2272,10 +2275,12 @@ const mech = {
},
{
name: "wormhole",
- description: "use energy to tunnel through a wormhole
wormholes attract blocks and power ups", //
bullets may also traverse wormholes
+ description: "use energy to tunnel through a wormhole
wormholes attract blocks and power ups
10% chance to duplicate spawned power ups", //
bullets may also traverse wormholes
effect: () => {
game.replaceTextLog = true; //allow text over write
mech.drop();
+ mech.duplicateChance = 0.1
+ game.draw.powerUp = game.draw.powerUpBonus //change power up draw
// mech.hole = { //this is reset with each new field, but I'm leaving it here for reference
// isOn: false,
// isReady: true,
diff --git a/js/powerup.js b/js/powerup.js
index abd4222..3d442b9 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -129,6 +129,33 @@ const powerUps = {
},
use(type) { //runs when you actually reroll a list of selections, type can be field, gun, or mod
powerUps.reroll.changeRerolls(-1)
+
+
+ // banish rerolled mods
+ if (mod.isBanish && type === 'mod') {
+ const banishLength = mod.isDeterminism ? 1 : 3 + mod.isExtraChoice * 2
+ if (powerUps.mod.choiceLog.length > banishLength || powerUps.mod.choiceLog.length === banishLength) { //I'm not sure this check is needed
+ for (let i = 0; i < banishLength; i++) {
+ powerUps.mod.banishLog.push(powerUps.mod.choiceLog[powerUps.mod.choiceLog.length - 1 - i])
+ }
+ }
+
+ if (powerUps.mod.lastTotalChoices - powerUps.mod.banishLog.length < 1) {
+ for (let i = 0, len = mod.mods.length; i < len; i++) {
+ if (mod.mods[i].name === "erase") {
+ powerUps.ejectMod(i)
+ }
+ }
+ game.makeTextLog(`No mods left
erase has been ejected
erased mods have been recovered`, 300)
+ } else {
+ game.makeTextLog(`about ${powerUps.mod.lastTotalChoices - powerUps.mod.banishLog.length} estimated mods left`, 300)
+ }
+
+
+ // console.log(powerUps.mod.banishLog)
+ }
+
+
powerUps[type].effect();
},
},
@@ -155,7 +182,6 @@ const powerUps = {
}
},
-
ammo: {
name: "ammo",
color: "#467",
@@ -164,9 +190,11 @@ const powerUps = {
},
effect() {
//give ammo to all guns in inventory
- if (mod.isAmmoForGun && b.inventory > 0) {
+ if (mod.isAmmoForGun && b.inventory.length > 0) {
const target = b.guns[b.activeGun]
target.ammo += Math.ceil(Math.random() * target.ammoPack) + Math.ceil(Math.random() * target.ammoPack)
+ game.makeTextLog(" added " + (Math.min(mech.maxHealth - mech.health, heal) * game.healScale * 100).toFixed(0) + "%", 300)
+
} else {
for (let i = 0, len = b.inventory.length; i < len; i++) {
const target = b.guns[b.inventory[i]]
@@ -176,40 +204,6 @@ const powerUps = {
}
}
game.updateGunHUD();
-
-
- // //only get ammo for guns player has
- // let target;
- // if (b.inventory.length > 0) {
- // if (mod.isAmmoForGun) {
- // target = b.guns[b.activeGun];
- // } else {
- // //find a gun in your inventory
- // target = b.guns[b.inventory[Math.floor(Math.random() * (b.inventory.length))]];
- // //try 3 more times to give ammo to a gun with ammo, not Infinity
- // if (target.ammo === Infinity) {
- // target = b.guns[b.inventory[Math.floor(Math.random() * (b.inventory.length))]]
- // if (target.ammo === Infinity) {
- // target = b.guns[b.inventory[Math.floor(Math.random() * (b.inventory.length))]]
- // if (target.ammo === Infinity) target = b.guns[b.inventory[Math.floor(Math.random() * (b.inventory.length))]]
- // }
- // }
- // }
- // //give ammo
- // if (target.ammo === Infinity) {
- // if (mech.energy < mech.maxEnergy) mech.energy = mech.maxEnergy;
- // if (!game.lastLogTime) game.makeTextLog("+energy", 300);
- // } else {
- // let ammo = Math.ceil((target.ammoPack * (0.8 + 0.25 * Math.random())));
- // target.ammo += ammo;
- // game.updateGunHUD();
- // game.makeTextLog(" +" + ammo + " ammo for " + target.name + "", 300);
- // }
- // } else {
- // // target = b.guns[Math.floor(Math.random() * b.guns.length)]; //if you don't have any guns just add ammo to a random gun you don't have yet
- // if (mech.energy < mech.maxEnergy) mech.energy = mech.maxEnergy;
- // if (!game.lastLogTime) game.makeTextLog("+energy", 300);
- // }
}
},
field: {
@@ -287,6 +281,8 @@ const powerUps = {
return 42;
},
choiceLog: [], //records all previous choice options
+ lastTotalChoices: 0, //tracks how many mods were available for random selection last time a mod was picked up
+ banishLog: [], //records all mods permanently removed from the selection pool
effect() {
if (mech.alive) {
function pick(skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) {
@@ -296,15 +292,28 @@ const powerUps = {
options.push(i);
}
}
- //remove repeats from last selection
- const totalChoices = mod.isDeterminism ? 1 : 3 + mod.isExtraChoice * 2
- if (powerUps.mod.choiceLog.length > totalChoices || powerUps.mod.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove
- for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection
- if (options.length > totalChoices) {
- for (let j = 0, len = options.length; j < len; j++) {
- if (powerUps.mod.choiceLog[powerUps.mod.choiceLog.length - 1 - i] === options[j]) {
- options.splice(j, 1) //remove previous choice from option pool
- break
+ powerUps.mod.lastTotalChoices = options.length //this is recorded so that banish can know how many mods were available
+
+ if (mod.isBanish) { //remove banished mods from last selection
+ for (let i = 0; i < powerUps.mod.banishLog.length; i++) {
+ for (let j = 0; j < options.length; j++) {
+ if (powerUps.mod.banishLog[i] === options[j]) {
+ options.splice(j, 1)
+ break
+ }
+ }
+ }
+ } else {
+ //remove repeats from last selection
+ const totalChoices = mod.isDeterminism ? 1 : 3 + mod.isExtraChoice * 2
+ if (powerUps.mod.choiceLog.length > totalChoices || powerUps.mod.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove
+ for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection
+ if (options.length > totalChoices) {
+ for (let j = 0, len = options.length; j < len; j++) {
+ if (powerUps.mod.choiceLog[powerUps.mod.choiceLog.length - 1 - i] === options[j]) {
+ options.splice(j, 1) //remove previous choice from option pool
+ break
+ }
}
}
}
@@ -555,14 +564,28 @@ const powerUps = {
powerUps.spawnRandomPowerUp(x, y);
}
},
- ejectMod() {
+ ejectMod(choose = 'random') {
//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)]
+ if (choose === 'random') {
+ const have = []
+ for (let i = 0; i < mod.mods.length; i++) {
+ if (mod.mods[i].count > 0) have.push(i)
+ }
+ if (have.length) {
+ choose = have[Math.floor(Math.random() * have.length)]
+ game.makeTextLog(` ${mod.mods[choose].name} was ejected`, 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
+ }
+ } else {
game.makeTextLog(` ${mod.mods[choose].name} was ejected`, 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");
diff --git a/todo.txt b/todo.txt
index 83fbf90..a49968b 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,8 +1,11 @@
*********** NEXT PATCH ***********
-custom and pause menu style update (mostly just thinner lines between blocks)
+field - wormhole now has a 10% chance to duplicate power ups
+mod: erase - remove rerolled mods from the selection pool
-mod: shotgun slug - fire a big bullet
+custom now lets you reproduce builds that only occur in game when a mod/gun/field is removed is ejected
+ example: in custom you can get time dilation only mods, then jump over to nano scale field and keep the crazy time dilation regen
+ this might cause some problems, let me know if anything gets weird
************** BUGS **************
@@ -26,6 +29,14 @@ mod: shotgun slug - fire a big bullet
************** TODO **************
+mod pilot wave: mini black hole - pull mobs and blocks in with more force
+ also from farther away
+ also do damage?
+mod pilot wave: antigravity - blocks have no gravity for a few seconds after exiting the field
+ maybe they bounce too?
+
+make the custom mode not disable mods that don't meet requirements after choosing a new mod
+
bullet mechanic - a bullet that swims through the air
rotate the velocity vector towards the normalized facing vector
use the cross product > 0 to determine which direction to rotate the velocity