boost power ups

tech: virtual particles - mobs have a chance to spawn coupling power ups
  old tech virtual particles renamed vacuum fluctuation

tech: exciton - mobs have a chance to spawn a boost
  boosts are a power up that increases your damage for 10 seconds
  old tech exciton renamed non-renewables
laser tech: quasiparticles - replace all ammo with boosts

added +20px to grid elements to prevent text spillover
bug fixes
This commit is contained in:
landgreen
2022-08-24 06:39:00 -07:00
parent 2ce8aca3ef
commit 6d1e62d6b8
7 changed files with 251 additions and 69 deletions

View File

@@ -280,7 +280,9 @@ const b = {
},
fireCDscale: 1,
setFireCD() {
b.fireCDscale = tech.fireRate * tech.slowFire * tech.researchHaste * tech.aimDamage
if (m.fieldMode === 6) b.fireCDscale *= 0.75
if (tech.isFastTime) b.fireCDscale *= 0.5
if (tech.isFireRateForGuns) b.fireCDscale *= Math.pow(0.82, b.inventory.length)
if (tech.isFireMoveLock) b.fireCDscale *= 0.55

View File

@@ -23,16 +23,17 @@ const level = {
// powerUps.research.changeRerolls(100000)
// m.immuneCycle = Infinity //you can't take damage
// tech.tech[297].frequency = 100
// m.setField("standing wave") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass
// m.setField("metamaterial cloaking") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass
// b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 matter wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.guns[0].ammo = 1000000
// tech.giveTech("expansion")
// tech.giveTech("1st ionization energy")
// for (let i = 0; i < 1; ++i) tech.giveTech("field coupling")
// for (let i = 0; i < 1; ++i) tech.giveTech("free-electron laser")
// m.damage(0.1);
// for (let i = 0; i < 1; i++) tech.giveTech("dynamic equilibrium")
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "research");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling");
// spawn.starter(1900, -500, 200)
// spawn.beetleBoss(1900, -400)

View File

@@ -874,6 +874,7 @@ const m = {
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
},
drawDefault() {
ctx.fillStyle = m.fillColor;
@@ -896,6 +897,7 @@ const m = {
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
},
// *********************************************
// **************** fields *********************
@@ -1373,11 +1375,23 @@ const m = {
m.fieldCDcycle = m.cycle + m.fieldBlockCD;
if (!who.isInvulnerable && (m.coupling && m.fieldMode < 3) && bullet.length < 250) { //for standing wave mostly
for (let i = 0; i < m.coupling; i++) {
const sub = Vector.mult(Vector.normalise(Vector.sub(who.position, m.pos)), (m.fieldRange * m.harmonicRadius) * (0.4 + 0.3 * Math.random())) //m.harmonicRadius should be 1 unless you are standing wave expansion
const rad = Vector.rotate(sub, 1 * (Math.random() - 0.5))
const angle = Math.atan2(sub.y, sub.x)
b.iceIX(6 + 6 * Math.random(), angle + 3 * (Math.random() - 0.5), Vector.add(m.pos, rad))
if (m.coupling - i > Math.random()) {
const sub = Vector.mult(Vector.normalise(Vector.sub(who.position, m.pos)), (m.fieldRange * m.harmonicRadius) * (0.4 + 0.3 * Math.random())) //m.harmonicRadius should be 1 unless you are standing wave expansion
const rad = Vector.rotate(sub, 1 * (Math.random() - 0.5))
const angle = Math.atan2(sub.y, sub.x)
b.iceIX(6 + 6 * Math.random(), angle + 3 * (Math.random() - 0.5), Vector.add(m.pos, rad))
}
}
// let count = 0
// for(let j=0; j<100;j++){
// const len = m.coupling + 0.5 * (Math.random() - 0.5)
// for (let i = 0; i < len; i++) {
// count++
// }
// }
// console.log(count)
}
const unit = Vector.normalise(Vector.sub(player.position, who.position))
if (tech.blockDmg) {
@@ -1562,7 +1576,7 @@ const m = {
return `<span style = 'font-size:95%;'><strong>deflecting</strong> condenses +${Math.ceil(couple)} <strong class='color-s'>ice IX</strong></span>`
// return `<span style = 'font-size:89%;'><strong>invulnerable</strong> <strong>+${2*couple}</strong> seconds post collision</span>`
case 3: //negative mass
return `<strong>+${27*couple}%</strong> <strong class='color-defense'>defense</strong>`
return `<strong>+${((1-0.73 ** couple)*100).toFixed(1)}%</strong> <strong class='color-defense'>defense</strong>`
case 4: //assembler
return `generate <strong>${6*couple}</strong> <strong class='color-f'>energy</strong> per second`
case 5: //plasma
@@ -1582,8 +1596,8 @@ const m = {
// m.setMaxHealth();
m.setFieldRegen()
mobs.setMobSpawnHealth();
if ((m.fieldMode === 0 || m.fieldMode === 9) && !build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.4);
powerUps.setDupChance();
if ((m.fieldMode === 0 || m.fieldMode === 9) && !build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.4);
// m.collisionImmuneCycles = 30 + m.coupling * 120 //2 seconds
// switch (m.fieldMode) {
// case 0: //field emitter
@@ -1757,7 +1771,7 @@ const m = {
m.harmonicRadius = 0.994 * m.harmonicRadius + 0.006
}
}
m.harmonicShield()
if (!simulation.isTimeSkipping) m.harmonicShield()
}
m.drawRegenEnergy()
}
@@ -1790,11 +1804,13 @@ const m = {
mob[i].locatePlayer();
const unit = Vector.normalise(Vector.sub(m.fieldPosition, mob[i].position))
m.fieldCDcycle = m.cycle + m.fieldBlockCD + (mob[i].isShielded ? 15 : 0);
if (bullet.length < 250) {
if (!mob[i].isInvulnerable && bullet.length < 250) {
for (let i = 0; i < m.coupling; i++) {
const angle = m.fieldAngle + 4 * m.fieldArc * (Math.random() - 0.5)
const radius = m.fieldRange * (0.6 + 0.3 * Math.random())
b.iceIX(6 + 6 * Math.random(), angle, Vector.add(m.fieldPosition, { x: radius * Math.cos(angle), y: radius * Math.sin(angle) }))
if (m.coupling - i > Math.random()) {
const angle = m.fieldAngle + 4 * m.fieldArc * (Math.random() - 0.5)
const radius = m.fieldRange * (0.6 + 0.3 * Math.random())
b.iceIX(6 + 6 * Math.random(), angle, Vector.add(m.fieldPosition, { x: radius * Math.cos(angle), y: radius * Math.sin(angle) }))
}
}
}
if (tech.blockDmg) { //electricity

View File

@@ -114,7 +114,37 @@ const powerUps = {
},
tech(num = 1) {
return `<div class="tech-circle"></div>`
}
},
coupling(num = 1) {
switch (num) {
case 1:
return `<div class="coupling-circle"></div>`
}
let text = '<span style="position:relative;">'
for (let i = 0; i < num; i++) {
text += `<div class="coupling-circle" style="position:absolute; top:1.5px; left:${i*8}px;"></div>`
}
text += '</span> &nbsp; &nbsp; '
for (let i = 0; i < num; i++) {
text += '&nbsp; '
}
return text
},
boost(num = 1) {
switch (num) {
case 1:
return `<div class="boost-circle"></div>`
}
let text = '<span style="position:relative;">'
for (let i = 0; i < num; i++) {
text += `<div class="boost-circle" style="position:absolute; top:1.5px; left:${i*8}px;"></div>`
}
text += '</span> &nbsp; &nbsp; '
for (let i = 0; i < num; i++) {
text += '&nbsp; '
}
return text
},
},
totalPowerUps: 0, //used for tech that count power ups at the end of a level
do() {},
@@ -303,7 +333,7 @@ const powerUps = {
},
endDraft(type, isCanceled = false) { //type should be a gun, tech, or field
if (isCanceled) {
if (tech.isCancelTech && Math.random() < 0.94) {
if (tech.isCancelTech && Math.random() < 0.9) {
// powerUps.research.use('tech')
powerUps[type].effect();
return
@@ -326,6 +356,7 @@ const powerUps = {
}
}
if (tech.isCancelCouple) {
simulation.makeTextLog(`m.coupling <span class='color-symbol'>+=</span> 0.5`);
m.coupling += 0.5
m.couplingChange()
}
@@ -364,6 +395,42 @@ const powerUps = {
if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 15; //player is immune to damage for 30 cycles
if (m.holdingTarget) m.drop();
},
coupling: {
name: "coupling",
color: "#0ae", //"#0cf",
size() {
return 13;
},
effect() {
simulation.makeTextLog(`m.coupling <span class='color-symbol'>+=</span> 0.1`);
m.coupling += 0.1
m.couplingChange()
},
},
boost: {
name: "boost",
color: "#f55", //"#0cf",
size() {
return 11;
},
endCycle: 0,
duration: 600,
damage: 1.5,
effect() {
powerUps.boost.endCycle = m.cycle + Math.floor(Math.max(0, powerUps.boost.endCycle - m.cycle) * 0.6) + powerUps.boost.duration //duration+seconds plus 2/3 of current time left
},
draw() {
// console.log(this.endCycle)
if (powerUps.boost.endCycle > m.cycle) {
ctx.strokeStyle = "rgba(255,0,0,0.8)" //m.fieldMeterColor; //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})`
ctx.beginPath();
const arc = (powerUps.boost.endCycle - m.cycle) / powerUps.boost.duration
ctx.arc(m.pos.x, m.pos.y, 28, m.angle - Math.PI * arc, m.angle + Math.PI * arc); //- Math.PI / 2
ctx.lineWidth = 4
ctx.stroke();
}
}
},
research: {
count: 0,
name: "research",
@@ -1203,6 +1270,12 @@ const powerUps = {
powerUps.spawn(x, y, "field");
return;
}
if (tech.isCouplingPowerUps && Math.random() < 0.17) {
powerUps.spawn(x, y, "coupling");
}
if (tech.isBoostPowerUps && Math.random() < 0.17) {
powerUps.spawn(x, y, "boost");
}
// if (Math.random() < 0.01) {
// powerUps.spawn(x, y, "research");
// return;
@@ -1389,6 +1462,7 @@ const powerUps = {
!(tech.isEnergyNoAmmo && target === 'ammo') &&
(!simulation.isNoPowerUps)
) {
if (tech.isBoostReplaceAmmo && target === 'ammo') target = 'boost'
powerUps.directSpawn(x, y, target, moving, mode, size)
if (Math.random() < tech.duplicationChance()) {
powerUps.directSpawn(x, y, target, moving, mode, size)

View File

@@ -209,6 +209,7 @@ const tech = {
damage: 1, //used for tech changes to player damage that don't have complex conditions
damageFromTech() {
let dmg = tech.damage //m.fieldDamage
if (powerUps.boost.endCycle > m.cycle) dmg *= 1 + powerUps.boost.damage
if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.15 * m.coupling
if (m.isSneakAttack && m.sneakAttackCycle + Math.min(120, 0.5 * (m.cycle - m.enterCloakCycle)) > m.cycle) dmg *= 4.33 * (1 + 0.33 * m.coupling)
if (tech.deathSkipTime) dmg *= 1 + 0.6 * tech.deathSkipTime
@@ -526,7 +527,7 @@ const tech = {
allowed() {
return !tech.isEnergyNoAmmo
},
requires: "not exciton",
requires: "not non-renewables",
effect() {
tech.isAmmoForGun = true;
},
@@ -548,7 +549,7 @@ const tech = {
allowed() {
return !tech.isEnergyNoAmmo
},
requires: "not exciton",
requires: "not non-renewables",
effect() {
tech.ammoCap = 16;
powerUps.ammo.effect()
@@ -567,7 +568,7 @@ const tech = {
allowed() {
return !tech.isEnergyNoAmmo
},
requires: "not exciton",
requires: "not non-renewables",
effect() {
tech.isAmmoFromHealth = true;
},
@@ -576,7 +577,7 @@ const tech = {
}
},
{
name: "exciton",
name: "non-renewables",
description: `<strong>+88%</strong> <strong class='color-d'>damage</strong><br>${powerUps.orb.ammo()} can't <strong>spawn</strong>`,
maxCount: 1,
count: 0,
@@ -1738,26 +1739,26 @@ const tech = {
tech.isBlockPowerUps = false
}
},
// {
// name: "Pauli exclusion",
// description: `after mob collisions<br>become <strong>invulnerable</strong> for <strong>+3</strong> seconds`,
// maxCount: 9,
// count: 0,
// frequency: 1,
// frequencyDefault: 1,
// allowed() { return true },
// requires: "",
// effect() {
// m.collisionImmuneCycles += 180;
// if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage
// },
// remove() {
// m.collisionImmuneCycles = 30;
// }
// },
{
name: "Pauli exclusion",
description: `after mob collisions<br>become <strong>invulnerable</strong> for <strong>+3</strong> seconds`,
maxCount: 9,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
effect() {
m.collisionImmuneCycles += 180;
if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage
},
remove() {
m.collisionImmuneCycles = 30;
}
},
{
name: "spinstatistics theorem",
description: `every <strong>7</strong> seconds<br>become <strong>invulnerable</strong> for <strong>+1.75</strong> seconds`,
description: `every <strong>7</strong> seconds<br>become <strong>invulnerable</strong> for <strong>+1.8</strong> seconds`,
maxCount: 3,
count: 0,
frequency: 1,
@@ -1767,7 +1768,7 @@ const tech = {
},
requires: "",
effect() {
tech.cyclicImmunity += 105;
tech.cyclicImmunity += 108;
},
remove() {
tech.cyclicImmunity = 0;
@@ -2226,7 +2227,7 @@ const tech = {
name: "1st ionization energy",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Ionization_energy' class="link">1st ionization energy</a>`,
description: `after you collect ${powerUps.orb.heal()}<br><strong>+10</strong> maximum <strong class='color-f'>energy</strong>`,
description: `convert ${powerUps.orb.heal()} into <div class="heal-circle" style = "background-color: #0ae;"></div><br><div class="heal-circle" style = "background-color: #0ae;"></div> give <strong>+10</strong> maximum <strong class='color-f'>energy</strong>`,
description: `convert ${powerUps.orb.heal()} into <div class="heal-circle" style = "background-color: #ff0; border: 0.5px #000 solid;"></div><br><div class="heal-circle" style = "background-color: #ff0; border: 0.5px #000 solid;"></div> give <strong>+10</strong> maximum <strong class='color-f'>energy</strong>`,
maxCount: 1,
count: 0,
frequency: 2,
@@ -2237,7 +2238,7 @@ const tech = {
requires: "mass-energy equivalence",
effect() {
tech.healGiveMaxEnergy = true; //tech.healMaxEnergyBonus given from heal power up
powerUps.heal.color = "#0ae"
powerUps.heal.color = "#ff0" //"#0ae"
for (let i = 0; i < powerUp.length; i++) { //find active heal power ups and adjust color live
if (powerUp[i].name === "heal") powerUp[i].color = powerUps.heal.color
}
@@ -3293,6 +3294,26 @@ const tech = {
}
}
},
{
name: "exciton",
descriptionFunction() {
return `<span style = 'font-size:94%;'>after mobs <strong>die</strong> they have a <strong>17%</strong> chance to<br>spawn ${powerUps.orb.boost(1)} that give <strong>+${powerUps.boost.damage*100}%</strong> <strong class='color-d'>damage</strong> for <strong>${(powerUps.boost.duration/60).toFixed(0)}</strong> seconds</span>`
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return true
},
requires: "",
effect() {
tech.isBoostPowerUps = true
},
remove() {
tech.isBoostPowerUps = false
}
},
{
name: "eternalism",
description: "<strong>+34%</strong> <strong class='color-d'>damage</strong><br><strong>time</strong> can't be <strong>paused</strong> <em>(time can be dilated)</em>",
@@ -3316,7 +3337,7 @@ const tech = {
},
{
name: "paradigm shift",
description: `<strong>clicking</strong> <strong class='color-m'>tech</strong> while paused <strong>ejects</strong> them<br><strong>16%</strong> chance to fail`,
description: `<strong>clicking</strong> <strong class='color-m'>tech</strong> while paused <strong>ejects</strong> them<br><strong>16%</strong> chance to remove without <strong>ejecting</strong>`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -3372,7 +3393,8 @@ const tech = {
},
requires: "",
effect() {
m.coupling++
simulation.makeTextLog(`m.coupling <span class='color-symbol'>+=</span> 1`);
m.coupling += 1
m.couplingChange()
},
remove() {
@@ -3383,12 +3405,12 @@ const tech = {
{
name: "quintessence",
descriptionFunction() {
return `use all your ${powerUps.orb.research(1)} to get <strong>+${powerUps.research.count*this.couplingToResearch}</strong> <strong class='color-coupling'>coupling</strong><br>${ m.couplingDescription()} ${m.fieldMode === 0 ? "" : "per <strong class='color-coupling'>coupling</strong>"}`
return `use all your ${powerUps.orb.research(1)} to get <strong>+${this.count ? this.researchUsed*this.couplingToResearch:powerUps.research.count*this.couplingToResearch}</strong> <strong class='color-coupling'>coupling</strong><br>${ m.couplingDescription()} ${m.fieldMode === 0 ? "" : "per <strong class='color-coupling'>coupling</strong>"}`
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
frequencyDefault: 100,
allowed() {
return powerUps.research.count > 3
},
@@ -3399,6 +3421,7 @@ const tech = {
while (powerUps.research.count > 0) {
powerUps.research.changeRerolls(-1)
this.researchUsed++
simulation.makeTextLog(`m.coupling <span class='color-symbol'>+=</span> ${(this.couplingToResearch).toFixed(2)}`);
m.coupling += this.couplingToResearch
}
m.couplingChange()
@@ -3412,6 +3435,26 @@ const tech = {
m.couplingChange()
}
},
{
name: "virtual particles",
descriptionFunction() {
return `after mobs <strong>die</strong> they have a <strong>17%</strong> chance to<br>spawn ${powerUps.orb.coupling(1)} that give <strong>+0.1</strong> <strong class='color-coupling'>coupling</strong>`
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return true
},
requires: "",
effect() {
tech.isCouplingPowerUps = true //about 20-30 mobs per level so at 16% and 0.1 coupling that's about 25 * 0.16 * 0.1 = 0.4 coupling per level with out duplication
},
remove() {
tech.isCouplingPowerUps = false
}
},
{
name: "fine-structure constant",
descriptionFunction() {
@@ -3428,6 +3471,7 @@ const tech = {
requires: "",
effect() {
tech.isCouplingNoHit = true
simulation.makeTextLog(`m.coupling <span class='color-symbol'>+=</span> ${(this.value).toFixed(1)}`);
m.coupling += this.value
m.couplingChange()
},
@@ -3462,7 +3506,7 @@ const tech = {
{
name: "options exchange",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Option_(finance)' class="link">options exchange</a>`,
description: `clicking <strong style = 'font-size:150%;'>×</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong> has a <strong>94%</strong><br>chance to randomize <strong>choices</strong> and not <strong>cancel</strong>`,
description: `clicking <strong style = 'font-size:150%;'>×</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong> has a <strong>90%</strong><br>chance to randomize <strong>choices</strong> and not <strong>cancel</strong>`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -5849,7 +5893,7 @@ const tech = {
allowed() {
return tech.haveGunCheck("foam") && !tech.isEnergyNoAmmo
},
requires: "foam, not exciton",
requires: "foam, not non-renewables",
ammoLost: 0,
effect() {
b.guns[8].ammoPack = b.guns[8].ammoPack * 12;
@@ -6197,6 +6241,27 @@ const tech = {
tech.isStuckOn = false
}
},
{
name: "quasiparticles",
descriptionFunction() {
return `replace all ${powerUps.orb.ammo(1)} spawns with ${powerUps.orb.boost(1)} which give<br><strong>+${powerUps.boost.damage*100}%</strong> <strong class='color-d'>damage</strong> for <strong>${(powerUps.boost.duration/60).toFixed(0)}</strong> seconds`
},
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("laser")
},
requires: "laser, not pulse",
effect() {
tech.isBoostReplaceAmmo = true
},
remove() {
tech.isBoostReplaceAmmo = false
}
},
{
name: "relativistic momentum",
description: "<strong class='color-laser'>lasers</strong> push <strong>mobs</strong> and <strong class='color-block'>blocks</strong>",
@@ -7325,7 +7390,7 @@ const tech = {
},
{
name: "time crystals",
description: "<strong>+300%</strong> passive <strong class='color-f'>energy</strong> generation",
description: "<strong>+200%</strong> passive <strong class='color-f'>energy</strong> generation",
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -7567,7 +7632,7 @@ const tech = {
}
},
{
name: "virtual particles",
name: "vacuum fluctuation",
description: `use ${powerUps.orb.research(6)}to exploit your <strong class='color-f'>field</strong> for a<br><strong>+11%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>`,
isFieldTech: true,
maxCount: 1,
@@ -10625,5 +10690,8 @@ const tech = {
isLastHitDamage: null,
isCloakHealLastHit: null,
isRicochet: null,
isCancelCouple: null
isCancelCouple: null,
isCouplingPowerUps: null,
isBoostPowerUps: null,
isBoostReplaceAmmo: null
}