added images

added images to tech, field, gun cards (enable this in settings)
  in progress - not all images are generated yet
  images are generated by me using midJourney plus significant post processing

random research power ups are 20% more common per level
global difficulty balance: player takes a bit less damage
mutualism: 0.5->1 borrowed health for 250->300% more spore damage

harpoon can still fire when out of energy, but slower
harpoon fire cooldown no longer triggers when the harpoon returns
  it's just a flat 2/3 of a second after you Fire
  improved fire rate now allows you to fire many harpoons at once until you run out of energy
default harpoon rope is a bit longer

several bug fixes and undocumented changes I forgot to list
This commit is contained in:
landgreen
2022-12-17 09:58:33 -08:00
parent 500bb3f73e
commit 16834e95be
376 changed files with 4150 additions and 2049 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,10 @@
"use strict";
//convert text into numbers for seed
Math.hash = s => { for (var i = 0, h = 9; i < s.length;) h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9); return h ^ h >>> 9 }
Math.hash = s => {
for (var i = 0, h = 9; i < s.length;) h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
return h ^ h >>> 9
}
// const date1 = new Date()
// console.log(date1.getUTCHours())
@@ -11,7 +14,7 @@ Math.hash = s => { for (var i = 0, h = 9; i < s.length;) h = Math.imul(h ^ s.cha
document.getElementById("seed").placeholder = Math.initialSeed = String(Math.floor(Date.now() % 100000))
Math.seed = Math.abs(Math.hash(Math.initialSeed)) //update randomizer seed in case the player changed it
Math.seededRandom = function(min = 0, max = 1) { // in order to work 'Math.seed' must NOT be undefined
Math.seededRandom = function (min = 0, max = 1) { // in order to work 'Math.seed' must NOT be undefined
Math.seed = (Math.seed * 9301 + 49297) % 233280;
return min + Math.seed / 233280 * (max - min);
}
@@ -97,7 +100,7 @@ const color = { //light
//difficulty is 0 easy, 1 normal, 2 hard, 4 why
function getUrlVars() {
let vars = {};
window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m, k, v) {
window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, k, v) {
vars[k] = v;
});
return vars;
@@ -122,7 +125,7 @@ window.addEventListener('load', () => {
break;
}
}
if (found) build.choosePowerUp(document.getElementById(`field-${index}`), index, 'field')
if (found) build.choosePowerUp(index, 'field')
}
if (property.substring(0, 3) === "gun") {
let found = false
@@ -134,12 +137,12 @@ window.addEventListener('load', () => {
break;
}
}
if (found) build.choosePowerUp(document.getElementById(`gun-${index}`), index, 'gun')
if (found) build.choosePowerUp(index, 'gun')
}
if (property.substring(0, 4) === "tech") {
for (let i = 0; i < tech.tech.length; i++) {
if (set[property] === tech.tech[i].name) {
build.choosePowerUp(document.getElementById(`tech-${i}`), i, 'tech', true)
build.choosePowerUp(i, 'tech', true)
break;
}
}
@@ -150,13 +153,14 @@ window.addEventListener('load', () => {
lore.setTechGoal()
document.getElementById("difficulty-select-experiment").value = Number(set[property])
}
if (property === "level") document.getElementById("starting-level").value = Math.max(Number(set[property]) - 1, 0)
if (property === "noPower") document.getElementById("no-power-ups").checked = Number(set[property])
if (property === "molMode") {
simulation.molecularMode = Number(set[property])
const i = 4 //update experiment text
m.fieldUpgrades[i].description = m.fieldUpgrades[i].setDescription()
document.getElementById(`field-${i}`).innerHTML = `<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div> ${m.fieldUpgrades[i].description}`
// document.getElementById(`field-${i}`).innerHTML = `<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div> ${m.fieldUpgrades[i].description}`
document.getElementById(`field-${i}`).innerHTML = `<div class="card-text">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div>
${m.fieldUpgrades[i].description}</div>`
}
// if (property === "seed") {
// document.getElementById("seed").placeholder = Math.initialSeed = String(set[property])
@@ -198,7 +202,7 @@ const ctx = canvas.getContext("2d");
document.body.style.backgroundColor = "#fff";
//disable pop up menu on right click
document.oncontextmenu = function() {
document.oncontextmenu = function () {
return false;
}
@@ -280,13 +284,27 @@ const build = {
}
requestAnimationFrame(loop);
},
showImages(from) { //on click event: from all 3 different places to hide / show images
localSettings.isHideImages = !localSettings.isHideImages
if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
if (from === 'experiment') {
// build.startExperiment()
// openExperimentMenu()
build.reset();
// build.populateGrid();
// build.choosePowerUp(null, 'none')
} else if (from === 'pause') {
build.unPauseGrid()
build.pauseGrid() //redraw pause text with images
} else { //settings
//nothing needs to be here I think
}
document.getElementById("hide-images").checked = localSettings.isHideImages
// console.log(localSettings.isHideImages, from)
},
pauseGrid() {
// build.pixelDraw();
//used for junk estimation
let junkCount = 0
let totalCount = 1 //start at one to avoid NaN issues
@@ -307,72 +325,108 @@ const build = {
if (tech.plasmaBotCount) botText += `<br>plasma-bots: ${tech.plasmaBotCount}`
if (tech.missileBotCount) botText += `<br>missile-bots: ${tech.missileBotCount}`
let text = `<div class="pause-grid-module" style = "font-size: 13px;line-height: 120%;padding: 5px;">`
if (!simulation.isChoosing) text += `<br><span style="font-size:1.5em;font-weight: 600;">PAUSED</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; press P to resume
<br><br><svg class="SVG-button" onclick="build.shareURL(false)" width="92" height="20" style="padding:0px; margin: 1px;">
let text = `<div class="pause-grid-module" style = "font-size: 13px;line-height: 120%;padding: 5px;">
<svg class="SVG-button" onclick="build.shareURL(false)" width="92" height="20" style="padding:0px; margin: 1px;">
<g stroke='none' fill='#333' stroke-width="2" font-size="14px" font-family="Ariel, sans-serif"> <text x="5" y="15">copy build url</text></g>
</svg><br>`
text += `
<br><strong class='color-d'>damage</strong>: ${((tech.damageFromTech())).toPrecision(3)} &nbsp; &nbsp; difficulty: ${((m.dmgScale)).toPrecision(3)}
<br><strong class='color-defense'>defense</strong>: ${tech.isEnergyHealth ? (1-Math.pow(m.harmReduction(), 0.1)).toPrecision(3) : (1-m.harmReduction()).toPrecision(3) } &nbsp; &nbsp; difficulty: ${(1/simulation.dmgScale).toPrecision(3)}
</svg><span style="font-size:1.5em;font-weight: 600; float: right;">PAUSED</span>
<br>
<label for="hide-images-pause" title="hide images for fields, guns, and tech" style="font-size:1.3em;" >hide images:</label>
<input onclick="build.showImages('pause')" type="checkbox" id="hide-images-pause" name="hide-images-pause" ${localSettings.isHideImages? "checked": ""}>
<span style="float: right;">press ${input.key.pause} to resume</span>
<br>
<br><strong class='color-d'>damage</strong>: ${((tech.damageFromTech())).toPrecision(4)} &nbsp; &nbsp; difficulty: ${((m.dmgScale)).toPrecision(4)}
<br><strong class='color-defense'>defense</strong>: ${tech.isEnergyHealth ? (1-Math.pow(m.harmReduction(), 0.1)).toPrecision(5) : (1-m.harmReduction()).toPrecision(5) } &nbsp; &nbsp; difficulty: ${(1/simulation.dmgScale).toPrecision(4)}
<br><strong><em>fire rate</em></strong>: ${((1-b.fireCDscale)*100).toFixed(b.fireCDscale < 0.1 ? 2 : 0)}%
${tech.duplicationChance() ? `<br><strong class='color-dup'>duplication</strong>: ${(tech.duplicationChance()*100).toFixed(0)}%`: ""}
${m.coupling ? `<br><strong class='color-coupling'>coupling</strong>: ${(m.coupling).toFixed(2)} &nbsp; <span style = 'font-size:90%;'>`+m.couplingDescription()+"</span>": ""}
${botText}
<br>
<br><strong class='color-h'>health</strong>: (${(m.health*100).toFixed(0)} / ${(m.maxHealth*100).toFixed(0)})
<span style="float: right;">mass: ${player.mass.toFixed(1)}</span>
<br><strong class='color-f'>energy</strong>: (${(m.energy*100).toFixed(0)} / ${(m.maxEnergy*100).toFixed(0)}) +(${(m.fieldRegen*6000).toFixed(0)}/s)
<span style="float: right;">position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)})</span>
<br><strong class='color-g'>gun</strong>: ${b.activeGun === null || b.activeGun === undefined ? "undefined":b.guns[b.activeGun].name} &nbsp; <strong class='color-g'>ammo</strong>: ${b.activeGun === null || b.activeGun === undefined ? "0":b.guns[b.activeGun].ammo}
<br><strong class='color-m'>tech</strong>: ${tech.totalCount} &nbsp; <strong class='color-r'>research</strong>: ${powerUps.research.count}
<span style="float: right;">mouse: (${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)})</span>
<br><strong class='color-m'>tech</strong>: ${tech.totalCount} &nbsp; <strong class='color-r'>research</strong>: ${powerUps.research.count}
<span style="float: right;">velocity: (${player.velocity.x.toFixed(3)}, ${player.velocity.y.toFixed(3)})</span>
${junkCount ? `<br><strong class='color-j'>JUNK</strong>: ${(junkCount / totalCount * 100).toFixed(1)}% `: ""}
<br>
<br>seed: ${Math.initialSeed}
<br>level: ${level.levels[level.onLevel]} (${level.difficultyText()}) &nbsp; ${m.cycle} cycles
<br>mobs: ${mob.length} &nbsp; deaths: ${mobs.mobDeaths}
<br>blocks: ${body.length} &nbsp; bullets: ${bullet.length} &nbsp; power ups: ${powerUp.length}
<br>position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)}) &nbsp; velocity: (${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)})
<br>mouse: (${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)}) &nbsp; mass: ${player.mass.toFixed(1)}
<br>level: ${level.levelsCleared} ${level.levels[level.onLevel]} (${level.difficultyText()})
<br>seed: ${Math.initialSeed} &nbsp; ${m.cycle} cycles
<br>mobs: ${mob.length} &nbsp; blocks: ${body.length} &nbsp; bullets: ${bullet.length} &nbsp; power ups: ${powerUp.length}
${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
</div>`;
for (let i = 0, len = b.inventory.length; i < len; i++) {
text += `<div class="pause-grid-module"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[b.inventory[i]].name)} - <span style="font-size:100%;font-weight: 100;">${b.guns[b.inventory[i]].ammo}</span></div> ${b.guns[b.inventory[i]].description}</div>`
// deaths: ${mobs.mobDeaths} &nbsp;
if (tech.isPauseSwitchField && !simulation.isChoosing) {
const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/field/${m.fieldUpgrades[m.fieldMode].name}${m.fieldMode === 0 ? Math.floor(Math.random()*10) : ""}.webp');"`
text += `<div class="pause-grid-module card-background" id ="pause-field" ${style} >
<div class="card-text" style = "animation: fieldColorCycle 1s linear infinite alternate;">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div>
${m.fieldUpgrades[m.fieldMode].description}</div> </div>`
} else {
const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/field/${m.fieldUpgrades[m.fieldMode].name}${m.fieldMode === 0 ? Math.floor(Math.random()*10) : ""}.webp');"`
text += `<div class="pause-grid-module card-background" id ="pause-field" ${style} >
<div class="card-text">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div>
${m.fieldUpgrades[m.fieldMode].description}</div> </div>`
}
// for (let i = 0, len = b.inventory.length; i < len; i++) {
// text += `<div class="pause-grid-module"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[b.inventory[i]].name)} - <span style="font-size:100%;font-weight: 100;">${b.guns[b.inventory[i]].ammo}</span></div> ${b.guns[b.inventory[i]].description}</div>`
// }
for (let i = 0, len = b.inventory.length; i < len; i++) {
const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/gun/${b.guns[b.inventory[i]].name}.webp');"`
text += `<div class="pause-grid-module card-background" ${style} >
<div class="card-text">
<div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[b.inventory[i]].name)} - <span style="font-size:100%;font-weight: 100;">${b.guns[b.inventory[i]].ammo}</span></div>
${b.guns[b.inventory[i]].description}</div> </div>`
}
let el = document.getElementById("pause-grid-left")
el.style.display = tech.isNoDraftPause ? "none" : "grid" //disabled for eternalism because eternalism lets the player play while this menu is up but the menu doesn't update
el.innerHTML = text
//right side
text = "";
if (tech.isPauseSwitchField && !simulation.isChoosing) {
text += `<div class="pause-grid-module" id ="pause-field" style="animation: fieldColorCycle 1s linear infinite alternate;"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div> ${m.fieldUpgrades[m.fieldMode].description}</div>`
} else {
text += `<div class="pause-grid-module" id ="pause-field"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div> ${m.fieldUpgrades[m.fieldMode].description}</div>`
}
const style = (tech.isPauseEjectTech && !simulation.isChoosing) ? 'style="animation: techColorCycle 1s linear infinite alternate;"' : ''
// const style = (tech.isPauseEjectTech && !simulation.isChoosing) ? 'style="animation: techColorCycle 1s linear infinite alternate;"' : ''
const ejectClass = (tech.isPauseEjectTech && !simulation.isChoosing) ? 'pause-eject' : ''
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].count > 0) {
// const techCountText = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
// if (tech.tech[i].isNonRefundable) {
// text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" style = "border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; margin: 1px; padding-top: 6px; padding-bottom: 6px;"><div class="grid-title">${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
// } else if (tech.tech[i].isFieldTech) {
// text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" ${style}><div class="grid-title">
// <span style="position:relative;">
// <div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
// <div class="circle-grid field" style="position:absolute; top:0; left:10px;opacity:0.65;"></div>
// </span>
// &nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
// } else if (tech.tech[i].isGunTech) {
// text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" ${style}><div class="grid-title">
// <span style="position:relative;">
// <div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
// <div class="circle-grid gun" style="position:absolute; top:0; left:10px; opacity:0.65;"></div>
// </span>
// &nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
// } else if (tech.tech[i].isLore) {
// text += `<div class="pause-grid-module"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[i].name} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
// } else {
// text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" ${style}><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
// }
const style = localSettings.isHideImages ? `style="height:auto;"` : `style = "background-image: url('img/${tech.tech[i].name}.webp');"`
const techCountText = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
if (tech.tech[i].isNonRefundable) {
text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" style = "border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; margin: 1px; padding-top: 6px; padding-bottom: 6px;"><div class="grid-title">${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
text += `<div class="pause-grid-module" id ="${i}-pause-tech" style = "border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; margin: 1px; padding-top: 6px; padding-bottom: 6px;"><div class="grid-title">${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
// } else if (tech.tech[i].isLore) {
// text += `<div class="pause-grid-module"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[i].name} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
} else if (tech.tech[i].isFieldTech) {
text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" ${style}><div class="grid-title">
<span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid field" style="position:absolute; top:0; left:10px;opacity:0.65;"></div>
</span>
&nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
text += `<div id="${i}-pause-tech" class="pause-grid-module card-background ${ejectClass}" onclick="powerUps.pauseEjectTech(${i})" ${style}>`
text += build.fieldTechText(i) + "</div>"
} else if (tech.tech[i].isGunTech) {
text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" ${style}><div class="grid-title">
<span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid gun" style="position:absolute; top:0; left:10px; opacity:0.65;"></div>
</span>
&nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
} else if (tech.tech[i].isLore) {
text += `<div class="pause-grid-module"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[i].name} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
text += `<div id="${i}-pause-tech" class="pause-grid-module card-background ${ejectClass}" onclick="powerUps.pauseEjectTech(${i})" ${style}>`
text += build.gunTechText(i) + "</div>"
} else {
text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" ${style}><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
text += `<div id="${i}-pause-tech" class="pause-grid-module card-background ${ejectClass}" onclick="powerUps.pauseEjectTech(${i})" ${style}>`
text += build.techText(i) + "</div>"
}
} else if (tech.tech[i].isLost) {
text += `<div class="pause-grid-module" style="text-decoration: line-through;"><div class="grid-title">${tech.tech[i].link}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
@@ -408,13 +462,39 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
},
isExperimentSelection: false,
isExperimentRun: false,
choosePowerUp(who, index, type, isAllowed = false) {
techText(i) {
return `<div class="card-text" >
<div class="grid-title" ><div class="circle-grid tech"></div> &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
},
gunTechText(i) {
return `<div class="card-text"> <div class="grid-title">
<span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid gun" style="position:absolute; top:0; left:10px; opacity:0.65;"></div>
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
},
fieldTechText(i) {
return `<div class="card-text"><div class="grid-title">
<span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid field" style="position:absolute; top:0; left:10px;opacity:0.65;"></div>
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
},
junkTechText(i) {
return `<div class="card-text">
<div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
},
choosePowerUp(index, type, isAllowed = false) {
if (type === "gun") {
let isDeselect = false
for (let i = 0, len = b.inventory.length; i < len; i++) { //look for selection in inventory
if (b.guns[b.inventory[i]].name === b.guns[index].name) { //if already clicked, remove gun
isDeselect = true
who.classList.remove("build-gun-selected");
document.getElementById("gun-" + b.inventory[i]).classList.remove("build-gun-selected");
//remove gun
b.inventory.splice(i, 1)
b.guns[index].count = 0;
@@ -426,110 +506,66 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
}
}
if (!isDeselect) { //add gun
who.classList.add("build-gun-selected");
document.getElementById("gun-" + index).classList.add("build-gun-selected");
b.giveGuns(index)
}
} else if (type === "field") {
if (m.fieldMode !== index) {
document.getElementById("field-" + m.fieldMode).classList.remove("build-field-selected");
m.setField(index)
who.classList.add("build-field-selected");
document.getElementById("field-" + index).classList.add("build-field-selected");
} else if (m.fieldMode === 4) {
const i = 4 //update experiment text
simulation.molecularMode++
if (simulation.molecularMode > i - 1) simulation.molecularMode = 0
m.fieldUpgrades[i].description = m.fieldUpgrades[i].setDescription()
document.getElementById(`field-${i}`).innerHTML = `<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div> ${m.fieldUpgrades[i].description}`
// document.getElementById(`field-${i}`).innerHTML = `<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div> ${m.fieldUpgrades[i].description}`
document.getElementById(`field-${i}`).innerHTML = `<div class="card-text">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div>
${m.fieldUpgrades[i].description}</div>`
}
// if (m.fieldMode === 4 && simulation.molecularMode < 3) {
// simulation.molecularMode++
// m.fieldUpgrades[4].description = m.fieldUpgrades[4].setDescription()
// } else {
// m.setField((m.fieldMode === m.fieldUpgrades.length - 1) ? 1 : m.fieldMode + 1) //cycle to next field
// if (m.fieldMode === 4) {
// simulation.molecularMode = 0
// m.fieldUpgrades[4].description = m.fieldUpgrades[4].setDescription()
// }
// }
} else if (type === "tech") {
if (tech.tech[index].count < tech.tech[index].maxCount) {
// if (!tech.tech[index].isLore && !tech.tech[index].isNonRefundable && !who.classList.contains("build-tech-selected")) who.classList.add("build-tech-selected");
if (!who.classList.contains("build-tech-selected")) who.classList.add("build-tech-selected");
if (!document.getElementById("tech-" + index).classList.contains("build-tech-selected")) document.getElementById("tech-" + index).classList.add("build-tech-selected");
tech.giveTech(index)
} else if (!tech.tech[index].isNonRefundable) {
// tech.totalCount -= tech.tech[index].count
tech.removeTech(index);
who.classList.remove("build-tech-selected");
document.getElementById("tech-" + index).classList.remove("build-tech-selected");
} else {
// for non refundable tech this makes it flash off for a second, but return to on to show that it can't be set off
who.classList.remove("build-tech-selected")
document.getElementById("tech-" + index).classList.remove("build-tech-selected")
setTimeout(() => {
who.classList.add("build-tech-selected")
document.getElementById("tech-" + index).classList.add("build-tech-selected")
}, 50);
}
}
// } else if (type === "tech") { //remove tech if you have too many
// if (tech.tech[index].count < tech.tech[index].maxCount) {
// if (!who.classList.contains("build-tech-selected")) who.classList.add("build-tech-selected");
// tech.giveTech(index)
// } else if (!tech.tech[index].isNonRefundable) {
// tech.totalCount -= tech.tech[index].count
// tech.removeTech(index);
// who.classList.remove("build-tech-selected");
// } else {
// who.classList.remove("build-tech-selected")
// setTimeout(() => { //return energy
// who.classList.add("build-tech-selected")
// }, 50);
// }
// }
//update tech text //disable not allowed tech
for (let i = 0, len = tech.tech.length; i < len; i++) {
const techID = document.getElementById("tech-" + i)
if ((!tech.tech[i].isJunk || localSettings.isJunkExperiment)) { //!tech.tech[i].isNonRefundable && //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! does removing this cause problems????
if (tech.tech[i].allowed() || isAllowed || tech.tech[i].count > 0) {
const techCountText = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
// <div class="circle-grid-small research" style="position:absolute; top:13px; left:30px;opacity:0.85;"></div>
if (tech.tech[i].isFieldTech) {
techID.classList.remove('experiment-grid-hide');
techID.innerHTML = `
<div class="grid-title">
<span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid field" style="position:absolute; top:0; left:10px;opacity:0.65;"></div>
</span>
&nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}
</div>`
// <div class="circle-grid gun" style="position:absolute; top:-3px; left:-3px; opacity:1; height: 33px; width:33px;"></div>
// <div class="circle-grid tech" style="position:absolute; top:5px; left:5px;opacity:1;height: 20px; width:20px;border: #fff solid 2px;"></div>
// border: #fff solid 0px;
techID.innerHTML = build.fieldTechText(i)
} else if (tech.tech[i].isGunTech) {
techID.classList.remove('experiment-grid-hide');
techID.innerHTML = `
<div class="grid-title">
<span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid gun" style="position:absolute; top:0; left:10px; opacity:0.65;"></div>
</span>
&nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}
</div>`
techID.innerHTML = build.gunTechText(i)
} else if (tech.tech[i].isJunk) {
techID.innerHTML = `<div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
techID.innerHTML = build.junkTechText(i)
// `<div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
} else {
techID.innerHTML = `<div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
techID.innerHTML = build.techText(i)
}
//deselect selected tech options if you don't have the tech any more // for example: when bot techs are converted after a bot upgrade tech is taken
if (tech.tech[i].count === 0 && techID.classList.contains("build-tech-selected")) techID.classList.remove("build-tech-selected");
if (techID.classList.contains("experiment-grid-disabled")) {
techID.classList.remove("experiment-grid-disabled");
techID.setAttribute("onClick", `javascript: build.choosePowerUp(this,${i},'tech')`);
techID.setAttribute("onClick", `javascript: build.choosePowerUp(${i},'tech')`);
}
// } else if (tech.tech[i].isGunTech || tech.tech[i].isFieldTech) {
// techID.classList.add('experiment-grid-hide');
@@ -544,63 +580,97 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
}
if (tech.tech[i].count > 0) tech.removeTech(i)
if (techID.classList.contains("build-tech-selected")) techID.classList.remove("build-tech-selected");
if (tech.tech[i].isFieldTech) {
techID.innerHTML = build.fieldTechText(i)
} else if (tech.tech[i].isGunTech) {
techID.innerHTML = build.gunTechText(i)
} else if (tech.tech[i].isJunk) {
techID.innerHTML = build.junkTechText(i)
} else {
techID.innerHTML = build.techText(i)
}
}
}
}
},
populateGrid() {
populateGrid() { //background-color:var(--build-bg-color);
let text = `
<div style="display: flex; justify-content: space-around; align-items: center;">
<svg class="SVG-button" onclick="build.startExperiment()" width="115" height="51">
<g stroke='none' fill='#333' stroke-width="2" font-size="40px" font-family="Ariel, sans-serif">
<text x="18" y="38">start</text>
</g>
<div class="experiment-grid-module" style="position: sticky; top:0; z-index: 10; align-self: start; width: 160px; font-size: 1.00em; line-height: 170%; background-color: #fafcfd;display: flex; flex-direction: column; justify-content: center; align-items: center;border: 1.5px #333 solid;border-radius:10px;">
<div>
<svg class="SVG-button" onclick="build.startExperiment()" width="150" height="68" >
<g stroke='none' fill='#333' stroke-width="2" font-size="60px" font-family="Ariel, sans-serif">
<text x="14" y="54">start</text>
</g>
</svg>
</div>
<div>
<svg class="SVG-button" onclick="build.reset()" width="50" height="25">
<g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif">
<g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif">
<text x="5" y="18">reset</text>
</g>
</g>
</svg>
&nbsp; &nbsp;
<svg class="SVG-button" onclick="build.shareURL(true)" width="52" height="25">
<g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif">
<g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif">
<text x="5" y="18">share</text>
</g>
</g>
</svg>
</div>
<div style="align-items: center; text-align:center; font-size: 1.00em; line-height: 190%;background-color:var(--build-bg-color);">
<div>starting level: <input id='starting-level' type="number" step="1" value="1" min="0" max="99"></div>
<div>
</div>
<div>
<label for="difficulty-select" title="effects: number of mobs, damage done by mobs, damage done to mobs, mob speed, heal effects">difficulty:</label>
<select name="difficulty-select" id="difficulty-select-experiment">
<select name="difficulty-select" id="difficulty-select-experiment">
<option value="1">easy</option>
<option value="2" selected>normal</option>
<option value="4">hard</option>
<option value="6">why?</option>
</select>
</div>
<div>
<label for="no-power-ups" title="no tech, fields, or guns will spawn">no power ups:</label>
<input type="checkbox" id="no-power-ups" name="no-power-ups" style="width:17px; height:17px;">
</div>
</div>`
</select>
</div>
<div>
<label for="hide-images-experiment" title="reload experiment with no images for fields, guns, and tech">hide images:</label>
<input onclick="build.showImages('experiment')" type="checkbox" id="hide-images-experiment" name="hide-images-experiment" style="width:17px; height:17px;" ${localSettings.isHideImages? "checked": ""}>
</div>
</div>`
const hideStyle = `style="height:auto; border: none; background-color: transparent;"`
for (let i = 0, len = m.fieldUpgrades.length; i < len; i++) {
text += `<div id ="field-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'field')"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div> ${m.fieldUpgrades[i].description}</div>`
const style = localSettings.isHideImages ? hideStyle : `style="background-image: url('img/field/${m.fieldUpgrades[i].name}${i === 0 ? Math.floor(Math.random()*10) : ""}.webp');"`
//original
// text += powerUps.fieldText(i, `build.choosePowerUp(this,${i},'field')`)
// text += `<div id ="field-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'field')"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div> ${m.fieldUpgrades[i].description}</div>`
text += `<div id="field-${i}" class="experiment-grid-module card-background" onclick="build.choosePowerUp(${i},'field')" ${style} >
<div class="card-text">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div>
${m.fieldUpgrades[i].description}</div> </div>`
}
for (let i = 0, len = b.guns.length; i < len; i++) {
text += `<div id = "gun-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'gun')"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[i].name)}</div> ${b.guns[i].description}</div>`
const style = localSettings.isHideImages ? hideStyle : `style="background-image: url('img/gun/${b.guns[i].name}.webp');"`
text += `<div id="gun-${i}" class="experiment-grid-module card-background" onclick="build.choosePowerUp(${i},'gun')" ${style} >
<div class="card-text">
<div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[i].name)}</div>
${b.guns[i].description}</div> </div>`
//original
// text += `<div id = "gun-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'gun')"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[i].name)}</div> ${b.guns[i].description}</div>`
}
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (!tech.tech[i].isJunk || localSettings.isJunkExperiment) {
const style = localSettings.isHideImages ? hideStyle : `style="background-image: url('img/${tech.tech[i].name}.webp');"`
if (tech.tech[i].allowed() && (!tech.tech[i].isNonRefundable || localSettings.isJunkExperiment)) { // || tech.tech[i].name === "+1 cardinality") { //|| tech.tech[i].name === "leveraged investment"
if (tech.tech[i].isJunk) {
text += `<div id="tech-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'tech')"><div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[i].link}</div> ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
} else {
text += `<div id="tech-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'tech')"><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[i].link}</div> ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
}
} else {
text += `<div id="tech-${i}" class="experiment-grid-module experiment-grid-disabled"><div class="grid-title"> ${tech.tech[i].name}</div> ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
// text += `<div id="tech-${i}" class="experiment-grid-module experiment-grid-disabled"><div class="grid-title"> ${tech.tech[i].name}</div> ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
text += `<div id="tech-${i}" class="experiment-grid-module card-background" onclick="build.choosePowerUp(${i},'tech')" ${style}>`
} else { //disabled
text += `<div id="tech-${i}" class="experiment-grid-module card-background experiment-grid-disabled" ${style}>`
// text += `<div id="tech-${i}" class="experiment-grid-module card-background experiment-grid-disabled" onclick="build.choosePowerUp(${i},'tech')" ${style}>`
}
if (tech.tech[i].isJunk) {
text += build.junkTechText(i)
} else if (tech.tech[i].isGunTech) {
text += build.gunTechText(i)
} else if (tech.tech[i].isFieldTech) {
text += build.fieldTechText(i)
} else {
text += build.techText(i)
}
text += '</div>'
}
}
document.getElementById("experiment-grid").innerHTML = text
@@ -672,23 +742,26 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
url += `&field=${encodeURIComponent(m.fieldUpgrades[m.fieldMode].name.trim())}`
url += `&difficulty=${simulation.difficultyMode}`
if (isCustom) {
url += `&level=${Math.abs(Number(document.getElementById("starting-level").value))}`
url += `&noPower=${Number(document.getElementById("no-power-ups").checked)}`
// url += `&level=${Math.abs(Number(document.getElementById("starting-level").value))}`
// alert('n-gon build URL copied to clipboard.\nPaste into browser address bar.')
} else {
simulation.makeTextLog("n-gon build URL copied to clipboard.<br>Paste into browser address bar.")
}
console.log('n-gon build URL copied to clipboard.\nPaste into browser address bar.')
console.log(url)
navigator.clipboard.writeText(url).then(function() {
navigator.clipboard.writeText(url).then(function () {
/* clipboard successfully set */
if (isCustom) {
setTimeout(function() { alert('n-gon build URL copied to clipboard.\nPaste into browser address bar.') }, 300);
setTimeout(function () {
alert('n-gon build URL copied to clipboard.\nPaste into browser address bar.')
}, 300);
}
}, function() {
}, function () {
/* clipboard write failed */
if (isCustom) {
setTimeout(function() { alert('copy failed') }, 300);
setTimeout(function () {
alert('copy failed')
}, 300);
}
console.log('copy failed')
});
@@ -705,23 +778,6 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
}
for (let i = 0; i < bullet.length; ++i) Matter.Composite.remove(engine.world, bullet[i]);
bullet = []; //remove any bullets that might have spawned from tech
const levelsCleared = Math.abs(Number(document.getElementById("starting-level").value) - 1)
level.difficultyIncrease(Math.min(99, levelsCleared * simulation.difficultyMode)) //increase difficulty based on modes
level.levelsCleared += levelsCleared;
simulation.isNoPowerUps = document.getElementById("no-power-ups").checked
if (simulation.isNoPowerUps) { //remove tech, guns, and fields
function removeOne() { //recursive remove one at a time to avoid array problems
for (let i = 0; i < powerUp.length; i++) {
if (powerUp[i].name === "tech" || powerUp[i].name === "gun" || powerUp[i].name === "field") {
Matter.Composite.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1);
removeOne();
break
}
}
}
removeOne();
}
build.hasExperimentalMode = false
if (!simulation.isCheating) {
for (let i = 0, len = tech.tech.length; i < len; i++) {
@@ -928,14 +984,14 @@ document.getElementById("control-table").addEventListener('click', (event) => {
window.addEventListener("keydown", input.setKeys);
}
});
document.getElementById("control-details").addEventListener("toggle", function() {
document.getElementById("control-details").addEventListener("toggle", function () {
input.controlTextUpdate()
input.endKeySensing();
})
document.getElementById("control-reset").addEventListener('click', input.setDefault);
window.addEventListener("keyup", function(event) {
window.addEventListener("keyup", function (event) {
switch (event.code) {
case input.key.right:
case "ArrowRight":
@@ -962,7 +1018,7 @@ window.addEventListener("keyup", function(event) {
}
});
window.addEventListener("keydown", function(event) {
window.addEventListener("keydown", function (event) {
// console.log(event.code)
switch (event.code) {
case input.key.right:
@@ -999,7 +1055,7 @@ window.addEventListener("keydown", function(event) {
case input.key.pause:
if (!simulation.isChoosing && input.isPauseKeyReady && m.alive) {
input.isPauseKeyReady = false
setTimeout(function() {
setTimeout(function () {
input.isPauseKeyReady = true
}, 300);
if (simulation.paused) {
@@ -1027,7 +1083,12 @@ window.addEventListener("keydown", function(event) {
}
}
m.energy = energy //return to current energy
document.getElementById("pause-field").innerHTML = `<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[m.fieldMode].name}</div> ${m.fieldUpgrades[m.fieldMode].description}`
// document.getElementById("pause-field").innerHTML = `<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[m.fieldMode].name}</div> ${m.fieldUpgrades[m.fieldMode].description}`
document.getElementById("pause-field").style.backgroundImage = `url('img/field/${m.fieldUpgrades[m.fieldMode].name}${m.fieldMode === 0 ? Math.floor(Math.random()*10) : ""}.webp')`
document.getElementById("pause-field").innerHTML = `
<div class="card-text" style = "animation: fieldColorCycle 1s linear infinite alternate;">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div>
${m.fieldUpgrades[m.fieldMode].description}</div>`
});
}
}
@@ -1210,8 +1271,12 @@ window.addEventListener("keydown", function(event) {
break
case "j":
for (let i = 0, len = mob.length; i < len; ++i) mob[i].damage(Infinity, true)
setTimeout(() => { for (let i = 0, len = mob.length; i < len; ++i) mob[i].damage(Infinity, true) }, 100);
setTimeout(() => { for (let i = 0, len = mob.length; i < len; ++i) mob[i].damage(Infinity, true) }, 200);
setTimeout(() => {
for (let i = 0, len = mob.length; i < len; ++i) mob[i].damage(Infinity, true)
}, 100);
setTimeout(() => {
for (let i = 0, len = mob.length; i < len; ++i) mob[i].damage(Infinity, true)
}, 200);
break
case "l":
document.getElementById("field").style.display = "none"
@@ -1312,7 +1377,9 @@ if (localstorageCheck()) {
}
} else {
console.log("localStorage is disabled")
localSettings = { isAllowed: false }
localSettings = {
isAllowed: false
}
}
if (localSettings.isAllowed && !localSettings.isEmpty) {
@@ -1358,6 +1425,9 @@ if (localSettings.isAllowed && !localSettings.isEmpty) {
localSettings.loreCount = 0; //this sets what conversation is heard
if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
}
if (localSettings.isHideImages === undefined) localSettings.isHideImages = false //default to show images
document.getElementById("hide-images").checked = localSettings.isHideImages
} else {
console.log('setting default localSettings')
@@ -1377,11 +1447,13 @@ if (localSettings.isAllowed && !localSettings.isEmpty) {
isLoreDoesNotNeedReset: false,
isHuman: false,
key: undefined,
isHideImages: false, //default to show images
};
input.setDefault()
if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
document.getElementById("community-maps").checked = localSettings.isCommunityMaps
simulation.isCommunityMaps = localSettings.isCommunityMaps
document.getElementById("hide-images").checked = localSettings.isHideImages
document.getElementById("difficulty-select").value = localSettings.difficultyMode
document.getElementById("fps-select").value = localSettings.fpsCapDefault
document.getElementById("banned").value = localSettings.banList
@@ -1427,10 +1499,10 @@ document.getElementById("difficulty-select").addEventListener("input", () => {
});
document.getElementById("updates").addEventListener("toggle", function() {
document.getElementById("updates").addEventListener("toggle", function () {
function loadJSON(path, success, error) { //generic function to get JSON
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
if (success)
@@ -1449,7 +1521,7 @@ document.getElementById("updates").addEventListener("toggle", function() {
/// https://api.github.com/repos/landgreen/n-gon/stats/commit_activity
loadJSON('https://api.github.com/repos/landgreen/n-gon/commits',
function(data) {
function (data) {
// console.log(data)
for (let i = 0, len = 20; i < len; i++) {
text += "<strong>" + data[i].commit.author.date.substr(0, 10) + "</strong> - "; //+ "<br>"
@@ -1458,7 +1530,7 @@ document.getElementById("updates").addEventListener("toggle", function() {
}
document.getElementById("updates-div").innerHTML = text.replace(/\n/g, "<br />")
},
function(xhr) {
function (xhr) {
console.error(xhr);
}
);
@@ -1498,6 +1570,55 @@ const sound = {
// return audioCtx
}
}
// preload images so they load cleaner
// MDN Scripting and preloads - https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload
// if (!localSettings.isHideImages) {
// for (let i = 0, len = b.guns.length; i < len; i++) {
// const preloadLink = document.createElement("link");
// preloadLink.href = "img/gun/" + b.guns[i].name + ".webp";
// preloadLink.rel = "preload";
// preloadLink.as = "image";
// document.head.appendChild(preloadLink);
// }
// for (let i = 1, len = m.fieldUpgrades.length; i < len; i++) {
// const preloadLink = document.createElement("link");
// preloadLink.href = "img/field/" + m.fieldUpgrades[i].name + ".webp";
// preloadLink.rel = "preload";
// preloadLink.as = "image";
// document.head.appendChild(preloadLink);
// }
// for (let i = 0, len = tech.tech.length; i < len; i++) {
// if (!tech.tech[i].isJunk) {
// const preloadLink = document.createElement("link");
// preloadLink.href = "img/" + tech.tech[i].name + ".webp";
// preloadLink.rel = "preload";
// preloadLink.as = "image";
// document.head.appendChild(preloadLink);
// }
// }
// }
//preload images early
if (!localSettings.isHideImages) {
addEventListener("load", () => {
let urls = new Array()
for (let i = 0, len = b.guns.length; i < len; i++) urls.push("img/gun/" + b.guns[i].name + ".webp")
for (let i = 1, len = m.fieldUpgrades.length; i < len; i++) urls.push("img/field/" + m.fieldUpgrades[i].name + ".webp")
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (!tech.tech[i].isJunk) urls.push("img/" + tech.tech[i].name + ".webp")
}
let images = new Array()
for (let i = 0; i < urls.length; i++) {
images[i] = new Image()
images[i].src = urls[i]
}
// console.log(urls, images)
});
}
//**********************************************************************
// main loop
//**********************************************************************

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1192,6 +1192,26 @@ const mobs = {
this.alive = false; //triggers mob removal in mob[i].replace(i)
if (this.isDropPowerUp) {
// if (true) { //spawn zombie on death
// // console.log(this)
// this.leaveBody = false;
// let count = 45 //delay spawn cycles
// let cycle = () => {
// if (count > 0) {
// if (m.alive) requestAnimationFrame(cycle);
// if (!simulation.paused && !simulation.isChoosing) {
// count--
// }
// } else {
// spawn.zombie(this.position.x, this.position.y, this.radius, this.vertices.length, this.fill) // zombie(x, y, radius, sides, color)
// }
// }
// requestAnimationFrame(cycle);
// }
if (tech.iceIXOnDeath && this.isSlowed) {
for (let i = 0, len = 2 * Math.sqrt(Math.min(this.mass, 25)) * tech.iceIXOnDeath; i < len; i++) b.iceIX(3, Math.random() * 2 * Math.PI, this.position)
}

View File

@@ -423,7 +423,7 @@ const m = {
m.health = 1;
// m.addHealth(1)
simulation.wipe = function() { //set wipe to have trails
simulation.wipe = function () { //set wipe to have trails
ctx.fillStyle = "rgba(255,255,255,0)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
@@ -433,8 +433,8 @@ const m = {
m.switchWorlds()
const swapPeriod = 1000
for (let i = 0, len = 5; i < len; i++) {
setTimeout(function() {
simulation.wipe = function() { //set wipe to have trails
setTimeout(function () {
simulation.wipe = function () { //set wipe to have trails
ctx.fillStyle = "rgba(255,255,255,0)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
@@ -444,14 +444,14 @@ const m = {
simulation.isTextLogOpen = true;
simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> 0.${len - i - 1}`, swapPeriod);
simulation.isTextLogOpen = false;
simulation.wipe = function() { //set wipe to have trails
simulation.wipe = function () { //set wipe to have trails
ctx.fillStyle = `rgba(255,255,255,${(i + 1) * (i + 1) * 0.006})`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
}, (i + 1) * swapPeriod);
}
setTimeout(function() {
simulation.wipe = function() { //set wipe to normal
setTimeout(function () {
simulation.wipe = function () { //set wipe to normal
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
simulation.isTextLogOpen = true;
@@ -467,7 +467,7 @@ const m = {
document.getElementById("text-log").style.opacity = 0; //fade out any active text logs
document.getElementById("fade-out").style.opacity = 0.9; //slowly fade to 90% white on top of canvas
// build.shareURL(false)
setTimeout(function() {
setTimeout(function () {
Composite.clear(engine.world);
Engine.clear(engine);
simulation.splashReturn();
@@ -487,7 +487,10 @@ const m = {
fieldIndex: m.fieldMode,
gunIndexes: gunList,
techIndexes: techList,
position: { x: m.pos.x, y: m.pos.y },
position: {
x: m.pos.x,
y: m.pos.y
},
levelName: level.levels[level.onLevel],
isHorizontalFlipped: simulation.isHorizontalFlipped
}
@@ -572,7 +575,10 @@ const m = {
if (m.immuneCycle < immunityCycle) m.immuneCycle = immunityCycle; //player is immune to damage until after grenades might explode...
for (let i = 1, len = Math.floor(4 + steps / 40); i < len; i++) {
b.grenade(Vector.add(m.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -i * Math.PI / len) //fire different angles for each grenade
b.grenade(Vector.add(m.pos, {
x: 10 * (Math.random() - 0.5),
y: 10 * (Math.random() - 0.5)
}), -i * Math.PI / len) //fire different angles for each grenade
const who = bullet[bullet.length - 1]
if (tech.isNeutronBomb) {
@@ -601,7 +607,10 @@ const m = {
let history = m.history[(m.cycle - steps) % 600]
Matter.Body.setPosition(player, history.position);
Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
Matter.Body.setVelocity(player, {
x: history.velocity.x,
y: history.velocity.y
});
m.yOff = history.yOff
if (m.yOff < 48) {
m.doCrouch()
@@ -623,14 +632,17 @@ const m = {
x: 250 * (Math.random() - 0.5),
y: 250 * (Math.random() - 0.5)
}));
Matter.Body.setVelocity(bullet[i], { x: 0, y: 0 });
Matter.Body.setVelocity(bullet[i], {
x: 0,
y: 0
});
}
}
m.energy = Math.max(m.energy - steps / 200, 0.01)
if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles
let isDrawPlayer = true
const shortPause = function() {
const shortPause = function () {
if (m.defaultFPSCycle < m.cycle) { //back to default values
simulation.fpsCap = simulation.fpsCapDefault
simulation.fpsInterval = 1000 / simulation.fpsCap;
@@ -687,7 +699,10 @@ const m = {
if (tech.isDroneOnDamage && bullet.length < 150) { //chance to build a drone on damage from tech
const len = Math.min((dmg - 0.06 * Math.random()) * 40, 40) / tech.droneEnergyReduction
for (let i = 0; i < len; i++) {
if (Math.random() < 0.5) b.drone({ x: m.pos.x + 30 * Math.cos(m.angle) + 100 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 100 * (Math.random() - 0.5) }) //spawn drone
if (Math.random() < 0.5) b.drone({
x: m.pos.x + 30 * Math.cos(m.angle) + 100 * (Math.random() - 0.5),
y: m.pos.y + 30 * Math.sin(m.angle) + 100 * (Math.random() - 0.5)
}) //spawn drone
}
}
if (tech.isEnergyHealth) {
@@ -701,13 +716,13 @@ const m = {
for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "heal", false);
m.energy = m.maxEnergy
if (m.immuneCycle < m.cycle + 300) m.immuneCycle = m.cycle + 300 //disable this.immuneCycle bonus seconds
simulation.wipe = function() { //set wipe to have trails
simulation.wipe = function () { //set wipe to have trails
ctx.fillStyle = "rgba(255,255,255,0.03)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
setTimeout(function() {
setTimeout(function () {
tech.maxDuplicationEvent()
simulation.wipe = function() { //set wipe to normal
simulation.wipe = function () { //set wipe to normal
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
}, 3000);
@@ -730,13 +745,13 @@ const m = {
<br>${powerUps.research.count}`)
for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "heal", false);
if (m.immuneCycle < m.cycle + 300) m.immuneCycle = m.cycle + 300 //disable this.immuneCycle bonus seconds
simulation.wipe = function() { //set wipe to have trails
simulation.wipe = function () { //set wipe to have trails
ctx.fillStyle = "rgba(255,255,255,0.03)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
setTimeout(function() {
setTimeout(function () {
tech.maxDuplicationEvent()
simulation.wipe = function() { //set wipe to normal
simulation.wipe = function () { //set wipe to normal
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
}, 3000);
@@ -756,7 +771,7 @@ const m = {
if (dmg > 0.06 / m.holdingMassScale) m.drop(); //drop block if holding // m.holdingMassScale = 0.5 for most fields
if (m.isCloak) m.fireCDcycle = m.cycle //forced exit cloak
}
const normalFPS = function() {
const normalFPS = function () {
if (m.defaultFPSCycle < m.cycle) { //back to default values
simulation.fpsCap = simulation.fpsCapDefault
simulation.fpsInterval = 1000 / simulation.fpsCap;
@@ -1043,7 +1058,7 @@ const m = {
ctx.fillRect(xOff, yOff, range * m.energy, 10);
}
},
drawRegenEnergyCloaking: function() {
drawRegenEnergyCloaking: function () {
if (m.energy < m.maxEnergy) { // replaces m.drawRegenEnergy() with custom code
m.regenEnergy();
const xOff = m.pos.x - m.radius * m.maxEnergy
@@ -1075,11 +1090,11 @@ const m = {
m.fieldRegen *= 0.6
}
},
regenEnergy: function() { //used in drawRegenEnergy // rewritten by some tech
regenEnergy: function () { //used in drawRegenEnergy // rewritten by some tech
if (m.immuneCycle < m.cycle) m.energy += m.fieldRegen;
if (m.energy < 0) m.energy = 0
},
regenEnergyDefault: function() {
regenEnergyDefault: function () {
if (m.immuneCycle < m.cycle) m.energy += m.fieldRegen;
if (m.energy < 0) m.energy = 0
},
@@ -1220,7 +1235,10 @@ const m = {
const cycles = 30
const charge = Math.min(m.throwCharge / 5, 1)
const speed = 80 * charge * Math.min(0.85, 0.8 / Math.pow(m.holdingTarget.mass, 0.25));
const v = { x: speed * Math.cos(m.angle), y: speed * Math.sin(m.angle) } //m.Vy / 2 + removed to make the path less jerky
const v = {
x: speed * Math.cos(m.angle),
y: speed * Math.sin(m.angle)
} //m.Vy / 2 + removed to make the path less jerky
ctx.beginPath()
for (let i = 1, len = 10; i < len + 1; i++) {
const time = cycles * i / len
@@ -1261,7 +1279,7 @@ const m = {
m.holdingTarget.friction = m.holdingTarget.frictionStatic = m.holdingTarget.frictionAir = 0.001
}
//check every second to see if player is away from thrown body, and make solid
const solid = function(that) {
const solid = function (that) {
const dx = that.position.x - player.position.x;
const dy = that.position.y - player.position.y;
if (that.speed < 3 && dx * dx + dy * dy > 10000 && that !== m.holdingTarget) {
@@ -1293,7 +1311,7 @@ const m = {
m.definePlayerMass() //return to normal player mass
if (tech.isAddBlockMass) {
const expand = function(that, massLimit) {
const expand = function (that, massLimit) {
if (that.mass < massLimit) {
const scale = 1.05;
Matter.Body.scale(that, scale, scale);
@@ -1409,7 +1427,10 @@ const m = {
}
const unit = Vector.normalise(Vector.sub(player.position, who.position))
if (tech.blockDmg) {
Matter.Body.setVelocity(who, { x: 0.5 * who.velocity.x, y: 0.5 * who.velocity.y });
Matter.Body.setVelocity(who, {
x: 0.5 * who.velocity.x,
y: 0.5 * who.velocity.y
});
if (who.isShielded) {
for (let i = 0, len = mob.length; i < len; i++) {
@@ -1675,10 +1696,9 @@ const m = {
fieldUpgrades: [{
name: "field emitter",
description: `use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs
<br><strong>100</strong> max <strong class='color-f'>energy</strong>
<br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second`,
<br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second`, // <br><strong>100</strong> max <strong class='color-f'>energy</strong>
effect: () => {
m.hold = function() {
m.hold = function () {
if (m.isHolding) {
m.drawHold(m.holdingTarget);
m.holding();
@@ -1776,7 +1796,7 @@ const m = {
} else {
m.harmonicShield = m.harmonicAtomic
}
m.hold = function() {
m.hold = function () {
if (m.isHolding) {
m.drawHold(m.holdingTarget);
m.holding();
@@ -1819,7 +1839,10 @@ const m = {
m.fieldShieldingScale = 0;
m.fieldBlockCD = 3;
m.grabPowerUpRange2 = 10000000
m.fieldPosition = { x: m.pos.x, y: m.pos.y }
m.fieldPosition = {
x: m.pos.x,
y: m.pos.y
}
m.fieldAngle = m.angle
m.perfectPush = (isFree = false) => {
if (m.fieldCDcycle < m.cycle) {
@@ -1827,7 +1850,10 @@ const m = {
if (
Vector.magnitude(Vector.sub(mob[i].position, m.fieldPosition)) - mob[i].radius < m.fieldRange &&
!mob[i].isUnblockable &&
Vector.dot({ x: Math.cos(m.fieldAngle), y: Math.sin(m.fieldAngle) }, Vector.normalise(Vector.sub(mob[i].position, m.fieldPosition))) > m.fieldThreshold &&
Vector.dot({
x: Math.cos(m.fieldAngle),
y: Math.sin(m.fieldAngle)
}, Vector.normalise(Vector.sub(mob[i].position, m.fieldPosition))) > m.fieldThreshold &&
Matter.Query.ray(map, mob[i].position, m.fieldPosition).length === 0
) {
mob[i].locatePlayer();
@@ -1838,12 +1864,18 @@ const m = {
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) }))
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
Matter.Body.setVelocity(mob[i], { x: 0.5 * mob[i].velocity.x, y: 0.5 * mob[i].velocity.y });
Matter.Body.setVelocity(mob[i], {
x: 0.5 * mob[i].velocity.x,
y: 0.5 * mob[i].velocity.y
});
if (mob[i].isShielded) {
for (let j = 0, len = mob.length; j < len; j++) {
@@ -1944,7 +1976,7 @@ const m = {
}
}
}
m.hold = function() {
m.hold = function () {
const wave = Math.sin(m.cycle * 0.022);
m.fieldRange = 180 + 12 * wave + 100 * tech.isBigField
m.fieldArc = 0.35 + 0.045 * wave + 0.065 * tech.isBigField //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
@@ -1957,7 +1989,10 @@ const m = {
//float while field is on
if (player.velocity.y > 1) {
player.force.y -= (tech.isBigField ? 0.87 : 0.7) * player.mass * simulation.g;
Matter.Body.setVelocity(player, { x: player.velocity.x, y: 0.98 * player.velocity.y }); //set velocity to cap, but keep the direction
Matter.Body.setVelocity(player, {
x: player.velocity.x,
y: 0.98 * player.velocity.y
}); //set velocity to cap, but keep the direction
}
@@ -1966,7 +2001,10 @@ const m = {
if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen
m.grabPowerUp();
m.lookForPickUp();
m.fieldPosition = { x: m.pos.x, y: m.pos.y }
m.fieldPosition = {
x: m.pos.x,
y: m.pos.y
}
m.fieldAngle = m.angle
//draw field attached to player
if (m.holdingTarget) {
@@ -2046,7 +2084,7 @@ const m = {
m.fieldHarmReduction = 0.45; //55% reduction
m.fieldDrawRadius = 0;
m.hold = function() {
m.hold = function () {
m.airSpeedLimit = 125 //5 * player.mass * player.mass
m.FxAir = 0.016
if (m.isHolding) {
@@ -2196,7 +2234,7 @@ const m = {
effect: () => {
m.fieldMeterColor = "#ff0"
m.eyeFillColor = m.fieldMeterColor
m.hold = function() {
m.hold = function () {
if (m.energy > m.maxEnergy - 0.02 && m.fieldCDcycle < m.cycle && !input.field && bullet.length < 300 && (m.cycle % 2)) {
if (simulation.molecularMode === 0) {
if (tech.isSporeFlea) {
@@ -2204,13 +2242,22 @@ const m = {
if (m.energy > drain) {
m.energy -= drain
const speed = m.crouch ? 20 + 8 * Math.random() : 10 + 3 * Math.random()
b.flea({ x: m.pos.x + 35 * Math.cos(m.angle), y: m.pos.y + 35 * Math.sin(m.angle) }, { x: speed * Math.cos(m.angle), y: speed * Math.sin(m.angle) })
b.flea({
x: m.pos.x + 35 * Math.cos(m.angle),
y: m.pos.y + 35 * Math.sin(m.angle)
}, {
x: speed * Math.cos(m.angle),
y: speed * Math.sin(m.angle)
})
}
} else if (tech.isSporeWorm) {
const drain = 0.18 + (Math.max(bullet.length, 130) - 130) * 0.02
if (m.energy > drain) {
m.energy -= drain
b.worm({ x: m.pos.x + 35 * Math.cos(m.angle), y: m.pos.y + 35 * Math.sin(m.angle) })
b.worm({
x: m.pos.x + 35 * Math.cos(m.angle),
y: m.pos.y + 35 * Math.sin(m.angle)
})
const SPEED = 2 + 1 * Math.random();
Matter.Body.setVelocity(bullet[bullet.length - 1], {
x: SPEED * Math.cos(m.angle),
@@ -2218,9 +2265,9 @@ const m = {
});
}
} else {
const drain = 0.1 + (Math.max(bullet.length, 130) - 130) * 0.01
const drain = 0.095 + (Math.max(bullet.length, 130) - 130) * 0.01
for (let i = 0, len = Math.random() * 20; i < len; i++) {
if (m.energy > drain) {
if (m.energy > 3 * drain) {
m.energy -= drain
b.spore(m.pos)
} else {
@@ -2235,10 +2282,12 @@ const m = {
y: Math.sin(m.angle)
}
const push = Vector.mult(Vector.perp(direction), 0.08)
b.missile({ x: m.pos.x + 30 * direction.x, y: m.pos.y + 30 * direction.y }, m.angle, -15)
b.missile({
x: m.pos.x + 30 * direction.x,
y: m.pos.y + 30 * direction.y
}, m.angle, -15)
bullet[bullet.length - 1].force.x += push.x * (Math.random() - 0.5)
bullet[bullet.length - 1].force.y += 0.005 + push.y * (Math.random() - 0.5)
// b.missile({ x: m.pos.x, y: m.pos.y - 40 }, -Math.PI / 2 + 0.5 * (Math.random() - 0.5), 0, 1)
} else if (simulation.molecularMode === 2) {
m.energy -= 0.045;
@@ -2248,7 +2297,10 @@ const m = {
const drain = 0.8 + (Math.max(bullet.length, 50) - 50) * 0.01
if (m.energy > drain) {
m.energy -= drain
b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 25)
b.droneRadioactive({
x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5),
y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5)
}, 25)
}
} else {
//every bullet above 100 adds 0.005 to the energy cost per drone
@@ -2367,7 +2419,10 @@ const m = {
radiusLimit: 10,
damage: 0.8,
setPositionToNose() {
const nose = { x: m.pos.x + 10 * Math.cos(m.angle), y: m.pos.y + 10 * Math.sin(m.angle) }
const nose = {
x: m.pos.x + 10 * Math.cos(m.angle),
y: m.pos.y + 10 * Math.sin(m.angle)
}
Matter.Body.setPosition(this, Vector.add(nose, Vector.mult(Vector.normalise(Vector.sub(nose, m.pos)), circleRadiusScale * this.circleRadius)));
},
fire() {
@@ -2531,7 +2586,10 @@ const m = {
ctx.arc(this.position.x, this.position.y, radius, 0, 2 * Math.PI);
ctx.fill();
//draw arcs
const unit = Vector.rotate({ x: 1, y: 0 }, Math.random() * 6.28)
const unit = Vector.rotate({
x: 1,
y: 0
}, Math.random() * 6.28)
let len = 8
const step = this.circleRadius / len
let x = this.position.x
@@ -2563,7 +2621,7 @@ const m = {
Composite.add(engine.world, m.plasmaBall);
// m.plasmaBall.startingVertices = m.plasmaBall.vertices.slice();
m.hold = function() {
m.hold = function () {
if (m.isHolding) {
m.drawHold(m.holdingTarget);
m.holding();
@@ -2654,7 +2712,7 @@ const m = {
m.plasmaBall.do()
}
} else if (tech.isExtruder) {
m.hold = function() {
m.hold = function () {
b.isExtruderOn = false
if (m.isHolding) {
m.drawHold(m.holdingTarget);
@@ -2696,7 +2754,7 @@ const m = {
ctx.stroke();
}
} else {
m.hold = function() {
m.hold = function () {
if (m.isHolding) {
m.drawHold(m.holdingTarget);
m.holding();
@@ -2760,8 +2818,8 @@ const m = {
if (tech.isRewindField) {
this.rewindCount = 0
m.grabPowerUpRange2 = 300000
m.hold = function() {
console.log(m.fieldCDcycle)
m.hold = function () {
// console.log(m.fieldCDcycle)
m.grabPowerUp();
// //grab power ups
// for (let i = 0, len = powerUp.length; i < len; ++i) {
@@ -2808,7 +2866,10 @@ const m = {
m.energy -= DRAIN
if (m.immuneCycle < m.cycle + 60) m.immuneCycle = m.cycle + 60; //player is immune to damage for __ cycles
Matter.Body.setPosition(player, history.position);
Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
Matter.Body.setVelocity(player, {
x: history.velocity.x,
y: history.velocity.y
});
if (m.health < history.health) {
m.health = history.health
if (m.health > m.maxHealth) m.health = m.maxHealth
@@ -2853,7 +2914,7 @@ const m = {
} else {
m.fieldFire = true;
m.isBodiesAsleep = false;
m.hold = function() {
m.hold = function () {
if (m.isHolding) {
m.wakeCheck();
m.drawHold(m.holdingTarget);
@@ -2920,7 +2981,7 @@ const m = {
m.isSneakAttack = true;
m.sneakAttackCycle = 0;
m.enterCloakCycle = 0;
m.drawCloak = function() {
m.drawCloak = function () {
m.fieldPhase += 0.007
const wiggle = 0.15 * Math.sin(m.fieldPhase * 0.5)
ctx.beginPath();
@@ -2934,7 +2995,7 @@ const m = {
ctx.globalCompositeOperation = "source-over";
ctx.clip();
}
m.hold = function() {
m.hold = function () {
if (m.isHolding) {
m.drawHold(m.holdingTarget);
m.holding();
@@ -2951,7 +3012,7 @@ const m = {
//not shooting (or using field) enable cloak
if (m.energy < 0.05 && m.fireCDcycle < m.cycle && !input.fire) m.fireCDcycle = m.cycle
if (m.fireCDcycle + 30 < m.cycle && !input.fire) { //automatically cloak if not firing
const drain = 0.1
const drain = 0.05
if (!m.isCloak && m.energy > drain + 0.05) {
m.energy -= drain
m.isCloak = true //enter cloak
@@ -3214,7 +3275,7 @@ const m = {
m.fieldOn = false;
m.fieldRadius = 0;
m.drop();
m.hold = function() {
m.hold = function () {
if (input.field) {
if (m.fieldCDcycle < m.cycle) {
const scale = 25
@@ -3398,7 +3459,7 @@ const m = {
//<strong class='color-worm'>wormholes</strong> attract <strong class='color-block'>blocks</strong> and power ups<br>
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong>+3%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
drain: 0,
effect: function() {
effect: function () {
m.fieldMeterColor = "#bbf" //"#0c5"
m.eyeFillColor = m.fieldMeterColor
@@ -3406,7 +3467,7 @@ const m = {
m.fieldRange = 0
powerUps.setDupChance(); //needed after adjusting duplication chance
m.hold = function() {
m.hold = function () {
// m.hole = { //this is reset with each new field, but I'm leaving it here for reference
// isOn: false,
// isReady: true,
@@ -3512,7 +3573,10 @@ const m = {
m.fieldRange *= 0.8
if ((m.fieldMode === 0 || m.fieldMode === 9) && m.immuneCycle < m.cycle) m.energy += 0.2 * m.coupling
if (tech.isWormholeWorms) { //pandimensional spermia
b.worm(Vector.add(m.hole.pos2, Vector.rotate({ x: m.fieldRange * 0.4, y: 0 }, 2 * Math.PI * Math.random())))
b.worm(Vector.add(m.hole.pos2, Vector.rotate({
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -10));
// for (let i = 0, len = Math.ceil(1.25 * Math.random()); i < len; i++) {
// }
@@ -3537,7 +3601,10 @@ const m = {
if ((m.fieldMode === 0 || m.fieldMode === 9) && m.immuneCycle < m.cycle) m.energy += 0.2 * m.coupling
if (m.fieldMode === 0 || m.fieldMode === 9) m.energy += 0.2 * m.coupling
if (tech.isWormholeWorms) { //pandimensional spermia
b.worm(Vector.add(m.hole.pos1, Vector.rotate({ x: m.fieldRange * 0.4, y: 0 }, 2 * Math.PI * Math.random())))
b.worm(Vector.add(m.hole.pos1, Vector.rotate({
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), 5));
// for (let i = 0, len = Math.ceil(1.25 * Math.random()); i < len; i++) {
// }
@@ -3624,7 +3691,10 @@ const m = {
this.drain = tech.isFreeWormHole ? 0 : 0.06 + 0.006 * Math.sqrt(mag)
}
const unit = Vector.perp(Vector.normalise(sub))
const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
const where = {
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
}
m.fieldRange = 0.97 * m.fieldRange + 0.03 * (50 + 10 * Math.sin(simulation.cycle * 0.025))
const edge2a = Vector.add(Vector.mult(unit, 1.5 * m.fieldRange), simulation.mouseInGame)
const edge2b = Vector.add(Vector.mult(unit, -1.5 * m.fieldRange), simulation.mouseInGame)
@@ -3922,27 +3992,86 @@ const m = {
}
m.isShipMode = true
// simulation.isCheating = true
const points = [
{ x: 29.979168754143455, y: 4.748337243898336 },
{ x: 27.04503734408824, y: 13.7801138209198 },
{ x: 21.462582474874278, y: 21.462582475257523 },
{ x: 13.780113820536943, y: 27.045037344471485 },
{ x: 4.74833724351507, y: 29.979168754526473 },
{ x: -4.748337245049098, y: 29.979168754526473 },
{ x: -13.780113822071026, y: 27.045037344471485 },
{ x: -21.46258247640829, y: 21.462582475257523 },
{ x: -27.045037345621797, y: 13.7801138209198 },
{ x: -29.979168755677012, y: 4.748337243898336 },
{ x: -29.979168755677012, y: -4.7483372446656045 },
{ x: -27.045037345621797, y: -13.78011382168726 },
{ x: -21.46258247640829, y: -21.462582476024817 },
{ x: -13.780113822071026, y: -27.045037345239006 },
{ x: -4.748337245049098, y: -29.97916875529422 },
{ x: 4.74833724351507, y: -29.97916875529422 },
{ x: 13.780113820536943, y: -27.045037345239006 },
{ x: 21.462582474874278, y: -21.462582476024817 },
{ x: 27.04503734408824, y: -13.78011382168726 },
{ x: 29.979168754143455, y: -4.7483372446656045 }
const points = [{
x: 29.979168754143455,
y: 4.748337243898336
},
{
x: 27.04503734408824,
y: 13.7801138209198
},
{
x: 21.462582474874278,
y: 21.462582475257523
},
{
x: 13.780113820536943,
y: 27.045037344471485
},
{
x: 4.74833724351507,
y: 29.979168754526473
},
{
x: -4.748337245049098,
y: 29.979168754526473
},
{
x: -13.780113822071026,
y: 27.045037344471485
},
{
x: -21.46258247640829,
y: 21.462582475257523
},
{
x: -27.045037345621797,
y: 13.7801138209198
},
{
x: -29.979168755677012,
y: 4.748337243898336
},
{
x: -29.979168755677012,
y: -4.7483372446656045
},
{
x: -27.045037345621797,
y: -13.78011382168726
},
{
x: -21.46258247640829,
y: -21.462582476024817
},
{
x: -13.780113822071026,
y: -27.045037345239006
},
{
x: -4.748337245049098,
y: -29.97916875529422
},
{
x: 4.74833724351507,
y: -29.97916875529422
},
{
x: 13.780113820536943,
y: -27.045037345239006
},
{
x: 21.462582474874278,
y: -21.462582476024817
},
{
x: 27.04503734408824,
y: -13.78011382168726
},
{
x: 29.979168754143455,
y: -4.7483372446656045
}
]
//
Matter.Body.setVertices(player, Matter.Vertices.create(points, player))

View File

@@ -325,10 +325,10 @@ const powerUps = {
ctx.fillStyle = `rgba(221,221,221,0.6)`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
});
document.getElementById("pause-grid-right").style.opacity = "0.7"
document.getElementById("pause-grid-left").style.opacity = "0.7"
// document.getElementById("pause-grid-right").style.opacity = "0.7"
// document.getElementById("pause-grid-left").style.opacity = "0.7"
}
build.pauseGrid()
// build.pauseGrid()
},
endDraft(type, isCanceled = false) { //type should be a gun, tech, or field
if (isCanceled) {
@@ -372,7 +372,7 @@ const powerUps = {
// simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`)
// }
}
if (tech.isAnsatz && powerUps.research.count === 0) {
if (tech.isAnsatz && powerUps.research.count < 1) {
for (let i = 0; i < 2; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false);
}
// document.getElementById("choose-grid").style.display = "none"
@@ -572,11 +572,11 @@ const powerUps = {
const target = b.guns[b.activeGun]
if (target.ammo !== Infinity) {
if (tech.ammoCap) {
const ammoAdded = Math.ceil(target.ammoPack * 0.7 * tech.ammoCap) //0.7 is average
const ammoAdded = Math.ceil(target.ammoPack * 0.7 * tech.ammoCap * 0.8) //0.7 is average
target.ammo = ammoAdded
// simulation.makeTextLog(`${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>=</span> ${ammoAdded}`)
} else {
const ammoAdded = Math.ceil((0.7 * Math.random() + 0.7 * Math.random()) * target.ammoPack)
const ammoAdded = Math.ceil((0.7 * Math.random() + 0.7 * Math.random()) * target.ammoPack * 0.8)
target.ammo += ammoAdded
// simulation.makeTextLog(`${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>+=</span> ${ammoAdded}`)
}
@@ -619,6 +619,125 @@ const powerUps = {
}
}
},
cancelText(type) {
if (tech.isSuperDeterminism) {
return `<div></div>`
} else if (tech.isCancelTech) {
return `<div class='choose-grid-module' onclick='powerUps.endDraft("${type}",true)' style="width: 115px; text-align: center;font-size: 1.1em;font-weight: 100;justify-self: end;">randomize</div>`
} else {
return `<div class='choose-grid-module' onclick='powerUps.endDraft("${type}",true)' style="width: 82px; text-align: center;font-size: 1.1em;font-weight: 100;justify-self: end;">cancel</div>`
}
},
researchText(type) {
let text = ""
if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
text += `<div onclick="powerUps.research.use('${type}')" class='choose-grid-module' style="font-size: 1.1em;font-weight: 100;">` // style = "margin-left: 192px; margin-right: -192px;"
tech.junkResearchNumber = Math.ceil(4 * Math.random())
text += `<div><div> <span style="position:relative;">`
for (let i = 0; i < tech.junkResearchNumber; i++) text += `<div class="circle-grid junk" style="position:absolute; top:0; left:${15*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
text += `</span>&nbsp; <span class='research-select'>pseudoscience</span></div></div></div>`
} else if (powerUps.research.count > 0) {
text += `<div onclick="powerUps.research.use('${type}')" class='choose-grid-module' style="font-size: 1.1em;font-weight: 100;">` // style = "margin-left: 192px; margin-right: -192px;"
text += `<div><div><span style="position:relative;">`
for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `<div class="circle-grid research" style="position:absolute; top:0; left:${(18 - len*0.21)*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
text += `</span>&nbsp; <span class='research-select'>${tech.isResearchReality?"<span class='alt'>alternate reality</span>": "research"}</span></div></div></div>`
} else {
text += `<div></div>`
}
return text
},
hideStyle: `style="height:auto; border: none; background-color: transparent;"`,
gunText(choose, click) {
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/gun/${b.guns[choose].name}.webp');"`
return `<div class="choose-grid-module card-background" onclick="${click}" ${style}>
<div class="card-text">
<div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choose].name}</div>
${b.guns[choose].description}</div></div>`
},
fieldText(choose, click) {
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/field/${m.fieldUpgrades[choose].name}${choose === 0 ? Math.floor(Math.random()*10) : ""}.webp');"`
return `<div class="choose-grid-module card-background" onclick="${click}" ${style}>
<div class="card-text">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choose].name}</div>
${m.fieldUpgrades[choose].description}</div></div>`
},
techText(choose, click) {
const techCountText = tech.tech[choose].count > 1 ? `(${tech.tech[choose].count}x)` : "";
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/${tech.tech[choose].name}.webp');"`
return `<div class="choose-grid-module card-background" onclick="${click}" ${style}>
<div class="card-text">
<div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
},
fieldTechText(choose, click) {
const techCountText = tech.tech[choose].count > 1 ? `(${tech.tech[choose].count}x)` : "";
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/${tech.tech[choose].name}.webp');"`
return `<div class="choose-grid-module card-background" onclick="${click}" ${style}>
<div class="card-text">
<div class="grid-title">
<span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid field" style="position:absolute; top:0; left:10px;opacity:0.65;"></div>
</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
},
gunTechText(choose, click) {
const techCountText = tech.tech[choose].count > 1 ? `(${tech.tech[choose].count}x)` : "";
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/${tech.tech[choose].name}.webp');"`
return `<div class="choose-grid-module card-background" onclick="${click}" ${style}>
<div class="card-text">
<div class="grid-title">
<span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid gun" style="position:absolute; top:0; left:10px; opacity:0.65;"></div>
</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
},
junkTechText(choose, click) {
const techCountText = tech.tech[choose].count > 1 ? `(${tech.tech[choose].count}x)` : "";
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-size: contain;background-repeat: no-repeat;"`
if (!localSettings.isHideImages) {
setTimeout(() => { //pull image from web search if no url
if (tech.tech[choose].url === undefined) {
const url = "https://images.search.yahoo.com/search/images?p=" + tech.tech[choose].name;
fetch(url)
.then((response) => response.text())
.then((html) => {
const parser = new DOMParser();
const doc = parser.parseFromString(html, "text/html");
const elements = doc.getElementsByClassName("ld");
// console.log(JSON.parse(elements[i].getAttribute("data")).iurl)
tech.tech[choose].url = JSON.parse(elements[i].getAttribute("data")).iurl
document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
});
} else {
document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
}
}, 100);
}
return `<div id = "junk-${choose}" class="choose-grid-module card-background" onclick="${click}" ${style}>
<div class="card-text">
<div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
},
incoherentTechText(choose, click) {
// text += `<div class="choose-grid-module" style = "background-color: #efeff5; border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; margin: 1px; padding-top: 6px; padding-bottom: 6px;"><div class="grid-title">${tech.tech[choose].name} <span style = "color: #aaa;font-weight: normal;font-size:80%;">- incoherent</span></div></div>`
const techCountText = tech.tech[choose].count > 1 ? `(${tech.tech[choose].count}x)` : "";
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/${tech.tech[choose].name}.webp');"`
return `<div class="choose-grid-module card-background" ${style}>
<div class="card-text" style = "background-color: #efeff5;">
<div class="grid-title" style = "color: #ddd;font-weight: normal;">incoherent</div> <br> <br>
</div></div>`
},
gun: {
name: "gun",
color: "#26a",
@@ -627,14 +746,11 @@ const powerUps = {
},
effect() {
if (m.alive) {
let text = ""
if (!tech.isSuperDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft("gun",true)'>${tech.isCancelTech ? "?":"✕"}</div>`
text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>gun</h3>`
let options = [];
for (let i = 0; i < b.guns.length; i++) {
if (!b.guns[i].have) options.push(i);
}
let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2) + tech.extraChoices + (m.fieldUpgrades[m.fieldMode].name === "pilot wave"))
let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + (m.fieldUpgrades[m.fieldMode].name === "pilot wave")))
if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay
function removeOption(index) {
for (let i = 0; i < options.length; i++) {
@@ -651,9 +767,26 @@ const powerUps = {
}
for (let i = 0; i < b.guns.length; i++) b.guns[i].isRecentlyShown = false //reset recently shown back to zero
if (options.length > 0) {
let text = ""
if (totalChoices === 2) {
document.getElementById("choose-grid").style.gridTemplateColumns = "384px 384px"
text += powerUps.researchText('gun')
text += powerUps.cancelText('gun')
} else if (totalChoices === 1) {
document.getElementById("choose-grid").style.gridTemplateColumns = "384px"
text += powerUps.cancelText('gun')
text += powerUps.researchText('gun')
} else {
document.getElementById("choose-grid").style.gridTemplateColumns = "384px 384px 384px"
text += "<div></div>"
text += powerUps.researchText('gun')
text += powerUps.cancelText('gun')
}
for (let i = 0; i < totalChoices; i++) {
const choose = options[Math.floor(Math.seededRandom(0, options.length))] //pick an element from the array of options
text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choose})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choose].name}</div> ${b.guns[choose].description}</div>`
const choose = options[Math.floor(Math.seededRandom(0, options.length))] //pick an element from the array of options
// text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choose})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choose].name}</div> ${b.guns[choose].description}</div>`
text += powerUps.gunText(choose, `powerUps.choose('gun',${choose})`)
b.guns[choose].isRecentlyShown = true
removeOption(choose)
if (options.length < 1) break
@@ -664,96 +797,24 @@ const powerUps = {
if (tech.tech[i].isBotTech && tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed()) botTech.push(i)
}
if (botTech.length > 0) { //pick random bot tech
// const choose = botTech[Math.floor(Math.random() * botTech.length)];
// const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : "";
// text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title"> <span id = "cellular-rule-id${this.id}" style = "font-size: 150%;font-family: 'Courier New', monospace;">⭓▸●■</span> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
const choose = botTech[Math.floor(Math.random() * botTech.length)];
const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : "";
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title"> <span id = "cellular-rule-id${this.id}" style = "font-size: 150%;font-family: 'Courier New', monospace;">⭓▸●■</span> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
const techCountText = tech.tech[choose].count > 1 ? `(${tech.tech[choose].count}x)` : "";
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/${tech.tech[choose].name}.webp');"`
text += `<div class="choose-grid-module card-background" onclick="powerUps.choose('tech',${choose})" ${style}>
<div class="card-text">
<div class="grid-title"><span id = "cellular-rule-id${this.id}" style = "font-size: 150%;font-family: 'Courier New', monospace;">⭓▸●■</span> &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
}
}
if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
tech.junkResearchNumber = Math.ceil(4 * Math.random())
text += `<div class="choose-grid-module" onclick="powerUps.research.use('gun')"><div class="grid-title"> <span style="position:relative;">`
for (let i = 0; i < tech.junkResearchNumber; i++) text += `<div class="circle-grid junk" style="position:absolute; top:0; left:${15*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
text += `</span>&nbsp; <span class='research-select'>pseudoscience</span></div></div>`
} else if (powerUps.research.count) {
text += `<div class="choose-grid-module" onclick="powerUps.research.use('gun')"><div class="grid-title"> <span style="position:relative;">`
for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `<div class="circle-grid research" style="position:absolute; top:0; left:${(18 - len*0.3)*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
text += `</span>&nbsp; <span class='research-select'>${tech.isResearchReality?"<span class='alt'>alternate reality</span>": "research"}</span></div></div>`
}
if (tech.isOneGun && b.inventory.length > 0) text += `<div style = "color: #f24">replaces your current gun</div>`
document.getElementById("choose-grid").innerHTML = text
powerUps.showDraft();
}
}
},
// pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) {
// let options = [];
// for (let i = 0; i < who.length; i++) {
// if (!who[i].have && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) {
// options.push(i);
// }
// }
// //remove repeats from last selection
// const totalChoices = tech.isDeterminism ? 1 : 3 + tech.extraChoices * 2
// if (powerUps.gun.choiceLog.length > totalChoices || powerUps.gun.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.gun.choiceLog[powerUps.gun.choiceLog.length - 1 - i] === options[j]) {
// options.splice(j, 1) //remove previous choice from option pool
// break
// }
// }
// }
// }
// }
// if (options.length > 0) {
// return options[Math.floor(Math.seededRandom(0, options.length))]
// }
// },
// effectOld() {
// let choice1 = powerUps.gun.pick(b.guns)
// let choice2 = -1
// let choice3 = -1
// if (choice1 > -1) {
// let text = ""
// if (!tech.isSuperDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft("gun",true)'>${tech.isCancelTech ? "?":"✕"}</div>`
// text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>gun</h3>`
// text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice1})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice1].name}</div> ${b.guns[choice1].description}</div>`
// if (!tech.isDeterminism) {
// choice2 = powerUps.gun.pick(b.guns, choice1)
// if (choice2 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice2})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice2].name}</div> ${b.guns[choice2].description}</div>`
// choice3 = powerUps.gun.pick(b.guns, choice1, choice2)
// if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice3})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice3].name}</div> ${b.guns[choice3].description}</div>`
// }
// if (tech.extraChoices) {
// let choice4 = powerUps.gun.pick(b.guns, choice1, choice2, choice3)
// if (choice4 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice4})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice4].name}</div> ${b.guns[choice4].description}</div>`
// let choice5 = powerUps.gun.pick(b.guns, choice1, choice2, choice3, choice4)
// if (choice5 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice5})">
// <div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[choice5].name}</div> ${b.guns[choice5].description}</div>`
// powerUps.gun.choiceLog.push(choice4)
// powerUps.gun.choiceLog.push(choice5)
// }
// powerUps.gun.choiceLog.push(choice1)
// powerUps.gun.choiceLog.push(choice2)
// powerUps.gun.choiceLog.push(choice3)
// // if (powerUps.research.count) text += `<div class="choose-grid-module" onclick="powerUps.research.use('gun')"><div class="grid-title"><div class="circle-grid research"></div> &nbsp; research <span class="research-select">${powerUps.research.count}</span></div></div>`
// if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
// tech.junkResearchNumber = Math.floor(5 * Math.random())
// text += `<div class="choose-grid-module" onclick="powerUps.research.use('gun')"><div class="grid-title"> <span style="position:relative;">`
// for (let i = 0; i < tech.junkResearchNumber; i++) text += `<div class="circle-grid junk" style="position:absolute; top:0; left:${15*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
// text += `</span>&nbsp; <span class='research-select'>pseudoscience</span></div></div>`
// } else if (powerUps.research.count) {
// text += `<div class="choose-grid-module" onclick="powerUps.research.use('gun')"><div class="grid-title"> <span style="position:relative;">`
// for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `<div class="circle-grid research" style="position:absolute; top:0; left:${(18 - len*0.3)*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
// text += `</span>&nbsp; <span class='research-select'>${tech.isResearchReality?"<span class='alt'>alternate reality</span>": "research"}</span></div></div>`
// }
// if (tech.isOneGun && b.inventory.length > 0) text += `<div style = "color: #f24">replaces your current gun</div>`
// document.getElementById("choose-grid").innerHTML = text
// powerUps.showDraft();
// }
// }
},
field: {
name: "field",
@@ -763,15 +824,11 @@ const powerUps = {
},
effect() {
if (m.alive) {
let text = ""
if (!tech.isSuperDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft("field",true)'>${tech.isCancelTech ? "?":"✕"}</div>`
text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>field</h3>`
let options = [];
for (let i = 1; i < m.fieldUpgrades.length; i++) { //skip field emitter
if (i !== m.fieldMode) options.push(i);
}
let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2) + tech.extraChoices + (m.fieldUpgrades[m.fieldMode].name === "pilot wave"))
let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + (m.fieldUpgrades[m.fieldMode].name === "pilot wave")))
if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay
function removeOption(index) {
@@ -790,9 +847,25 @@ const powerUps = {
for (let i = 0; i < m.fieldUpgrades.length; i++) m.fieldUpgrades[i].isRecentlyShown = false //reset recently shown back to zero
if (options.length > 0 || tech.isExtraBotOption) {
let text = ""
if (totalChoices === 2) {
document.getElementById("choose-grid").style.gridTemplateColumns = "384px 384px"
text += powerUps.researchText('field')
text += powerUps.cancelText('field')
} else if (totalChoices === 1) {
document.getElementById("choose-grid").style.gridTemplateColumns = "384px"
text += powerUps.cancelText('field')
text += powerUps.researchText('field')
} else {
document.getElementById("choose-grid").style.gridTemplateColumns = "384px 384px 384px"
text += "<div></div>"
text += powerUps.researchText('field')
text += powerUps.cancelText('field')
}
for (let i = 0; i < totalChoices; i++) {
const choose = options[Math.floor(Math.seededRandom(0, options.length))] //pick an element from the array of options
text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choose})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choose].name}</div> ${m.fieldUpgrades[choose].description}</div>`
//text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choose})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choose].name}</div> ${m.fieldUpgrades[choose].description}</div>` //default
text += powerUps.fieldText(choose, `powerUps.choose('field',${choose})`)
m.fieldUpgrades[choose].isRecentlyShown = true
removeOption(choose)
if (options.length < 1) break
@@ -803,94 +876,23 @@ const powerUps = {
if (tech.tech[i].isBotTech && tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed()) botTech.push(i)
}
if (botTech.length > 0) { //pick random bot tech
// const choose = botTech[Math.floor(Math.random() * botTech.length)];
// const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : "";
// text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title"> <span id = "cellular-rule-id${this.id}" style = "font-size: 150%;font-family: 'Courier New', monospace;">⭓▸●■</span> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
const choose = botTech[Math.floor(Math.random() * botTech.length)];
const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : "";
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title"> <span id = "cellular-rule-id${this.id}" style = "font-size: 150%;font-family: 'Courier New', monospace;">⭓▸●■</span> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
const techCountText = tech.tech[choose].count > 1 ? `(${tech.tech[choose].count}x)` : "";
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/${tech.tech[choose].name}.webp');"`
text += `<div class="choose-grid-module card-background" onclick="powerUps.choose('tech',${choose})" ${style}>
<div class="card-text">
<div class="grid-title"><span id = "cellular-rule-id${this.id}" style = "font-size: 150%;font-family: 'Courier New', monospace;">⭓▸●■</span> &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
}
}
if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
tech.junkResearchNumber = Math.ceil(4 * Math.random())
text += `<div class="choose-grid-module" onclick="powerUps.research.use('field')"><div class="grid-title"> <span style="position:relative;">`
for (let i = 0; i < tech.junkResearchNumber; i++) text += `<div class="circle-grid junk" style="position:absolute; top:0; left:${15*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
text += `</span>&nbsp; <span class='research-select'>pseudoscience</span></div></div>`
} else if (powerUps.research.count) {
text += `<div class="choose-grid-module" onclick="powerUps.research.use('field')"><div class="grid-title"> <span style="position:relative;">`
for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `<div class="circle-grid research" style="position:absolute; top:0; left:${(18 - len*0.3)*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
text += `</span>&nbsp; <span class='research-select'>${tech.isResearchReality?"<span class='alt'>alternate reality</span>": "research"}</span></div></div>`
}
document.getElementById("choose-grid").innerHTML = text
powerUps.showDraft();
}
}
},
// pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) {
// let options = [];
// for (let i = 1; i < who.length; i++) {
// if (i !== m.fieldMode && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) options.push(i);
// }
// //remove repeats from last selection
// const totalChoices = tech.isDeterminism ? 1 : 3 + tech.extraChoices * 2
// if (powerUps.field.choiceLog.length > totalChoices || powerUps.field.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.field.choiceLog[powerUps.field.choiceLog.length - 1 - i] === options[j]) {
// options.splice(j, 1) //remove previous choice from option pool
// break
// }
// }
// }
// }
// }
// if (options.length > 0) {
// // return options[Math.floor(Math.random() * options.length)]
// return options[Math.floor(Math.seededRandom(0, options.length))]
// }
// },
// effectOld() {
// let choice1 = powerUps.field.pick(m.fieldUpgrades)
// let choice2 = -1
// let choice3 = -1
// if (choice1 > -1) {
// let text = ""
// if (!tech.isSuperDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft("field",true)'>${tech.isCancelTech ? "?":"✕"}</div>`
// text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>field</h3>`
// text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice1})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice1].name}</div> ${m.fieldUpgrades[choice1].description}</div>`
// powerUps.field.choiceLog.push(choice1)
// if (!tech.isDeterminism) {
// choice2 = powerUps.field.pick(m.fieldUpgrades, choice1)
// if (choice2 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice2})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice2].name}</div> ${m.fieldUpgrades[choice2].description}</div>`
// choice3 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2)
// if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice3})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice3].name}</div> ${m.fieldUpgrades[choice3].description}</div>`
// powerUps.field.choiceLog.push(choice2)
// powerUps.field.choiceLog.push(choice3)
// }
// if (tech.extraChoices) {
// let choice4 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2, choice3)
// if (choice4 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice4})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice4].name}</div> ${m.fieldUpgrades[choice4].description}</div>`
// let choice5 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2, choice3, choice4)
// if (choice5 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice5})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice5].name}</div> ${m.fieldUpgrades[choice5].description}</div>`
// powerUps.field.choiceLog.push(choice4)
// powerUps.field.choiceLog.push(choice5)
// }
// if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
// tech.junkResearchNumber = Math.floor(4 * Math.random())
// text += `<div class="choose-grid-module" onclick="powerUps.research.use('field')"><div class="grid-title"> <span style="position:relative;">`
// for (let i = 0; i < tech.junkResearchNumber; i++) text += `<div class="circle-grid junk" style="position:absolute; top:0; left:${15*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
// text += `</span>&nbsp; <span class='research-select'>pseudoscience</span></div></div>`
// } else if (powerUps.research.count) {
// text += `<div class="choose-grid-module" onclick="powerUps.research.use('field')"><div class="grid-title"> <span style="position:relative;">`
// for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `<div class="circle-grid research" style="position:absolute; top:0; left:${(18 - len*0.3)*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
// // text += `</span>&nbsp; <span class='research-select'>research</span></div></div>`
// text += `</span>&nbsp; <span class='research-select'>${tech.isResearchReality?"<span class='alt'>alternate reality</span>": "research"}</span></div></div>`
// }
// //(${powerUps.research.count})
// // text += `<div style = 'color:#fff'>${simulation.SVGrightMouse} activate the shield with the right mouse<br>fields shield you from damage <br>and let you pick up and throw blocks</div>`
// document.getElementById("choose-grid").innerHTML = text
// powerUps.showDraft();
// }
// }
},
tech: {
name: "tech",
@@ -900,14 +902,8 @@ const powerUps = {
},
effect() {
if (m.alive) {
let text = ""
if (!tech.isSuperDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft("tech",true)'>${tech.isCancelTech ? "?":"✕"}</div>`
text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>tech</h3>`
//used for junk estimation
let junkCount = 0
let totalCount = 0
let junkCount = 0 //used for junk estimation
let totalCount = 0 //used for junk estimation
let options = []; //generate all options
optionLengthNoDuplicates = 0
for (let i = 0; i < tech.tech.length; i++) {
@@ -928,19 +924,14 @@ const powerUps = {
if (options.length < 1) return;
}
}
//set total choices
let totalChoices = (tech.isDeterminism ? 1 : 3) + tech.extraChoices + (m.fieldUpgrades[m.fieldMode].name === "pilot wave")
let totalChoices = (tech.isDeterminism ? 1 : 3 + tech.extraChoices + (m.fieldUpgrades[m.fieldMode].name === "pilot wave"))
if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay
if (optionLengthNoDuplicates < totalChoices + 1) { //if not enough options for all the choices
// console.log('if not enough options for all the choices')
totalChoices = optionLengthNoDuplicates
if (tech.isBanish) { //when you run out of options eject banish
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].name === "decoherence") {
// console.log(i)
powerUps.ejectTech(i, true)
}
if (tech.tech[i].name === "decoherence") powerUps.ejectTech(i, true)
}
simulation.makeTextLog(`decoherence <span class='color-var'>tech</span> ejected`)
simulation.makeTextLog(`options reset`)
@@ -950,15 +941,10 @@ const powerUps = {
tech.tooManyTechChoices = false
totalChoices = optionLengthNoDuplicates
}
//check for tech that were a choice last time and remove them
if (optionLengthNoDuplicates > totalChoices) {
// console.log('check for tech that were a choice last time and remove them', optionLengthNoDuplicates, options.length)
if (optionLengthNoDuplicates > totalChoices) { //check for tech that were a choice last time and remove them
for (let i = 0; i < tech.tech.length; i++) {
if (optionLengthNoDuplicates > totalChoices) {
if (tech.tech[i].isRecentlyShown) {
// console.log(i)
removeOption(i)
}
if (tech.tech[i].isRecentlyShown) removeOption(i)
} else {
break //you have to repeat choices if there are not enough choices left to display
}
@@ -966,42 +952,42 @@ const powerUps = {
}
}
for (let i = 0; i < tech.tech.length; i++) tech.tech[i].isRecentlyShown = false //reset recently shown back to zero
// powerUps.tech.lastTotalChoices = options.length //this is recorded so that banish can know how many tech were available
// console.log(optionLengthNoDuplicates, options.length)
if (options.length > 0) {
let text = ""
if (totalChoices === 2) {
document.getElementById("choose-grid").style.gridTemplateColumns = "384px 384px"
text += powerUps.researchText('tech')
text += powerUps.cancelText('tech')
} else if (totalChoices === 1) {
document.getElementById("choose-grid").style.gridTemplateColumns = "384px"
text += powerUps.cancelText('tech')
text += powerUps.researchText('tech')
} else {
document.getElementById("choose-grid").style.gridTemplateColumns = "384px 384px 384px"
text += "<div></div>"
text += powerUps.researchText('tech')
text += powerUps.cancelText('tech')
}
for (let i = 0; i < totalChoices; i++) {
if (options.length < 1) break
const choose = options[Math.floor(Math.seededRandom(0, options.length))] //pick an element from the array of options
if (tech.isBanish) {
tech.tech[choose].isBanished = true
if (i === 0) simulation.makeTextLog(`options.length = ${optionLengthNoDuplicates}`)
}
removeOption(choose) //move from future options pool to avoid repeats on this selection
tech.tech[choose].isRecentlyShown = true //this flag prevents this option from being shown the next time you pick up a tech power up
tech.tech[choose].isRecentlyShown = true //this flag prevents this option from being shown the next time you pick up a tech power up
const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : "";
if (tech.tech[choose].isFieldTech) {
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title">
<span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid field" style="position:absolute; top:0; left:10px;opacity:0.65;"></div>
</span>
&nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() :tech.tech[choose].description}</div></div>`
text += powerUps.fieldTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isGunTech) {
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title">
<span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid gun" style="position:absolute; top:0; left:10px; opacity:0.65;"></div>
</span>
&nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() :tech.tech[choose].description}</div></div>`
} else if (tech.tech[choose].isLore) {
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
text += powerUps.gunTechText(choose, `powerUps.choose('tech',${choose})`)
// } else if (tech.tech[choose].isLore) {
// text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
} else if (tech.tech[choose].isJunk) {
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
} else {
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`)
} else { //normal tech
text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`)
}
if (options.length < 1) break
}
@@ -1011,9 +997,16 @@ const powerUps = {
if (tech.tech[i].isBotTech && tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isRecentlyShown) botTech.push(i)
}
if (botTech.length > 0) { //pick random bot tech
// const choose = botTech[Math.floor(Math.random() * botTech.length)];
// const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : "";
// text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title"> <span id = "cellular-rule-id${this.id}" style = "font-size: 150%;font-family: 'Courier New', monospace;">⭓▸●■</span> &nbsp; ${tech.tech[choose].name} ${isCount}</div> ${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
const choose = botTech[Math.floor(Math.random() * botTech.length)];
const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : "";
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title"> <span id = "cellular-rule-id${this.id}" style = "font-size: 150%;font-family: 'Courier New', monospace;">⭓▸●■</span> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
const techCountText = tech.tech[choose].count > 1 ? `(${tech.tech[choose].count}x)` : "";
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/${tech.tech[choose].name}.webp');"`
text += `<div class="choose-grid-module card-background" onclick="powerUps.choose('tech',${choose})" ${style}>
<div class="card-text">
<div class="grid-title"><span id = "cellular-rule-id${this.id}" style = "font-size: 150%;font-family: 'Courier New', monospace;">⭓▸●■</span> &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
}
}
@@ -1024,14 +1017,16 @@ const powerUps = {
if (!b.guns[i].have) gunOptions.push(i);
}
const pick = gunOptions[Math.floor(Math.seededRandom(0, gunOptions.length))] //pick an element from the array of options
text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${pick})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[pick].name}</div> ${b.guns[pick].description}</div>`
// text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${pick})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[pick].name}</div> ${b.guns[pick].description}</div>`
text += powerUps.gunText(pick, `powerUps.choose('gun',${pick})`)
} else {
let fieldOptions = [];
for (let i = 1; i < m.fieldUpgrades.length; i++) { //skip field emitter
if (i !== m.fieldMode) fieldOptions.push(i);
}
const pick = fieldOptions[Math.floor(Math.seededRandom(0, fieldOptions.length))] //pick an element from the array of options
text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${pick})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[pick].name}</div> ${m.fieldUpgrades[pick].description}</div>`
// text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${pick})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[pick].name}</div> ${m.fieldUpgrades[pick].description}</div>`
text += powerUps.fieldText(pick, `powerUps.choose('field',${pick})`)
}
}
if (tech.isMicroTransactions && powerUps.research.count > 0) {
@@ -1063,18 +1058,6 @@ const powerUps = {
}
requestAnimationFrame(cycle);
}
//add in research button or pseudoscience button
if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
tech.junkResearchNumber = Math.ceil(4 * Math.random())
text += `<div class="choose-grid-module" onclick="powerUps.research.use('tech')"><div class="grid-title"> <span style="position:relative;">`
for (let i = 0; i < tech.junkResearchNumber; i++) text += `<div class="circle-grid junk" style="position:absolute; top:0; left:${15*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
text += `</span>&nbsp; <span class='research-select'>pseudoscience</span></div></div>`
} else if (powerUps.research.count > 0) {
text += `<div class="choose-grid-module" onclick="powerUps.research.use('tech')"><div class="grid-title"> <span style="position:relative;">`
for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `<div class="circle-grid research" style="position:absolute; top:0; left:${(18 - len*0.3)*i}px;opacity:0.8; border: 1px #fff solid;"></div>`
// text += `</span>&nbsp; <span class='research-select'>research</span></div></div>`
text += `</span>&nbsp; <span class='research-select'>${tech.isResearchReality?"<span class='alt'>alternate reality</span>": "research"}</span></div></div>`
}
document.getElementById("choose-grid").innerHTML = text
powerUps.showDraft();
@@ -1094,52 +1077,50 @@ const powerUps = {
entanglement: {
name: "entanglement",
color: "#fff", //"hsl(248,100%,65%)",
size() { return 40 },
size() {
return 40
},
effect() {
if (m.alive && localSettings.entanglement) {
let text = ""
text += `<div class='cancel' onclick='powerUps.endDraft("tech")'>✕</div>`
text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>entanglement</h3>`
document.getElementById("choose-grid").style.gridTemplateColumns = "384px 384px 384px"
// text += powerUps.researchText('tech')
text += "<div></div>"
text += "<div class='choose-grid-module entanglement flipX'>entanglement</div>"
text += `<div class='choose-grid-module' onclick='powerUps.endDraft("tech",true)' style="width: 82px; text-align: center;font-size: 1.1em;font-weight: 100;justify-self: end;">cancel</div>` //powerUps.cancelText('tech')
if (localSettings.entanglement.fieldIndex) {
const field = localSettings.entanglement.fieldIndex //add field
text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${field})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[field].name}</div> ${m.fieldUpgrades[field].description}</div>`
const choose = localSettings.entanglement.fieldIndex //add field
text += powerUps.fieldText(choose, `powerUps.choose('field',${choose})`)
}
for (let i = 0; i < localSettings.entanglement.gunIndexes.length; i++) { //add guns
const gun = localSettings.entanglement.gunIndexes[i]
text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${gun})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[gun].name}</div> ${b.guns[gun].description}</div>`
const choose = localSettings.entanglement.gunIndexes[i]
// text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${gun})"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[gun].name}</div> ${b.guns[gun].description}</div>`
text += powerUps.gunText(choose, `powerUps.choose('gun',${choose})`)
}
for (let i = 0; i < localSettings.entanglement.techIndexes.length; i++) { //add tech
let choose = localSettings.entanglement.techIndexes[i]
const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : "";
if (choose === null || tech.tech[choose].count + 1 > tech.tech[choose].maxCount || !tech.tech[choose].allowed()) {
text += `<div class="choose-grid-module" style = "background-color: #efeff5; border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; margin: 1px; padding-top: 6px; padding-bottom: 6px;"><div class="grid-title">${tech.tech[choose].name} <span style = "color: #aaa;font-weight: normal;font-size:80%;">- incompatible</span></div></div>`
// text += `<div class="choose-grid-module" style = "background-color: #efeff5; border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; margin: 1px; padding-top: 6px; padding-bottom: 6px;"><div class="grid-title">${tech.tech[choose].name} <span style = "color: #aaa;font-weight: normal;font-size:80%;">- incoherent</span></div></div>`
text += powerUps.incoherentTechText(choose)
} else {
if (tech.tech[choose].isFieldTech) {
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title">
<span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid field" style="position:absolute; top:0; left:10px;opacity:0.65;"></div>
</span>
&nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() :tech.tech[choose].description}</div></div>`
text += powerUps.fieldTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isGunTech) {
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title">
<span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid gun" style="position:absolute; top:0; left:10px; opacity:0.65;"></div>
</span>
&nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() :tech.tech[choose].description}</div></div>`
text += powerUps.gunTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isLore) {
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
} else if (tech.tech[choose].isJunk) {
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
} else {
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`)
} else { //normal tech
text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`)
}
}
}
// document.getElementById("choose-grid").classList.add("flipX");
document.getElementById("choose-grid").innerHTML = text
powerUps.showDraft();
localSettings.entanglement = undefined
if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
}
@@ -1152,7 +1133,10 @@ const powerUps = {
if (m.alive) requestAnimationFrame(cycle);
if (!simulation.paused && !simulation.isChoosing) { //&& !(simulation.cycle % 2)
count--
const where = { x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) }
const where = {
x: m.pos.x + 50 * (Math.random() - 0.5),
y: m.pos.y + 50 * (Math.random() - 0.5)
}
powerUps.spawn(where.x, where.y, type);
}
}
@@ -1167,7 +1151,10 @@ const powerUps = {
if (tech.isLaserMine && input.down) {
b.laserMine(who.position)
} else {
b.mine(who.position, { x: 0, y: 0 }, 0)
b.mine(who.position, {
x: 0,
y: 0
}, 0)
}
}
if (tech.isRelay) {
@@ -1276,7 +1263,7 @@ const powerUps = {
}
},
addResearchToLevel() { //add a random power up to a location that has a mob, mostly used to give each level one randomly placed research
if (mob.length && Math.random() < 0.5 - 0.3 && simulation.difficultyMode < 5) { //lower chance on why difficulty
if (mob.length && Math.random() < 0.45 - 0.3 * (simulation.difficultyMode > 5)) { //lower chance on why difficulty
const index = Math.floor(Math.random() * mob.length)
powerUps.spawn(mob[index].position.x, mob[index].position.y, "research");
}
@@ -1415,8 +1402,7 @@ const powerUps = {
spawn(x, y, target, moving = true, mode = null, size = powerUps[target].size()) {
if (
(!tech.isSuperDeterminism || (target !== 'research')) &&
!(tech.isEnergyNoAmmo && target === 'ammo') &&
(!simulation.isNoPowerUps)
!(tech.isEnergyNoAmmo && target === 'ammo')
) {
if (tech.isBoostReplaceAmmo && target === 'ammo') target = 'boost'
powerUps.directSpawn(x, y, target, moving, mode, size)

View File

@@ -190,7 +190,6 @@ const simulation = {
healScale: 1,
accelScale: null, //set in levels.setDifficulty
CDScale: null, //set in levels.setDifficulty
isNoPowerUps: false,
molecularMode: Math.floor(4 * Math.random()), //0 spores, 1 missile, 2 ice IX, 3 drones //randomize molecular assembler field type
// dropFPS(cap = 40, time = 15) {
// simulation.fpsCap = cap
@@ -547,16 +546,16 @@ const simulation = {
const swapPeriod = 150
const len = 30
for (let i = 0; i < len; i++) {
setTimeout(function() {
simulation.wipe = function() { //set wipe to have trails
setTimeout(function () {
simulation.wipe = function () { //set wipe to have trails
ctx.fillStyle = `rgba(221,221,221,${i*i*0.0005 +0.0025})`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
}, (i) * swapPeriod);
}
setTimeout(function() {
simulation.wipe = function() { //set wipe to normal
setTimeout(function () {
simulation.wipe = function () { //set wipe to normal
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
}, len * swapPeriod);
@@ -617,7 +616,7 @@ const simulation = {
simulation.clearTimeouts();
simulation.onTitlePage = true;
document.getElementById("splash").onclick = function() {
document.getElementById("splash").onclick = function () {
simulation.startGame();
};
// document.getElementById("choose-grid").style.display = "none"
@@ -699,10 +698,8 @@ const simulation = {
}
if (isTrainingRun) {
simulation.isTraining = true
simulation.isNoPowerUps = true
} else {
simulation.isTraining = false
simulation.isNoPowerUps = false;
}
simulation.onTitlePage = false;
// document.getElementById("choose-grid").style.display = "none"
@@ -785,11 +782,13 @@ const simulation = {
// m.maxEnergy = 1
// m.energy = 1
input.isPauseKeyReady = true
simulation.wipe = function() { //set wipe to normal
simulation.wipe = function () { //set wipe to normal
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
m.hole.isOn = false
simulation.paused = false;
// simulation.cycle = 0
// m.cycle = 0
engine.timing.timeScale = 1;
simulation.fpsCap = simulation.fpsCapDefault;
simulation.isAutoZoom = true;
@@ -864,7 +863,7 @@ const simulation = {
requestAnimationFrame(cycle); //starts game loop
},
clearTimeouts() {
let id = window.setTimeout(function() {}, 0);
let id = window.setTimeout(function () {}, 0);
while (id--) {
window.clearTimeout(id); // will do nothing if no timeout with id is present
}
@@ -899,7 +898,7 @@ const simulation = {
if (tech.isMutualism && !tech.isEnergyHealth) {
for (let i = 0; i < bullet.length; i++) {
if (bullet[i].isMutualismActive) {
m.health += 0.005 + 0.005 * (bullet[i].isSpore || bullet[i].isFlea)
m.health += 0.01 + 0.01 * (bullet[i].isSpore || bullet[i].isFlea)
if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth();
}
@@ -958,12 +957,21 @@ const simulation = {
if (droneCount > 0) {
requestAnimationFrame(respawnDrones);
if (!simulation.paused && !simulation.isChoosing && m.alive) {
const where = { x: level.enter.x + 50, y: level.enter.y - 60 }
const where = {
x: level.enter.x + 50,
y: level.enter.y - 60
}
droneCount--
if (tech.isDroneRadioactive) {
b.droneRadioactive({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 100 * (Math.random() - 0.5) }, 0)
b.droneRadioactive({
x: where.x + 100 * (Math.random() - 0.5),
y: where.y + 100 * (Math.random() - 0.5)
}, 0)
} else {
b.drone({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 120 * (Math.random() - 0.5) }, 0)
b.drone({
x: where.x + 100 * (Math.random() - 0.5),
y: where.y + 120 * (Math.random() - 0.5)
}, 0)
if (tech.isDroneGrab && deliveryCount > 0) {
const who = bullet[bullet.length - 1]
who.isImproved = true;
@@ -985,8 +993,14 @@ const simulation = {
requestAnimationFrame(respawnSpores);
if (!simulation.paused && !simulation.isChoosing) {
sporeCount--
const where = { x: level.enter.x + 50, y: level.enter.y - 60 }
b.spore({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 120 * (Math.random() - 0.5) })
const where = {
x: level.enter.x + 50,
y: level.enter.y - 60
}
b.spore({
x: where.x + 100 * (Math.random() - 0.5),
y: where.y + 120 * (Math.random() - 0.5)
})
}
}
}
@@ -998,8 +1012,14 @@ const simulation = {
requestAnimationFrame(respawnWorms);
if (!simulation.paused && !simulation.isChoosing) {
wormCount--
const where = { x: level.enter.x + 50, y: level.enter.y - 60 }
b.worm({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 120 * (Math.random() - 0.5) })
const where = {
x: level.enter.x + 50,
y: level.enter.y - 60
}
b.worm({
x: where.x + 100 * (Math.random() - 0.5),
y: where.y + 120 * (Math.random() - 0.5)
})
}
}
}
@@ -1011,10 +1031,19 @@ const simulation = {
requestAnimationFrame(respawnFleas);
if (!simulation.paused && !simulation.isChoosing) {
fleaCount--
const where = { x: level.enter.x + 50, y: level.enter.y - 60 }
const where = {
x: level.enter.x + 50,
y: level.enter.y - 60
}
const speed = 6 + 3 * Math.random()
const angle = 2 * Math.PI * Math.random()
b.flea({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 120 * (Math.random() - 0.5) }, { x: speed * Math.cos(angle), y: speed * Math.sin(angle) })
b.flea({
x: where.x + 100 * (Math.random() - 0.5),
y: where.y + 120 * (Math.random() - 0.5)
}, {
x: speed * Math.cos(angle),
y: speed * Math.sin(angle)
})
}
}
}
@@ -1171,7 +1200,7 @@ const simulation = {
}
if (tech.cyclicImmunity && m.immuneCycle < m.cycle + tech.cyclicImmunity) m.immuneCycle = m.cycle + tech.cyclicImmunity; //player is immune to damage for 60 cycles
fallCheck = function(who, save = false) {
fallCheck = function (who, save = false) {
let i = who.length;
while (i--) {
if (who[i].position.y > simulation.fallHeight) {
@@ -1555,7 +1584,12 @@ const simulation = {
outHTML += "<div>" + simulation.constructMapString[i] + "</div>"
}
console.log(out)
navigator.clipboard.writeText(out).then(function() { /* clipboard successfully set */ }, function() { /* clipboard write failed */ console.log('copy failed') });
navigator.clipboard.writeText(out).then(function () {
/* clipboard successfully set */
}, function () {
/* clipboard write failed */
console.log('copy failed')
});
document.getElementById("construct").innerHTML = outHTML
},
// copyToClipBoard(value) {

View File

@@ -411,7 +411,7 @@ const spawn = {
}
}
me.damageReductionDecay = function() { //slowly make the boss take more damage over time //damageReduction resets with each invulnerability phase
if (!(me.cycle % 60) && this.lastDamageCycle + 240 > this.cycle) this.damageReduction *= 1.017 //only decay once a second //only decay if the player has done damage in the last 4 seconds
if (!(me.cycle % 60) && this.lastDamageCycle + 240 > this.cycle) this.damageReduction *= 1.02 //only decay once a second //only decay if the player has done damage in the last 4 seconds
}
me.mobType = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]
me.spawnMobs = function(index = 0) {
@@ -976,6 +976,7 @@ const spawn = {
// build.shareURL(false)
setTimeout(function() {
if (!simulation.onTitlePage) {
m.alive = false
simulation.paused = true;
// simulation.clearMap();
// Matter.Composite.clear(composite, keepStatic, [deep = false])
@@ -1533,6 +1534,101 @@ const spawn = {
// }
// };
// },
zombie(x, y, radius, sides, color) { //mob that attacks other mobs
mobs.spawn(x, y, sides, radius, color);
let me = mob[mob.length - 1];
me.isZombie = true
me.isDropPowerUp = false;
me.showHealthBar = false;
me.stroke = "#83a"
me.accelMag = 0.0015
me.frictionAir = 0.01
// me.repulsionRange = 400000 + radius * radius; //squared
// me.memory = 120;
me.seeAtDistance2 = 1000000 //1000 vision range
// Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback
me.do = function() {
this.zombieHealthBar();
this.lookForMobTargets();
this.attack();
this.checkStatus();
};
me.mobSearchIndex = 0;
me.target = null
me.lookForMobTargets = function() {
if (this.target && !this.target.alive) this.target = null
if (this.target === null && !(simulation.cycle % 10) && mob.length > 1) { //if you have no target
this.mobSearchIndex++ //look for a different mob index every time
if (this.mobSearchIndex > mob.length - 1) this.mobSearchIndex = 0
if (
!mob[this.mobSearchIndex].isZombie &&
(Vector.magnitudeSquared(Vector.sub(this.position, mob[this.mobSearchIndex].position)) < this.seeAtDistance2 || Matter.Query.ray(map, this.position, mob[this.mobSearchIndex].position).length === 0)
) {
this.target = mob[this.mobSearchIndex]
}
}
}
me.zombieHealthBar = function() {
this.damage(0.001); //decay
const h = this.radius * 0.3;
const w = this.radius * 2;
const x = this.position.x - w / 2;
const y = this.position.y - w * 0.7;
ctx.fillStyle = "rgba(100, 100, 100, 0.3)";
ctx.fillRect(x, y, w, h);
ctx.fillStyle = "rgba(136, 51, 170,0.7)";
ctx.fillRect(x, y, w * this.health, h);
}
me.hitCD = 0
me.attack = function() { //hit non zombie mobs
if (this.hitCD < simulation.cycle) {
if (this.target) {
this.force = Vector.mult(Vector.normalise(Vector.sub(this.target.position, this.position)), this.accelMag * this.mass)
if (this.speed > 6) { // speed cap instead of friction to give more agility
Matter.Body.setVelocity(this, {
x: this.velocity.x * 0.97,
y: this.velocity.y * 0.97
});
}
}
const hit = (who) => {
if (!who.isZombie && who.damageReduction) {
this.hitCD = simulation.cycle + 15
//knock back away from recently hit mob
const force = Vector.mult(Vector.normalise(Vector.sub(who.position, this.position)), 0.03 * this.mass)
this.force.x -= force.x;
this.force.y -= force.y;
this.target = null //look for a new target
const dmg = 0.3 * m.dmgScale
who.damage(dmg);
simulation.drawList.push({
x: this.position.x,
y: this.position.y,
radius: Math.log(dmg + 1.1) * 40 * who.damageReduction + 3,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
}
}
const collide = Matter.Query.collides(this, mob) //damage mob targets if nearby
if (collide.length > 1) { //don't count self collide
for (let i = 0, len = collide.length; i < len; i++) {
hit(collide[i].bodyA)
hit(collide[i].bodyB)
}
}
}
}
// me.onDamage = function(dmg) {
// }
},
starter(x, y, radius = Math.floor(15 + 20 * Math.random())) { //easy mob for on level 1
mobs.spawn(x, y, 8, radius, "#9ccdc6");
let me = mob[mob.length - 1];
@@ -6674,7 +6770,7 @@ const spawn = {
this.seePlayerByHistory(60);
this.attraction();
this.checkStatus();
this.eventHorizon = 900 + 200 * Math.sin(simulation.cycle * 0.005)
this.eventHorizon = 950 + 250 * Math.sin(simulation.cycle * 0.005)
if (!simulation.isTimeSkipping) {
if (Vector.magnitude(Vector.sub(this.position, m.pos)) < this.eventHorizon) {
this.attraction();

1754
js/tech.js

File diff suppressed because it is too large Load Diff