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