tech: repeater - shotgun gets another shot, and a longer fire delay
  shotgun cross hairs show when fire is on cooldown

keys 1,2,3,4,5,6,7,8,9,0,-,= switch to a gun in your inventory
Nerfed blinkBoss health and speed
sneaker mobs are immune to harm for one cycles after vanishing
experiment button new style
new images for energy, bots

bug fixes
This commit is contained in:
landgreen
2023-01-08 09:14:58 -08:00
parent 802cd90220
commit 9206d47f40
29 changed files with 577 additions and 380 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 47 KiB

BIN
img/repeater.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@@ -140,8 +140,7 @@
<summary>controls</summary>
<div class="details-div">
To change controls click a box
<br>
and press an unused key.
<br>and press an unused key.
<br><br>
<table id="control-table">
<tr>
@@ -185,6 +184,10 @@
<td id='key-previous-gun' class='key-input'>E</td>
<td class='key-used'>MouseWheel</td>
</tr>
<tr style="opacity:0.5;">
<th>GUN #</th>
<td id="key-num" class='key-input'>Num</td>
</tr>
<tr>
<th>PAUSE</th>
<td id='key-pause' class='key-input'>P</td>
@@ -197,7 +200,8 @@
<td></td>
</tr>
</table>
<button id="control-reset" type="button">reset</button><span style="font-size: 60%;"> to default keys</span>
<br><button id="control-reset" type="button">reset</button><span style="font-size: 60%;"> to default keys</span>
</div>
</details>
</div>

View File

