From c855508ddadedd698a85ad2c4f09c02b0f208129 Mon Sep 17 00:00:00 2001 From: landgreen Date: Wed, 2 Dec 2020 09:56:20 -0800 Subject: [PATCH] erase field - wormhole now has a 10% chance to duplicate power ups mod: erase - remove rerolled mods from the selection pool 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 --- js/game.js | 3 ++ js/index.js | 4 +- js/mods.js | 26 +++++++++-- js/player.js | 9 +++- js/powerup.js | 127 +++++++++++++++++++++++++++++--------------------- todo.txt | 15 +++++- 6 files changed, 123 insertions(+), 61 deletions(-) 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