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
This commit is contained in:
landgreen
2020-12-02 09:56:20 -08:00
parent 7d9bfbd8cc
commit c855508dda
6 changed files with 123 additions and 61 deletions

View File

@@ -510,6 +510,9 @@ const game = {
input.endKeySensing(); input.endKeySensing();
b.removeAllGuns(); b.removeAllGuns();
game.isNoPowerUps = false; 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 mod.setupAllMods(); //sets mods to default values
b.setFireCD(); b.setFireCD();
game.updateModHUD(); game.updateModHUD();

View File

@@ -275,7 +275,7 @@ const build = {
for (let i = 0, len = mod.mods.length; i < len; i++) { for (let i = 0, len = mod.mods.length; i < len; i++) {
const modID = document.getElementById("mod-" + i) const modID = document.getElementById("mod-" + i)
if (!mod.mods[i].isCustomHide) { 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) { if (mod.mods[i].count > 1) {
modID.innerHTML = `<div class="grid-title"><div class="circle-grid mod"></div> &nbsp; ${mod.mods[i].name} (${mod.mods[i].count}x)</div>${mod.mods[i].description}</div>` modID.innerHTML = `<div class="grid-title"><div class="circle-grid mod"></div> &nbsp; ${mod.mods[i].name} (${mod.mods[i].count}x)</div>${mod.mods[i].description}</div>`
} else { } else {
@@ -480,7 +480,7 @@ document.getElementById("build-button").addEventListener("click", () => { //setu
for (let i = 0, len = mod.mods.length; i < len; i++) { for (let i = 0, len = mod.mods.length; i < len; i++) {
const modID = document.getElementById("mod-" + i) const modID = document.getElementById("mod-" + i)
if (!mod.mods[i].isCustomHide) { 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) { if (mod.mods[i].count > 1) {
modID.innerHTML = `<div class="grid-title"><div class="circle-grid mod"></div> &nbsp; ${mod.mods[i].name} (${mod.mods[i].count}x)</div>${mod.mods[i].description}</div>` modID.innerHTML = `<div class="grid-title"><div class="circle-grid mod"></div> &nbsp; ${mod.mods[i].name} (${mod.mods[i].count}x)</div>${mod.mods[i].description}</div>`
} else { } else {

View File

@@ -104,7 +104,7 @@ const mod = {
return dmg * mod.slowFire * mod.aimDamage return dmg * mod.slowFire * mod.aimDamage
}, },
duplicationChance() { 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() { totalBots() {
return mod.foamBotCount + mod.nailBotCount + mod.laserBotCount + mod.boomBotCount + mod.plasmaBotCount + mod.orbitBotCount 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", requires: "at least 1 mod, a chance to duplicate power ups",
effect: () => { effect: () => {
const chanceStore = mod.duplicateChance 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"); powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
mod.duplicateChance = chanceStore mod.duplicateChance = chanceStore
}, },
@@ -1686,6 +1686,25 @@ const mod = {
mod.renormalization = false; mod.renormalization = false;
} }
}, },
{
name: "erase",
description: "permanently remove <strong class='color-r'>rerolled</strong> <strong class='color-m'>mods</strong><br>spawn <strong>4</strong> <strong class='color-r'>rerolls</strong>",
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", name: "quantum immortality",
description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br>spawn <strong>4</strong> <strong class='color-r'>rerolls</strong>", description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br>spawn <strong>4</strong> <strong class='color-r'>rerolls</strong>",
@@ -3614,5 +3633,6 @@ const mod = {
isCancelDuplication: null, isCancelDuplication: null,
cancelCount: null, cancelCount: null,
isCancelRerolls: null, isCancelRerolls: null,
isBotDamage: null isBotDamage: null,
isBanish: null
} }

View File

@@ -775,6 +775,7 @@ const mech = {
fieldRange: 155, fieldRange: 155,
fieldShieldingScale: 1, fieldShieldingScale: 1,
fieldDamage: 1, fieldDamage: 1,
duplicateChance: 0,
energy: 0, energy: 0,
fieldRegen: 0, fieldRegen: 0,
fieldMode: 0, fieldMode: 0,
@@ -806,6 +807,8 @@ const mech = {
mech.fieldBlockCD = 10; mech.fieldBlockCD = 10;
mech.fieldHarmReduction = 1; mech.fieldHarmReduction = 1;
mech.fieldDamage = 1 mech.fieldDamage = 1
mech.duplicateChance = 0
if (mod.duplicationChance() === 0) game.draw.powerUp = game.draw.powerUpNormal
mech.grabPowerUpRange2 = 156000; mech.grabPowerUpRange2 = 156000;
mech.fieldRange = 155; mech.fieldRange = 155;
mech.fieldFire = false; mech.fieldFire = false;
@@ -1284,7 +1287,7 @@ const mech = {
}, },
fieldUpgrades: [{ fieldUpgrades: [{
name: "field emitter", name: "field emitter",
description: "use <strong class='color-f'>energy</strong> to <strong>block</strong> mobs<br><strong>throw</strong> blocks to <strong class='color-d'>damage</strong> mobs<br><strong>pick up</strong> power ups", description: "using the field drains <strong class='color-f'>energy</strong><br><strong>block</strong> mobs, <strong>grab</strong> power ups<br><strong>pick up</strong> and <strong>throw</strong> blocks",
effect: () => { effect: () => {
game.replaceTextLog = true; //allow text over write game.replaceTextLog = true; //allow text over write
mech.hold = function() { mech.hold = function() {
@@ -2272,10 +2275,12 @@ const mech = {
}, },
{ {
name: "wormhole", name: "wormhole",
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract blocks and power ups", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong> description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract blocks and power ups<br><strong>10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
effect: () => { effect: () => {
game.replaceTextLog = true; //allow text over write game.replaceTextLog = true; //allow text over write
mech.drop(); 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 // mech.hole = { //this is reset with each new field, but I'm leaving it here for reference
// isOn: false, // isOn: false,
// isReady: true, // isReady: true,

View File

@@ -129,6 +129,33 @@ const powerUps = {
}, },
use(type) { //runs when you actually reroll a list of selections, type can be field, gun, or mod use(type) { //runs when you actually reroll a list of selections, type can be field, gun, or mod
powerUps.reroll.changeRerolls(-1) 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 <strong class='color-m'>mods</strong> left<br><strong>erase</strong> has been ejected<br>erased <strong class='color-m'>mods</strong> have been recovered`, 300)
} else {
game.makeTextLog(`about ${powerUps.mod.lastTotalChoices - powerUps.mod.banishLog.length} estimated <strong class='color-m'>mods</strong> left`, 300)
}
// console.log(powerUps.mod.banishLog)
}
powerUps[type].effect(); powerUps[type].effect();
}, },
}, },
@@ -155,7 +182,6 @@ const powerUps = {
} }
}, },
ammo: { ammo: {
name: "ammo", name: "ammo",
color: "#467", color: "#467",
@@ -164,9 +190,11 @@ const powerUps = {
}, },
effect() { effect() {
//give ammo to all guns in inventory //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] const target = b.guns[b.activeGun]
target.ammo += Math.ceil(Math.random() * target.ammoPack) + Math.ceil(Math.random() * target.ammoPack) target.ammo += Math.ceil(Math.random() * target.ammoPack) + Math.ceil(Math.random() * target.ammoPack)
game.makeTextLog("<div class='circle ammo'></div> &nbsp; added " + (Math.min(mech.maxHealth - mech.health, heal) * game.healScale * 100).toFixed(0) + "%</span>", 300)
} else { } else {
for (let i = 0, len = b.inventory.length; i < len; i++) { for (let i = 0, len = b.inventory.length; i < len; i++) {
const target = b.guns[b.inventory[i]] const target = b.guns[b.inventory[i]]
@@ -176,40 +204,6 @@ const powerUps = {
} }
} }
game.updateGunHUD(); 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("<span style='font-size:115%;'><span class='color-f'>+energy</span></span>", 300);
// } else {
// let ammo = Math.ceil((target.ammoPack * (0.8 + 0.25 * Math.random())));
// target.ammo += ammo;
// game.updateGunHUD();
// game.makeTextLog("<div class='circle gun'></div> &nbsp; <span style='font-size:110%;'>+" + ammo + " ammo for " + target.name + "</span>", 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("<span style='font-size:115%;'><span class='color-f'>+energy</span></span>", 300);
// }
} }
}, },
field: { field: {
@@ -287,6 +281,8 @@ const powerUps = {
return 42; return 42;
}, },
choiceLog: [], //records all previous choice options 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() { effect() {
if (mech.alive) { if (mech.alive) {
function pick(skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { function pick(skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) {
@@ -296,6 +292,18 @@ const powerUps = {
options.push(i); options.push(i);
} }
} }
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 //remove repeats from last selection
const totalChoices = mod.isDeterminism ? 1 : 3 + mod.isExtraChoice * 2 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 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
@@ -310,6 +318,7 @@ const powerUps = {
} }
} }
} }
}
if (options.length > 0) { if (options.length > 0) {
const choose = options[Math.floor(Math.random() * options.length)] const choose = options[Math.floor(Math.random() * options.length)]
@@ -555,14 +564,28 @@ const powerUps = {
powerUps.spawnRandomPowerUp(x, y); powerUps.spawnRandomPowerUp(x, y);
} }
}, },
ejectMod() { ejectMod(choose = 'random') {
//find which mods you have //find which mods you have
if (choose === 'random') {
const have = [] const have = []
for (let i = 0; i < mod.mods.length; i++) { for (let i = 0; i < mod.mods.length; i++) {
if (mod.mods[i].count > 0) have.push(i) if (mod.mods[i].count > 0) have.push(i)
} }
if (have.length) { if (have.length) {
const choose = have[Math.floor(Math.random() * have.length)] choose = have[Math.floor(Math.random() * have.length)]
game.makeTextLog(`<div class='circle mod'></div> &nbsp; <strong>${mod.mods[choose].name}</strong> 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(`<div class='circle mod'></div> &nbsp; <strong>${mod.mods[choose].name}</strong> was ejected`, 600) //message about what mod was lost game.makeTextLog(`<div class='circle mod'></div> &nbsp; <strong>${mod.mods[choose].name}</strong> was ejected`, 600) //message about what mod was lost
for (let i = 0; i < mod.mods[choose].count; i++) { for (let i = 0; i < mod.mods[choose].count; i++) {
powerUps.directSpawn(mech.pos.x, mech.pos.y, "mod"); powerUps.directSpawn(mech.pos.x, mech.pos.y, "mod");

View File

@@ -1,8 +1,11 @@
*********** NEXT PATCH *********** *********** 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 ************** ************** BUGS **************
@@ -26,6 +29,14 @@ mod: shotgun slug - fire a big bullet
************** TODO ************** ************** 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 bullet mechanic - a bullet that swims through the air
rotate the velocity vector towards the normalized facing vector rotate the velocity vector towards the normalized facing vector
use the cross product > 0 to determine which direction to rotate the velocity use the cross product > 0 to determine which direction to rotate the velocity