@@ -23,7 +23,7 @@ const b = {
},
fire() {},
fireNormal() {
if (b.inventory.length) {
if (b.inventory.length && b.activeGun !== null) {
if (input.fire && m.fireCDcycle < m.cycle && (!input.field || m.fieldFire)) {
if (b.guns[b.activeGun].ammo > 0) {
b.fireWithAmmo()
@@ -36,7 +36,7 @@ const b = {
}
},
fireNotMove() { //added && player.speed < 0.5 && m.onGround
if (b.inventory.length) {
if (b.inventory.length && b.activeGun !== null) {
if (input.fire && m.fireCDcycle < m.cycle && (!input.field || m.fieldFire) && player.speed < 2.5 && m.onGround && Math.abs(m.yOff - m.yOffGoal) < 1) {
if (b.guns[b.activeGun].ammo > 0) {
b.fireWithAmmo()
@@ -49,7 +49,7 @@ const b = {
}
},
fireAlwaysFire() { //added && player.speed < 0.5 && m.onGround //removed input.fire && (!input.field || m.fieldFire)
if (b.inventory.length) {
if (b.inventory.length && b.activeGun !== null) {
if (m.fireCDcycle < m.cycle && player.speed < 0.5 && m.onGround && Math.abs(m.yOff - m.yOffGoal) < 1) {
if (b.guns[b.activeGun].ammo > 0) {
b.fireWithAmmo()
@@ -60,7 +60,7 @@ const b = {
}
},
fireFloat() { //added && player.speed < 0.5 && m.onGround
if (b.inventory.length) {
if (b.inventory.length && b.activeGun !== null) {
if (input.fire && (!input.field || m.fieldFire)) {
if (m.fireCDcycle < m.cycle) {
if (b.guns[b.activeGun].ammo > 0) {
@@ -125,11 +125,11 @@ const b = {
simulation.updateGunHUD();
}
},
returnGunAmmo(name) {
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === name) return b.guns[i].ammo
}
},
// returnGunAmmo(name) {
// for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
// if (b.guns[i].name === name) return b.guns[i].ammo
// }
// },
giveGuns(gun = "random", ammoPacks = 10) {
if (tech.ammoCap) ammoPacks = 0.45 * tech.ammoCap
if (tech.isOneGun) b.removeAllGuns();
@@ -173,6 +173,7 @@ const b = {
// if (tech.infiniteWaveAmmo === 2) b.guns[3].ammo = Infinity
}
simulation.makeGunHUD();
simulation.switchGun();
b.setFireCD();
if (tech.isOneGun && b.inventory > 0) {
//count how many gun tech you have and remove them
@@ -323,11 +324,19 @@ const b = {
};
}
},
muzzleFlash(radius = 10) {
ctx.fillStyle = "#fb0";
ctx.beginPath();
ctx.arc(m.pos.x + 35 * Math.cos(m.angle), m.pos.y + 35 * Math.sin(m.angle), radius, 0, 2 * Math.PI);
ctx.fill();
muzzleFlash(radius = 30) {
// ctx.fillStyle = "#fb0";
// ctx.beginPath();
// ctx.arc(m.pos.x + 35 * Math.cos(m.angle), m.pos.y + 35 * Math.sin(m.angle), radius, 0, 2 * Math.PI);
// ctx.fill();
simulation.drawList.push({ //add dmg to draw queue
x: m.pos.x + 35 * Math.cos(m.angle),
y: m.pos.y + 35 * Math.sin(m.angle),
radius: radius,
color: "#fb0",
time: 1
});
},
removeConsBB(me) {
for (let i = 0, len = consBB.length; i < len; ++i) {
@@ -1618,13 +1627,16 @@ const b = {
player.force.x += momentum.x
player.force.y += momentum.y
// refund ammo
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "harpoon") {
b.guns[i].ammo++;
b.guns[9].ammo++;
simulation.updateGunHUD();
break;
}
}
// for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
// if (b.guns[i].name === "harpoon") {
// b.guns[i].ammo++;
// simulation.updateGunHUD();
// break;
// }
// }
} else {
if (m.energy > this.drain) m.energy -= this.drain
const sub = Vector.sub(this.position, m.pos)
@@ -1743,13 +1755,13 @@ const b = {
this.endCycle = 0;
if (m.cycle + 50 < m.fireCDcycle) m.fireCDcycle = m.cycle + 50
// refund ammo
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "harpoon") {
b.guns[i].ammo++;
b.guns[9].ammo++;
simulation.updateGunHUD();
break;
}
}
// for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
// if (b.guns[i].name === "harpoon") {
// break;
// }
// }
}
}
}
@@ -1941,13 +1953,13 @@ const b = {
player.force.y += momentum.y
// refund ammo
if (isReturnAmmo) {
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "harpoon") {
b.guns[i].ammo++;
b.guns[9].ammo++;
simulation.updateGunHUD();
break;
}
}
// for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
// if (b.guns[i].name === "harpoon") {
// break;
// }
// }
}
} else {
const sub = Vector.sub(this.position, m.pos)
@@ -2818,7 +2830,7 @@ const b = {
) {
if (tech.isStun) b.AoEStunEffect(this.position, this.range + mob[i].radius + random); //AoEStunEffect(where, range, cycles = 90 + 60 * Math.random()) {
if (tech.isMineSentry) {
this.lookFrequency = 15 + 10 * (tech.oneSuperBall && tech.isSuperMine) + Math.floor(3 * Math.random())
this.lookFrequency = Math.floor(7 + 7 * b.fireCDscale + 10 * (tech.oneSuperBall && tech.isSuperMine) + Math.floor(3 * Math.random()))
// this.endCycle = Infinity
this.shots = tech.sentryAmmo
this.do = function() { //overwrite the do method for this bullet
@@ -3376,9 +3388,7 @@ const b = {
}
},
onEnd() {
if (tech.isDroneRespawn && b.inventory.length) {
const who = b.guns[b.activeGun]
if (who.name === "drones" && who.ammo > 0 && mob.length) {
if (tech.isDroneRespawn && b.inventory.length && b.activeGun === 7 && b.guns[b.activeGun].ammo > 0 && mob.length) {
b.drone({
x: this.position.x,
y: this.position.y
@@ -3388,7 +3398,6 @@ const b = {
simulation.updateGunHUD();
}
}
}
},
do() {
if (simulation.cycle + this.deathCycles > this.endCycle) { //fall shrink and die
@@ -3565,9 +3574,7 @@ const b = {
maxRadioRadius: 270 + Math.floor(90 * Math.random()),
beforeDmg() {},
onEnd() {
if (tech.isDroneRespawn && b.inventory.length) {
const who = b.guns[b.activeGun]
if (who.name === "drones" && who.ammo > 0 && mob.length) {
if (tech.isDroneRespawn && b.inventory.length && b.activeGun === 7 && b.guns[b.activeGun].ammo > 0 && mob.length) {
b.droneRadioactive({
x: this.position.x,
y: this.position.y
@@ -3577,7 +3584,6 @@ const b = {
simulation.updateGunHUD();
}
}
}
},
do() {
//radioactive zone
@@ -3756,15 +3762,7 @@ const b = {
bullet[me].minDmgSpeed = 0;
bullet[me].restitution = 1;
bullet[me].friction = 0;
if (tech.isIncendiary) {
bullet[me].do = function() {
this.force.y += this.mass * 0.0012;
if (Matter.Query.collides(this, map).length) {
b.explosion(this.position, this.mass * 280); //makes bullet do explosive damage at end
this.endCycle = 0
}
};
} else if (tech.superHarm) {
if (tech.superHarm) {
bullet[me].collidePlayerDo = function() {
if (Matter.Query.collides(this, [player]).length) {
this.endCycle = 0
@@ -3781,13 +3779,11 @@ const b = {
}
bullet[me].cycle = 0
bullet[me].do = function() {
this.cycle++
if (this.cycle > 6) this.do = this.collidePlayerDo
this.force.y += this.mass * 0.0012;
};
} else {
bullet[me].do = function() {
this.cycle++
this.force.y += this.mass * 0.0012;
};
}
@@ -3801,6 +3797,10 @@ const b = {
}
this.endCycle = 0
}
if (tech.isIncendiary) {
b.explosion(this.position, this.mass * 280); //makes bullet do explosive damage at end
this.endCycle = 0
}
};
},
targetedBall(position, num = 1, speed = 42 + 12 * Math.random(), range = 1200, isRandomAim = true) {
@@ -5818,7 +5818,7 @@ const b = {
this.rotateToVelocity()
};
}
b.muzzleFlash(30);
b.muzzleFlash();
//very complex recoil system
if (m.onGround) {
if (input.down) {
@@ -5905,7 +5905,7 @@ const b = {
};
}
b.muzzleFlash(30);
b.muzzleFlash();
//very complex recoil system
if (m.onGround) {
if (input.down) {
@@ -5970,24 +5970,49 @@ const b = {
ammoPack: 3.5,
defaultAmmoPack: 3.5,
have: false,
do() {},
do() {
//fade cross hairs
// draw loop around player head
// const left = m.fireCDcycle !== Infinity ? 0.05 * Math.max(m.fireCDcycle - m.cycle, 0) : 0
// if (left > 0) {
// ctx.beginPath();
// // ctx.arc(simulation.mouseInGame.x, simulation.mouseInGame.y, 30, 0, left);
// ctx.arc(m.pos.x, m.pos.y, 28, m.angle - left, m.angle);
// // ctx.fillStyle = "rgba(0,0,0,0.3)" //"#333"
// // ctx.fill();
// ctx.strokeStyle = "#333";
// ctx.lineWidth = 2;
// ctx.stroke();
// }
//draw hip circle
// ctx.beginPath();
// ctx.arc(m.pos.x + m.hip.x, m.pos.y + m.hip.y, 11, 0, 2 * Math.PI);
// ctx.fillStyle = "rgba(0,0,0,0.3)" //"#333"
// ctx.fill();
},
fire() {
let knock, spread
const coolDown = function() {
if (input.down) {
spread = 0.65
m.fireCDcycle = m.cycle + Math.floor(73 * b.fireCDscale) // cool down
m.fireCDcycle = m.cycle + Math.floor((73 + 36 * tech.shotgunExtraShots) * b.fireCDscale) // cool down
if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(60 * b.fireCDscale)) m.immuneCycle = m.cycle + Math.floor(60 * b.fireCDscale); //player is immune to damage for 30 cycles
knock = 0.01
} else {
m.fireCDcycle = m.cycle + Math.floor(56 * b.fireCDscale) // cool down
m.fireCDcycle = m.cycle + Math.floor((56 + 28 * tech.shotgunExtraShots) * b.fireCDscale) // cool down
if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(47 * b.fireCDscale)) m.immuneCycle = m.cycle + Math.floor(47 * b.fireCDscale); //player is immune to damage for 30 cycles
spread = 1.3
knock = 0.1
}
if (tech.isShotgunReversed) {
player.force.x += 1.6 * knock * Math.cos(m.angle)
player.force.y += 1.6 * knock * Math.sin(m.angle) - 3 * player.mass * simulation.g
player.force.x += 1.5 * knock * Math.cos(m.angle)
player.force.y += 1.5 * knock * Math.sin(m.angle) - 3 * player.mass * simulation.g
} else if (tech.isShotgunRecoil) {
m.fireCDcycle -= 0.66 * (56 * b.fireCDscale)
player.force.x -= 2 * knock * Math.cos(m.angle)
@@ -5996,7 +6021,7 @@ const b = {
player.force.x -= knock * Math.cos(m.angle)
player.force.y -= knock * Math.sin(m.angle) * 0.5 //reduce knock back in vertical direction to stop super jumps
}
}
const spray = (num) => {
const side = 22
for (let i = 0; i < num; i++) {
@@ -6020,9 +6045,7 @@ const b = {
};
}
}
b.muzzleFlash(35);
const chooseBulletType = function() {
if (tech.isRivets) {
const me = bullet.length;
// const dir = m.angle + 0.02 * (Math.random() - 0.5)
@@ -6204,6 +6227,30 @@ const b = {
spray(16); //fires normal shotgun bullets
}
}
coolDown();
b.muzzleFlash(35);
chooseBulletType();
if (tech.shotgunExtraShots) {
const delay = 7
let count = tech.shotgunExtraShots * delay
function cycle() {
count--
if (!(count % delay)) {
coolDown();
b.muzzleFlash(35);
chooseBulletType();
}
if (count > 0) {
requestAnimationFrame(cycle);
}
}
requestAnimationFrame(cycle);
}
}
}, {
name: "super balls", //2
description: "fire <strong>3</strong> balls in a wide arc<br>balls <strong>bounce</strong> with no momentum loss",

View File

@@ -415,7 +415,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
const style = (localSettings.isHideImages || tech.tech[i].isJunk) ? `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" 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: 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) {
@@ -588,13 +588,19 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
},
populateGrid() { //background-color:var(--build-bg-color);
let text = `
<div class="experiment-grid-module" style="position: sticky; top:0; z-index: 10; align-self: start; width: 165px; 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; padding:7px; height: 190px;">
<div class="experiment-start-box">
<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">
<option value="1">easy</option>
<option value="2" selected>normal</option>
<option value="4">hard</option>
<option value="6">why?</option>
</select>
</div>
<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>
<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; margin-bottom: 15px;" ${localSettings.isHideImages? "checked": ""}>
</div>
<div>
<svg class="SVG-button" onclick="build.reset()" width="50" height="25">
@@ -610,17 +616,11 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
</svg>
</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">
<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="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": ""}>
<svg class="SVG-button" onclick="build.startExperiment()" width="165" height="70" >
<g stroke='none' fill='#333' stroke-width="2" font-size="65px" font-family="Ariel, sans-serif">
<text x="17" y="57">start</text>
</g>
</svg>
</div>
</div>`
const hideStyle = `style="height:auto; border: none; background-color: transparent;"`
@@ -905,6 +905,7 @@ const input = {
document.getElementById("key-previous-gun").style.background = backgroundColor
document.getElementById("key-testing").style.background = backgroundColor
if (input.focus) input.focus.style.background = 'rgb(0, 200, 255)';
document.getElementById("key-num").style.background = backgroundColor //always not highlighted
},
setKeys(event) {
//check for duplicate keys
@@ -923,7 +924,8 @@ const input = {
// event.code === "Escape" ||
event.code === input.key.nextGun ||
event.code === input.key.previousGun ||
event.code === input.key.testing
event.code === input.key.testing ||
event.code === "Digit1" || event.code === "Digit2" || event.code === "Digit3" || event.code === "Digit4" || event.code === "Digit5" || event.code === "Digit6" || event.code === "Digit7" || event.code === "Digit8" || event.code === "Digit9" || event.code === "Digit0" || event.code === "Minus" || event.code === "Equal"
)) {
switch (input.focus.id) {
case "key-fire":
@@ -1029,11 +1031,9 @@ window.addEventListener("keydown", function(event) {
input.down = true
break;
case input.key.fire:
// event.preventDefault();
input.fire = true
break
case input.key.field:
// event.preventDefault();
input.field = true
break
case input.key.nextGun:
@@ -1042,7 +1042,6 @@ window.addEventListener("keydown", function(event) {
case input.key.previousGun:
simulation.previousGun();
break
// case "Escape":
case input.key.pause:
if (!simulation.isChoosing && input.isPauseKeyReady && m.alive) {
input.isPauseKeyReady = false
@@ -1160,6 +1159,47 @@ window.addEventListener("keydown", function(event) {
}
break
}
if (b.inventory.length > 1 && !simulation.testing) {
switch (event.code) {
case "Digit1":
simulation.switchToGunInInventory(0);
break
case "Digit2":
simulation.switchToGunInInventory(1);
break
case "Digit3":
simulation.switchToGunInInventory(2);
break
case "Digit4":
simulation.switchToGunInInventory(3);
break
case "Digit5":
simulation.switchToGunInInventory(4);
break
case "Digit6":
simulation.switchToGunInInventory(5);
break
case "Digit7":
simulation.switchToGunInInventory(6);
break
case "Digit8":
simulation.switchToGunInInventory(7);
break
case "Digit9":
simulation.switchToGunInInventory(8);
break
case "Digit0":
simulation.switchToGunInInventory(9);
break
case "Minus":
simulation.switchToGunInInventory(10);
break
case "Equal":
simulation.switchToGunInInventory(11);
break
}
}
if (simulation.testing) {
if (event.key === "X") m.death(); //only uppercase
switch (event.key.toLowerCase()) {

View File

@@ -28,24 +28,24 @@ const level = {
// m.setField("perfect diamagnetism") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass pilot wave plasma torch
// simulation.molecularMode = 2
// m.damage(0.1);
// b.giveGuns("mine") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("spores") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("shotgun") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.guns[0].ammo = 10000
// tech.giveTech("blast ball")
// tech.giveTech("elephants toothpaste")
// tech.giveTech("sentry gun")
// tech.giveTech("needle gun")
// tech.giveTech("repeater")
// tech.giveTech("ice-shot")
// for (let i = 0; i < 1; ++i) tech.giveTech("super ball")
// tech.isFoamBall = true
// for (let i = 0; i < 1; ++i) tech.giveTech("super ball")
// for (let i = 0; i < 3; ++i) tech.giveTech("repeater")
// for (let i = 0; i < 1; i++) tech.giveTech("irradiated nails")
// for (let i = 0; i < 1; i++) tech.giveTech("colony")
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling");
// level.testing();
// spawn.shooter(1900, -500, 200)
// spawn.blinkBoss(1900, -500)
// spawn.sneakBoss(1900, -500)
// spawn.starter(1900, -500, 25)
// spawn.starter(1900, -500, 200)
// spawn.sneaker(1900, -500, 25)
// spawn.hopper(2538, -950)
// spawn.zombie(1000 + 1000 * Math.random(), -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color)

View File

@@ -697,7 +697,7 @@ const m = {
}
m.lastHarmCycle = m.cycle
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
const len = Math.min((dmg - 0.06 * Math.random()) * 40, 40) / tech.droneEnergyReduction * (tech.isEnergyHealth ? 0.5 : 1)
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),

View File

@@ -769,6 +769,9 @@ const powerUps = {
} else if (parseInt(JSON.parse(elements[index + 1].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
tech.tech[choose].url = JSON.parse(elements[index + 1].getAttribute("data")).iurl
document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
} else if (parseInt(JSON.parse(elements[index + 2].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
tech.tech[choose].url = JSON.parse(elements[index + 2].getAttribute("data")).iurl
document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
}
});
} else {

View File

@@ -297,6 +297,34 @@ const simulation = {
ctx.strokeStyle = "#000"; //'rgba(0,0,0,0.4)'
ctx.stroke(); // Draw it
},
drawCursorBasic() {
const size = 10;
ctx.beginPath();
ctx.moveTo(simulation.mouse.x - size, simulation.mouse.y);
ctx.lineTo(simulation.mouse.x + size, simulation.mouse.y);
ctx.moveTo(simulation.mouse.x, simulation.mouse.y - size);
ctx.lineTo(simulation.mouse.x, simulation.mouse.y + size);
ctx.lineWidth = 2;
ctx.strokeStyle = "#000"; //'rgba(0,0,0,0.4)'
ctx.stroke(); // Draw it
},
drawCursorCoolDown() {
const size = 10;
ctx.lineWidth = 2;
ctx.strokeStyle = "#000"; //'rgba(0,0,0,0.4)'
ctx.beginPath();
if (m.fireCDcycle > m.cycle) {
ctx.strokeStyle = "#777"; //'rgba(0,0,0,0.4)'
ctx.arc(simulation.mouse.x, simulation.mouse.y, size + 1, 0, 2 * Math.PI);
} else {
ctx.strokeStyle = "#000"; //'rgba(0,0,0,0.4)'
}
ctx.moveTo(simulation.mouse.x - size, simulation.mouse.y);
ctx.lineTo(simulation.mouse.x + size, simulation.mouse.y);
ctx.moveTo(simulation.mouse.x, simulation.mouse.y - size);
ctx.lineTo(simulation.mouse.x, simulation.mouse.y + size);
ctx.stroke(); // Draw it
},
drawList: [], //so you can draw a first frame of explosions.. I know this is bad
drawTime: 8, //how long circles are drawn. use to push into drawlist.time
mobDmgColor: "rgba(255,0,0,0.7)", //color when a mob damages the player // set by mass-energy tech
@@ -437,15 +465,14 @@ const simulation = {
simulation.switchGun();
}
},
switchToGunInInventory(num) {
if (b.inventory[num] !== undefined && b.inventoryGun !== num) {
b.inventoryGun = num
simulation.switchGun();
}
},
switchGun() {
if (tech.isLongitudinal && b.guns[b.activeGun].name === "wave") {
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "wave") {
b.guns[i].waves = []; //empty array of wave bullets
break;
}
}
}
if (tech.isLongitudinal && b.activeGun === 3) b.guns[3].waves = []; //empty array of wave bullets
if (tech.crouchAmmoCount) tech.crouchAmmoCount = 1 //this prevents hacking the tech by switching guns
if (b.inventory.length > 0) {
b.activeGun = b.inventory[b.inventoryGun];
@@ -453,6 +480,12 @@ const simulation = {
}
simulation.updateGunHUD();
simulation.boldActiveGunHUD();
//set crosshairs
if (b.activeGun === 1) {
simulation.drawCursor = simulation.drawCursorCoolDown
} else {
simulation.drawCursor = simulation.drawCursorBasic
}
},
zoom: null,
zoomScale: 1000,
@@ -741,6 +774,7 @@ const simulation = {
input.endKeySensing();
b.removeAllGuns();
simulation.switchGun();
tech.setupAllTech(); //sets tech to default values
tech.cancelCount = 0;
@@ -881,7 +915,7 @@ const simulation = {
let count = 0;
for (i = 0, len = bullet.length; i < len; i++) { //count mines left on map
if (bullet[i].bulletType === "mine" || bullet[i].bulletType === "laser mine") count++
if ((bullet[i].bulletType === "mine" || bullet[i].bulletType === "laser mine") && !bullet[i].isArmed) count++
}
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun is mine
if (b.guns[i].name === "mine") {

View File

@@ -623,7 +623,7 @@ const spawn = {
{
name: "black hole",
eventHorizon: 0,
eventHorizonRadius: 2100,
eventHorizonRadius: 1900,
eventHorizonCycle: 0,
do() {
this.eventHorizonCycle++
@@ -4146,7 +4146,7 @@ const spawn = {
Matter.Body.rotate(me, Math.PI * 0.1);
Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
me.isBoss = true;
me.damageReduction = 0.03 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.035 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.frictionStatic = 0;
me.friction = 0;
@@ -4160,7 +4160,7 @@ const spawn = {
me.grenadeDelay = 100
}
me.pulseRadius = 1.5 * Math.min(550, 200 + simulation.difficulty * 2)
me.delay = 35 + 35 * simulation.CDScale;
me.delay = 55 + 35 * simulation.CDScale;
me.nextBlinkCycle = me.delay;
spawn.shield(me, x, y, 1);
me.onDamage = function() {
@@ -5058,7 +5058,7 @@ const spawn = {
if (this.phaseCycle > -1) {
Matter.Body.rotate(this, 0.02)
for (let i = 0, len = this.vertices.length; i < len; i++) { //fire a bullet from each vertex
spawn.sniperBullet(this.vertices[i].x, this.vertices[i].y, 5, 4);
spawn.sniperBullet(this.vertices[i].x, this.vertices[i].y, 3, 4);
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[i])), -15)
Matter.Body.setVelocity(mob[mob.length - 1], {
x: velocity.x,
@@ -5724,7 +5724,7 @@ const spawn = {
let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
me.isBoss = true;
me.damageReduction = 0.4 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.accelMag = 0.0017 * Math.sqrt(simulation.accelScale);
me.frictionAir = 0.01;
@@ -5736,17 +5736,15 @@ const spawn = {
me.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player
me.showHealthBar = false;
me.memory = 30;
me.vanishesLeft = 2 + simulation.difficultyMode
me.vanishesLeft = Math.ceil(1 + simulation.difficultyMode * 0.5)
me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
me.onDamage = function() {
if (this.vanishesLeft > 0 && this.health < 0.1) { //if health is below 10% teleport to a random spot on player history, heal, and cloak
this.vanishesLeft--
// const scale = 0.95;
// Matter.Body.scale(this, scale, scale);
// this.radius *= scale;
//flash screen to hide vanish
for (let i = 0; i < 8; i++) {
for (let i = 0; i < 8; i++) { //flash screen to hide vanish
simulation.drawList.push({
x: this.position.x,
y: this.position.y,
@@ -5761,6 +5759,7 @@ const spawn = {
Matter.Body.setPosition(this, history.position)
Matter.Body.setVelocity(this, { x: 0, y: 0 });
this.damageReduction = 0 //immune to harm for the rest of this game cycle
this.seePlayer.recall = 0
this.cloak();
this.health = 1;
@@ -5784,6 +5783,14 @@ const spawn = {
}
}
me.do = function() {
if (this.damageReduction === 0) {
this.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
let i = this.status.length //clear bad status effects
while (i--) {
if (this.status[i].type === "stun" || this.status[i].type === "dot") this.status.splice(i, 1);
}
this.isStunned = false;
}
this.gravity();
this.seePlayerByHistory(55);
this.checkStatus();
@@ -5835,6 +5842,7 @@ const spawn = {
//teleport to near the end of player history
Matter.Body.setPosition(this, m.history[Math.floor((m.history.length - 1) * (0.66 + 0.33 * Math.random()))].position)
Matter.Body.setVelocity(this, { x: 0, y: 0 });
this.damageReduction = 0 //immune to harm for the rest of this game cycle
}
};
me.cloak = function() {
@@ -5846,6 +5854,14 @@ const spawn = {
}
}
me.do = function() {
if (this.damageReduction === 0) {
this.damageReduction = 1 //stop being immune to harm immediately
let i = this.status.length //clear bad status effects
while (i--) {
if (this.status[i].type === "stun" || this.status[i].type === "dot") this.status.splice(i, 1);
}
this.isStunned = false;
}
this.gravity();
this.seePlayerByHistory(25);
this.checkStatus();

View File

@@ -2382,7 +2382,7 @@ const tech = {
// description: `after you collect ${powerUps.orb.heal()}<br><strong>+${0.1 * tech.largerHeals}</strong> maximum <strong class='color-f'>energy</strong>`,
// descriptionFunction: `convert current and future ${powerUps.orb.heal()} into <div class="heal-circle" style = "background-color: #ff0; border: 0.5px #000 solid;"></div><br><div class="heal-circle" style = "background-color: #ff0; border: 0.5px #000 solid;"></div> give <strong>+${10 * tech.largerHeals}</strong> maximum <strong class='color-f'>energy</strong>`,
descriptionFunction() {
return `convert current and future <div class="heal-circle"></div> into <div class="heal-circle" style = "background-color: #ff0; border: 0.5px #000 solid;"></div><br><div class="heal-circle" style = "background-color: #ff0; border: 0.5px #000 solid;"></div> give <strong>+${8 * tech.largerHeals}</strong> maximum <strong class='color-f'>energy</strong>`
return `convert current and future <div class="heal-circle"></div> into <div class="heal-circle" style = "background-color: #ff0; border: 0.5px #000 solid;"></div><br><div class="heal-circle" style = "background-color: #ff0; border: 0.5px #000 solid;"></div> give <strong>+${8 * tech.largerHeals * (tech.isHalfHeals ? 0.5 : 1)}</strong> maximum <strong class='color-f'>energy</strong>`
},
maxCount: 1,
count: 0,
@@ -2585,7 +2585,7 @@ const tech = {
},
{
name: "energy conservation",
description: "<strong>5%</strong> of <strong class='color-d'>damage</strong> done recovered as <strong class='color-f'>energy</strong>",
description: "<strong>4%</strong> of <strong class='color-d'>damage</strong> done recovered as <strong class='color-f'>energy</strong>",
maxCount: 9,
count: 0,
frequency: 1,
@@ -2595,7 +2595,7 @@ const tech = {
},
requires: "",
effect() {
tech.energySiphon += 0.05;
tech.energySiphon += 0.04;
},
remove() {
tech.energySiphon = 0;
@@ -4151,6 +4151,25 @@ const tech = {
tech.needleTunnel = false
}
},
{
name: "ceramics",
description: `<strong>needles</strong> and <strong>harpoons</strong> pierce <strong>shields</strong><br>directly <strong class='color-d'>damaging</strong> shielded mobs`,
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return (!tech.isLargeHarpoon && tech.haveGunCheck("harpoon")) || tech.isNeedles
},
requires: "needle gun, harpoon, not Bessemer process",
effect() {
tech.isShieldPierce = true
},
remove() {
tech.isShieldPierce = false
}
},
{
name: "needle gun",
description: "<strong>nail gun</strong> and <strong>shotgun</strong> fire mob piercing <strong>needles</strong>",
@@ -4505,6 +4524,25 @@ const tech = {
tech.isShotgunReversed = false;
}
},
{
name: "repeater",
description: "<strong>shotgun</strong> immediately fires again for no <strong class='color-ammo'>ammo</strong><br><strong>-50%</strong> <strong>shotgun</strong> <strong><em>fire rate</em></strong>",
isGunTech: true,
maxCount: 9,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return (tech.haveGunCheck("shotgun"))
},
requires: "shotgun, not Newtons 3rd law",
effect() {
tech.shotgunExtraShots++;
},
remove() {
tech.shotgunExtraShots = 0
}
},
{
name: "nail-shot",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Nail_(fastener)' class="link">nail-shot</a>`,
@@ -5569,7 +5607,7 @@ const tech = {
{
name: "blast ball",
descriptionFunction() {
return `instead of nails <strong>mines</strong> fire bouncy ${b.guns[10].nameString('s')}`
return `instead of nails <strong>mines</strong> fire <strong>bouncy balls</strong>`
},
isGunTech: true,
maxCount: 1,
@@ -6386,7 +6424,7 @@ const tech = {
},
{
name: "railgun",
description: `<strong>harpoons</strong> can't <strong>retract</strong>, hold fire to charge<br><strong>+50%</strong> <strong>harpoon</strong> density and <strong class='color-d'>damage</strong>`,
description: `hold fire to charge <strong>harpoon</strong> and release to launch<br><strong>harpoons</strong> can't <strong>retract</strong>`,
// description: `<strong>+900%</strong> <strong>harpoon</strong> <strong class='color-ammo'>ammo</strong>, but it can't <strong>retract</strong><br><strong>+50%</strong> <strong>harpoon</strong> density and <strong class='color-d'>damage</strong>`,
isGunTech: true,
maxCount: 1,
@@ -6480,25 +6518,6 @@ const tech = {
tech.isRailEnergy = false;
}
},
{
name: "ceramics",
description: `<strong>needles</strong> and <strong>harpoons</strong> pierce <strong>shields</strong><br>directly <strong class='color-d'>damaging</strong> shielded mobs`,
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return (!tech.isLargeHarpoon && tech.haveGunCheck("harpoon")) || tech.isNeedles
},
requires: "needle gun, harpoon, not Bessemer process",
effect() {
tech.isShieldPierce = true
},
remove() {
tech.isShieldPierce = false
}
},
{
name: "Bessemer process",
descriptionFunction() {
@@ -6535,7 +6554,7 @@ const tech = {
return (tech.isRailGun ? 5 : 1) * (2 + 2 * this.count)
},
allowed() {
return tech.haveGunCheck("harpoon") && b.returnGunAmmo('harpoon') >= this.removeAmmo()
return tech.haveGunCheck("harpoon") && b.guns[9].ammo >= this.removeAmmo()
},
requires: "harpoon",
effect() {
@@ -10095,7 +10114,7 @@ const tech = {
m.drawLeg("#4a4a4a");
m.calcLeg(0, 0);
m.drawLeg("#333");
ctx.rotate(m.angle - (m.fireCDcycle != Infinity ? m.flipLegs * 0.25 * Math.pow(Math.max(m.fireCDcycle - m.cycle, 0), 0.5) : 0));
ctx.rotate(m.angle - (m.fireCDcycle !== Infinity ? m.flipLegs * 0.25 * Math.pow(Math.max(m.fireCDcycle - m.cycle, 0), 0.5) : 0));
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
@@ -10510,7 +10529,7 @@ const tech = {
},
{
name: "translucent",
description: "remove your <strong class='color-g'>guns</strong> and <strong>spawn</strong> new ones<br>your <strong class='color-g'>bullets</strong> and bots are transparent",
description: "spawn <strong>3</strong> <strong class='color-g'>gun</strong> power ups<br>your <strong class='color-g'>bullets</strong> and bots are transparent",
maxCount: 1,
count: 0,
frequency: 0,
@@ -10521,18 +10540,18 @@ const tech = {
},
requires: "",
effect() {
for (let i = 0; i < b.inventory.length; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "gun");
for (let i = 0; i < 3; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "gun");
//removes guns and ammo
b.inventory = [];
b.activeGun = null;
b.inventoryGun = 0;
for (let i = 0, len = b.guns.length; i < len; ++i) {
b.guns[i].have = false;
if (b.guns[i].ammo !== Infinity) b.guns[i].ammo = 0;
}
simulation.makeGunHUD(); //update gun HUD
b.bulletDraw = () => {};
// //removes guns and ammo
// b.inventory = [];
// b.activeGun = null;
// b.inventoryGun = 0;
// for (let i = 0, len = b.guns.length; i < len; ++i) {
// b.guns[i].have = false;
// if (b.guns[i].ammo !== Infinity) b.guns[i].ammo = 0;
// }
// simulation.makeGunHUD(); //update gun HUD
b.bulletDraw = () => {}; //make bullets invisible
},
remove() {}
},

View File

@@ -255,16 +255,16 @@ summary {
#experiment-grid {
display: flex;
justify-content: center;
padding: 10px 1px;
padding: 0px;
margin: 0px;
border: 0px;
background-color: var(--build-bg-color);
display: none;
grid-template-columns: repeat(auto-fit, 384px);
grid-auto-flow: row;
grid-auto-rows: minmax(auto, auto);
/* grid-auto-rows: minmax(auto, auto); */
position: relative;
bottom: 0px;
/* bottom: 0px; */
z-index: 10;
font-size: 1.3em;
-ms-overflow-style: none; /* IE and Edge */
@@ -295,6 +295,30 @@ summary {
background-color: #efeff5;
}
.experiment-start-box{
background-color: #fafcfd;
/* font-size: 1em; */
position: sticky;
top:0;
z-index: 10;
align-self: start;
width: 195px;
line-height: 170%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border: 2px #333 solid;
border-top: 0px;
border-radius: 10px;
border-top-left-radius: 0px;
/* border-bottom-left-radius: 0px; */
border-top-right-radius: 0px;
padding:0.2em 0px;
height: 190px;
box-shadow: 8px 8px 7px rgba(0,0,50,0.15);
}
.card-background {
height:340px;
background-size: contain;
@@ -325,6 +349,9 @@ summary {
line-height: 160%;
background-color: #fafcfd;
}
.cancel-card:hover {
background-color: #efeff5;
}
.research-card {
font-size: 1.1em;
font-weight: 100;
@@ -335,6 +362,9 @@ summary {
line-height: 160%;
background-color: #fafcfd;
}
.research-card:hover {
background-color: #efeff5;
}
/* keeps 5 columns at 1440px */

View File

@@ -1,26 +1,34 @@
******************************************************** NEXT PATCH **************************************************
tech: cordyceps - sporangium infect mobs, making them fight for you as zombies
tech: blast ball - mines fire super balls
tech: extended magazine - sentry fires 50% more shots
sentry works with foam, nails, or super balls
tech: repeater - shotgun gets another shot, and a longer fire delay
shotgun cross hairs show when fire is on cooldown
dark patterns - stacks to 9
38->15% damage, 53->15% JUNK
electronegativity - stacks to 9
0.12->0.1% damage per energy
keys 1,2,3,4,5,6,7,8,9,0,-,= switch to a gun in your inventory
Nerfed blinkBoss health and speed
sneaker mobs are immune to harm for one cycles after vanishing
experiment button new style
new images for energy, bots
bug fixes
*********************************************************** TODO *****************************************************
super-bot
tech - only allow 1,2 turrets at time?
turrets drain energy?
turrets never run out of ammo
turrets automatically use one of your mine ammos when they run out?
good with multi gun builds
conflict with booby trap
tech - shotgun triple shot, but a bit longer of a delay
tech: Bose Einstein condensate - freezes enemies in pilot wave, and drains some energy?
super-bot
tech - after standing wave runs out of energy from blocking, gain a buff
buff: defense, damage?
aoe damage like railgun
push mobs away
make super balls with Zectron deflectable with field
but is there a simple way to do this?
@@ -1157,12 +1165,8 @@ if pause is pressed while selecting power ups, display pause menu on top of sele
***major themes missing***
***maybe redo***
dynamical systems
nail-bot
homeostasis
heuristics
thermal runaway - infrared maybe?
redo the energy tech images with by Laurie Greasley
now that you can use --ar 3:2 --stylize 1000 and photo repair
negative feedback - too dark
***past style themes***
field emitter - isometric, clean white robot spherical gun turret on bird legs, blender 3d, style of artstation and behance, Disney Pixar, cute
standing wave - concentric transparent blue geometric circles science