grapple stuff

grappling hook - small quality of life improvements
  about 30% larger, and a new shape (does more damage as a result)
  continues past mobs after hitting them instead of retracting
  pulls faster even at close range
  sticks into walls more reliably
  returns to you when you let go of fire, even when stuck
  loses ammo less often
  drains energy as it pulls

JUNK tech: Mech v4.48 - open a portal to a primordial version of reality (an old scratch game I wrote)
JUNK tech: harvest - convert all the mobs on this level into ammo
pause menu stats are a bit different
This commit is contained in:
landgreen
2022-02-27 06:55:30 -08:00
parent 1ca00d3598
commit 05dbd63a50
10 changed files with 289 additions and 224 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -1348,11 +1348,10 @@ const b = {
Composite.add(engine.world, bullet[me]); //add bullet to world Composite.add(engine.world, bullet[me]); //add bullet to world
}, },
grapple(where, angle = m.angle, isReturn = false, harpoonSize = 1) { grapple(where, angle = m.angle, harpoonSize = 1) {
const me = bullet.length; const me = bullet.length;
const returnRadius = 100 * Math.sqrt(harpoonSize) const returnRadius = 100 * Math.sqrt(harpoonSize)
bullet[me] = Bodies.fromVertices(where.x, where.y, [{ x: -40 * harpoonSize, y: 2 * harpoonSize, index: 0, isInternal: false }, { x: -40 * harpoonSize, y: -2 * harpoonSize, index: 1, isInternal: false }, { x: 50 * harpoonSize, y: -3 * harpoonSize, index: 3, isInternal: false }, { x: 30 * harpoonSize, y: 2 * harpoonSize, index: 4, isInternal: false }], { bullet[me] = Bodies.fromVertices(where.x, where.y, [{ x: -70 * harpoonSize, y: 3 * harpoonSize, index: 0, isInternal: false }, { x: -70 * harpoonSize, y: -3 * harpoonSize, index: 1, isInternal: false }, { x: 45 * harpoonSize, y: -2 * harpoonSize, index: 2, isInternal: false }, { x: 50 * harpoonSize, y: 0, index: 3, isInternal: false }, { x: 45 * harpoonSize, y: 2 * harpoonSize, index: 4, isInternal: false }], {
cycle: 0,
angle: angle, angle: angle,
friction: 1, friction: 1,
frictionAir: 0.4, frictionAir: 0.4,
@@ -1362,12 +1361,13 @@ const b = {
endCycle: simulation.cycle + 45, endCycle: simulation.cycle + 45,
collisionFilter: { collisionFilter: {
category: cat.bullet, category: cat.bullet,
mask: tech.isShieldPierce ? cat.map | cat.body | cat.mob | cat.mobBullet : cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield, mask: tech.isShieldPierce ? cat.body | cat.mob | cat.mobBullet : cat.body | cat.mob | cat.mobBullet | cat.mobShield,
}, },
minDmgSpeed: 4, minDmgSpeed: 4,
ropeExtension: 0, ropeExtension: 0,
lookFrequency: Math.floor(7 + Math.random() * 3), lookFrequency: Math.floor(7 + Math.random() * 3),
density: tech.harpoonDensity, //0.001 is normal for blocks, 0.006 is normal for harpoon, 0.006*6 when buffed density: tech.harpoonDensity, //0.001 is normal for blocks, 0.006 is normal for harpoon, 0.006*6 when buffed
drain: 0.004,
beforeDmg(who) { beforeDmg(who) {
if (tech.isShieldPierce && who.isShielded) { //disable shields if (tech.isShieldPierce && who.isShielded) { //disable shields
who.isShielded = false who.isShielded = false
@@ -1375,19 +1375,10 @@ const b = {
} }
if (tech.fragments) { if (tech.fragments) {
b.targetedNail(this.vertices[2], tech.fragments * 3) b.targetedNail(this.vertices[2], tech.fragments * 3)
if (!isReturn) this.endCycle = 0;
}
if (!who.isBadTarget) {
if (isReturn) {
this.do = this.returnToPlayer
} else {
this.frictionAir = 0.01
this.do = () => {
this.force.y += this.mass * 0.003; //gravity
this.draw();
}
}
} }
// if (!who.isBadTarget) {
// this.do = this.returnToPlayer
// }
}, },
caughtPowerUp: null, caughtPowerUp: null,
dropCaughtPowerUp() { dropCaughtPowerUp() {
@@ -1416,7 +1407,7 @@ const b = {
this.dropCaughtPowerUp() this.dropCaughtPowerUp()
} }
}, },
drawString() { draw() {
const where = { const where = {
x: m.pos.x + 30 * Math.cos(m.angle), x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle) y: m.pos.y + 30 * Math.sin(m.angle)
@@ -1430,8 +1421,9 @@ const b = {
ctx.quadraticCurveTo(controlPoint.x, controlPoint.y, this.vertices[0].x, this.vertices[0].y) ctx.quadraticCurveTo(controlPoint.x, controlPoint.y, this.vertices[0].x, this.vertices[0].y)
// ctx.lineTo(this.vertices[0].x, this.vertices[0].y); // ctx.lineTo(this.vertices[0].x, this.vertices[0].y);
ctx.stroke(); ctx.stroke();
//draw hook
// ctx.beginPath();
}, },
draw() {},
returnToPlayer() { returnToPlayer() {
if (Vector.magnitude(Vector.sub(this.position, m.pos)) < returnRadius) { //near player if (Vector.magnitude(Vector.sub(this.position, m.pos)) < returnRadius) { //near player
this.endCycle = 0; this.endCycle = 0;
@@ -1482,9 +1474,7 @@ const b = {
} }
}, },
do() { do() {
this.cycle++ if (input.fire) { //&& !Matter.Query.collides(this, body).length
if (isReturn) {
if (input.fire) {
this.grabPowerUp() this.grabPowerUp()
if (this.endCycle < simulation.cycle + 1) { //if at end of lifespan, but player is holding down fire, force retraction if (this.endCycle < simulation.cycle + 1) { //if at end of lifespan, but player is holding down fire, force retraction
this.endCycle = simulation.cycle + 60 this.endCycle = simulation.cycle + 60
@@ -1514,25 +1504,14 @@ const b = {
this.collisionFilter.mask = cat.map | cat.mob | cat.mobBullet | cat.mobShield // | cat.body this.collisionFilter.mask = cat.map | cat.mob | cat.mobBullet | cat.mobShield // | cat.body
} }
} }
//grappling hook //grappling hook
if (input.fire && Matter.Query.collides(this, map).length) { if (input.fire && Matter.Query.collides(this, map).length) {
const pull = Vector.mult(Vector.normalise(Vector.sub(this.position, m.pos)), 0.1) Matter.Body.setPosition(this, Vector.add(this.position, { x: 20 * Math.cos(this.angle), y: 20 * Math.sin(this.angle) }))
player.force.x += pull.x
player.force.y += pull.y - player.mass * 0.02
const move = { x: 50 * Math.cos(this.angle), y: 50 * Math.sin(this.angle), }
Matter.Body.setPosition(this, Vector.add(this.position, move))
if (Matter.Query.collides(this, map).length) { if (Matter.Query.collides(this, map).length) {
Matter.Body.setStatic(this, true) Matter.Sleeping.set(this, true)
this.endCycle = simulation.cycle + 5 this.endCycle = simulation.cycle + 5
this.dropCaughtPowerUp() this.dropCaughtPowerUp()
this.do = () => { this.do = () => {
// const grappleBack = {
// x: this.position.x - 50 * Math.cos(this.angle),
// y: this.position.y - 50 * Math.sin(this.angle)
// }
//between player nose and the grapple //between player nose and the grapple
const sub = Vector.sub(this.vertices[0], { const sub = Vector.sub(this.vertices[0], {
x: m.pos.x + 30 * Math.cos(m.angle), x: m.pos.x + 30 * Math.cos(m.angle),
@@ -1540,14 +1519,6 @@ const b = {
}) })
let dist = Vector.magnitude(sub) - this.ropeExtension let dist = Vector.magnitude(sub) - this.ropeExtension
if (input.fire) { if (input.fire) {
m.fireCDcycle = m.cycle + 30; // cool down if out of energy
this.endCycle = simulation.cycle + 10
Matter.Body.setVelocity(player, { x: player.velocity.x * 0.8, y: player.velocity.y * 0.8 });
if (input.down) { //down
dist *= 0.25
player.force.y += 5 * player.mass * simulation.g;
}
//control position while hooked //control position while hooked
// if (input.down) { //down // if (input.down) { //down
// player.force.y += 5 * player.mass * simulation.g; // player.force.y += 5 * player.mass * simulation.g;
@@ -1567,17 +1538,23 @@ const b = {
// dist *= 0.4 // dist *= 0.4
// player.force.x -= 5 * player.mass * simulation.g; // player.force.x -= 5 * player.mass * simulation.g;
// } // }
if (!tech.isRailEnergyGain && m.energy > 0.004 && dist > 400) m.energy -= 0.004 m.fireCDcycle = m.cycle + 30; // cool down if out of energy
const pull = Vector.mult(Vector.normalise(sub), 0.00035 * Math.min(Math.max(30, dist), 500)) this.endCycle = simulation.cycle + 10
if (input.down) { //down
dist = 0
player.force.y += 5 * player.mass * simulation.g;
}
if (m.energy > this.drain || tech.isRailEnergyGain) {
Matter.Body.setVelocity(player, { x: player.velocity.x * 0.8, y: player.velocity.y * 0.8 });
const pull = Vector.mult(Vector.normalise(sub), 0.0008 * Math.min(Math.max(15, dist), 200))
player.force.x += pull.x player.force.x += pull.x
player.force.y += pull.y player.force.y += pull.y
} else { //if (Vector.magnitude(Vector.sub(this.position, m.pos)) < returnRadius + 200)
// if (input.up) { //up if (!tech.isRailEnergyGain && dist > 500) {
// player.force.y -= 20 * player.mass * simulation.g; m.energy -= this.drain
// } if (m.energy < 0) {
//automatically get ammo back
this.endCycle = 0; this.endCycle = 0;
if (m.cycle + 15 * b.fireCDscale < m.fireCDcycle) m.fireCDcycle = m.cycle + 15 * b.fireCDscale //lower cd to 15 if it is above 15 if (m.cycle + 50 < m.fireCDcycle) m.fireCDcycle = m.cycle + 50
// refund ammo // refund ammo
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "harpoon") { if (b.guns[i].name === "harpoon") {
@@ -1587,7 +1564,30 @@ const b = {
} }
} }
} }
// if (dist > returnRadius) }
}
// if (tech.isIntangibleGrapple) {
// player.collisionFilter.mask = cat.map
// let inPlayer = Matter.Query.region(mob, player.bounds)
// if (inPlayer.length > 0) {
// for (let i = 0; i < inPlayer.length; i++) {
// if (m.energy > 0 && inPlayer[i].shield) m.energy -= 0.014;
// }
// }
// //check for disabling intangible in next cycle
// requestAnimationFrame(() => {
// if (!tech.isIntangibleGrapple || !input.fire || this.) {
// player.collisionFilter.mask = cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield //normal collisions
// }
// });
// }
} else {
Matter.Sleeping.set(this, false)
this.collisionFilter.category = 0
this.collisionFilter.mask = 0
this.do = this.returnToPlayer
this.endCycle = simulation.cycle + 60
}
this.draw(); this.draw();
} }
} }
@@ -1595,36 +1595,8 @@ const b = {
this.force.x += this.thrustMag * this.mass * Math.cos(this.angle); this.force.x += this.thrustMag * this.mass * Math.cos(this.angle);
this.force.y += this.thrustMag * this.mass * Math.sin(this.angle); this.force.y += this.thrustMag * this.mass * Math.sin(this.angle);
this.draw() this.draw()
}
}, },
}); });
if (!isReturn) {
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + 60 * Math.cos(bullet[me].angle),
y: m.Vy / 2 + 60 * Math.sin(bullet[me].angle)
});
bullet[me].frictionAir = 0.002
bullet[me].do = function() {
if (this.speed < 20) this.force.y += 0.0005 * this.mass;
this.draw();
}
}
if (tech.isHarpoonPowerUp && bullet[me].density > 0.01) {
if (isReturn) {
bullet[me].draw = function() {
this.drawToggleHarpoon()
this.drawString()
}
} else {
bullet[me].draw = function() {
this.drawToggleHarpoon()
}
}
} else if (isReturn) {
bullet[me].draw = function() {
this.drawString()
}
}
Composite.add(engine.world, bullet[me]); //add bullet to world Composite.add(engine.world, bullet[me]); //add bullet to world
}, },
harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35) { harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35) {
@@ -6122,7 +6094,7 @@ const b = {
simulation.updateGunHUD(); simulation.updateGunHUD();
m.fireCDcycle = m.cycle + 90 // cool down m.fireCDcycle = m.cycle + 90 // cool down
} else { } else {
b.grapple(where, m.angle, !input.down, harpoonSize) b.grapple(where, m.angle, harpoonSize)
} }
m.fireCDcycle = m.cycle + 45 // cool down m.fireCDcycle = m.cycle + 45 // cool down
}, },

View File

@@ -257,31 +257,37 @@ const build = {
if (tech.plasmaBotCount) botText += `<br>plasma-bots: ${tech.plasmaBotCount}` if (tech.plasmaBotCount) botText += `<br>plasma-bots: ${tech.plasmaBotCount}`
if (tech.missileBotCount) botText += `<br>missile-bots: ${tech.missileBotCount}` if (tech.missileBotCount) botText += `<br>missile-bots: ${tech.missileBotCount}`
const harm = (1 - m.harmReduction()) * 100
let text = `<div class="pause-grid-module" style = "font-size: 13px;line-height: 120%;padding: 5px;">` 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 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;"> <br><br><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> <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>` </svg><br>`
text += `<strong class='color-d'>damage</strong> increase: ${((tech.damageFromTech()-1)*100).toFixed(0)}% //{ /* <strong class='color-d'>damage</strong> increase: ${((tech.damageFromTech()-1)*100).toFixed(0)}% */ }
<br><strong class='color-harm'>harm</strong> reduction: ${harm.toFixed(harm > 90 ? 2 : 0)}% // <br>damage difficulty reduction: ${((1-m.dmgScale)*100).toFixed(2)}%
<br><strong><em>fire delay</em></strong> decrease: ${((1-b.fireCDscale)*100).toFixed(b.fireCDscale < 0.1 ? 2 : 0)}% // <br>effective damage: ${(((tech.damageFromTech()-1)*m.dmgScale)*100).toFixed(0)}%
<br><strong class='color-dup'>duplication</strong> chance: ${(tech.duplicationChance()*100).toFixed(0)}% // <br>
${botText} // <br><strong class='color-d'>damage</strong> = ${((tech.damageFromTech())*100).toFixed(0)}% × ${((m.dmgScale)*100).toFixed(2)}% = ${(((tech.damageFromTech())*m.dmgScale)*100).toFixed(0)}%
/// <br>heal difficulty scale: ${(simulation.healScale*100).toFixed(1)}%
text +=
`
<br>effective <strong class='color-d'>damage</strong>: ${(tech.damageFromTech() * m.dmgScale).toPrecision(4)}
<br>damage: ${((tech.damageFromTech())).toPrecision(4)}, difficulty: ${((m.dmgScale)).toPrecision(4)}
<br> <br>
<br><strong class='color-m'>tech</strong>: ${tech.totalCount} &nbsp; <strong class='color-r'>research</strong>: ${powerUps.research.count} <br>effective <strong class='color-harm'>harm</strong>: ${(simulation.dmgScale*m.harmReduction()).toPrecision(4)}
<br>reduction: ${(m.harmReduction()).toPrecision(4)}, difficulty: ${(simulation.dmgScale).toPrecision(4)}
<br>
${botText}
<br><strong class='color-h'>health</strong>: (${(m.health*100).toFixed(0)} / ${(m.maxHealth*100).toFixed(0)}) &nbsp; <strong class='color-f'>energy</strong>: (${(m.energy*100).toFixed(0)} / ${(m.maxEnergy*100).toFixed(0)}) <br><strong class='color-h'>health</strong>: (${(m.health*100).toFixed(0)} / ${(m.maxHealth*100).toFixed(0)}) &nbsp; <strong class='color-f'>energy</strong>: (${(m.energy*100).toFixed(0)} / ${(m.maxEnergy*100).toFixed(0)})
<br><strong class='color-g'>gun</strong>: ${b.activeGun !== null ? b.guns[b.activeGun].name: "null"} &nbsp; <strong class='color-g'>ammo</strong>: ${b.activeGun !== null ? b.guns[b.activeGun].ammo: "0"} <br><strong class='color-g'>gun</strong>: ${b.activeGun !== null ? b.guns[b.activeGun].name: "null"} &nbsp; <strong class='color-g'>ammo</strong>: ${b.activeGun !== null ? b.guns[b.activeGun].ammo: "0"}
<br><strong><em>fire delay</em></strong> decrease: ${((1-b.fireCDscale)*100).toFixed(b.fireCDscale < 0.1 ? 2 : 0)}%
<br><strong class='color-dup'>duplication</strong> chance: ${(tech.duplicationChance()*100).toFixed(0)}%
<br><strong class='color-m'>tech</strong>: ${tech.totalCount} &nbsp; <strong class='color-r'>research</strong>: ${powerUps.research.count}
<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>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>mouse: (${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)}) &nbsp; mass: ${player.mass.toFixed(1)}
<br> <br>
<br>seed: ${Math.initialSeed} <br>seed: ${Math.initialSeed}
<br>level: ${level.levels[level.onLevel]} (${level.difficultyText()}) &nbsp; ${m.cycle} cycles <br>level: ${level.levels[level.onLevel]} (${level.difficultyText()}) &nbsp; ${m.cycle} cycles
<br>${mob.length} mobs, &nbsp; ${body.length} blocks, &nbsp; ${bullet.length} bullets, &nbsp; ${powerUp.length} power ups <br>${mob.length} mobs, &nbsp; ${body.length} blocks, &nbsp; ${bullet.length} bullets, &nbsp; ${powerUp.length} power ups
<br>damage difficulty scale: ${(m.dmgScale*100).toFixed(2) }%
<br>harm difficulty scale: ${(simulation.dmgScale*100).toFixed(0)}%
<br>heal difficulty scale: ${(simulation.healScale*100).toFixed(1)}%
${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""} ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
</div>`; </div>`;
for (let i = 0, len = b.inventory.length; i < len; i++) { for (let i = 0, len = b.inventory.length; i < len; i++) {

View File

@@ -18,7 +18,7 @@ const level = {
// m.setField("time dilation") // m.setField("time dilation")
// b.giveGuns("harpoon") // b.giveGuns("harpoon")
// for (let i = 0; i < 9; i++) tech.giveTech("smelting") // for (let i = 0; i < 9; i++) tech.giveTech("smelting")
// tech.giveTech("UHMWPE") // tech.giveTech("boson quasiparticles")
// tech.giveTech("grappling hook") // tech.giveTech("grappling hook")
// for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech"); // for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech");
// for (let i = 0; i < 3; i++) tech.giveTech("undefined") // for (let i = 0; i < 3; i++) tech.giveTech("undefined")
@@ -32,7 +32,7 @@ const level = {
// simulation.enableConstructMode() //used to build maps in testing mode // simulation.enableConstructMode() //used to build maps in testing mode
// level.reactor(); // level.reactor();
// level.testing(); //not in rotation, used for testing // level.testing(); //not in rotation, used for testing
// level.run() // level.pavilion()
if (simulation.isTraining) { level.walk(); } else { level.intro(); } if (simulation.isTraining) { level.walk(); } else { level.intro(); }
// powerUps.research.changeRerolls(3000) // powerUps.research.changeRerolls(3000)
@@ -2547,7 +2547,7 @@ const level = {
// spawn.launcherBoss(3200, -500) // spawn.launcherBoss(3200, -500)
// spawn.laserTargetingBoss(1700, -500) // spawn.laserTargetingBoss(1700, -500)
// spawn.powerUpBoss(1900, -500) // spawn.powerUpBoss(1900, -500)
// spawn.powerUpBossBaby(3200, -500) spawn.powerUpBossBaby(3200, -500)
// spawn.snakeBoss(1700, -500) // spawn.snakeBoss(1700, -500)
// spawn.streamBoss(3200, -500) // spawn.streamBoss(3200, -500)
// spawn.pulsarBoss(1700, -500) // spawn.pulsarBoss(1700, -500)

View File

@@ -803,27 +803,27 @@ const mobs = {
} }
} }
}, },
invulnerability() { // invulnerability() {
if (this.isInvulnerable) { // if (this.isInvulnerable) {
if (this.invulnerabilityCountDown > 0) { // if (this.invulnerabilityCountDown > 0) {
this.invulnerabilityCountDown-- // this.invulnerabilityCountDown--
//graphics //draw a super shield? // //graphics //draw a super shield?
ctx.beginPath(); // ctx.beginPath();
let vertices = this.vertices; // let vertices = this.vertices;
ctx.moveTo(vertices[0].x, vertices[0].y); // ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y); // for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y); // ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 20; // ctx.lineWidth = 20;
// ctx.fillStyle = `rgba(${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},0.5)` // // ctx.fillStyle = `rgba(${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},0.5)`
// ctx.fill(); // // ctx.fill();
ctx.strokeStyle = "rgba(255,255,255,0.4)"; // ctx.strokeStyle = "rgba(255,255,255,0.4)";
ctx.stroke(); // ctx.stroke();
} else { // } else {
this.isInvulnerable = false // this.isInvulnerable = false
this.damageReduction = this.startingDamageReduction // this.damageReduction = this.startingDamageReduction
} // }
} // }
}, // },
grow() { grow() {
if (this.seePlayer.recall) { if (this.seePlayer.recall) {
if (this.radius < 80) { if (this.radius < 80) {

View File

@@ -872,7 +872,7 @@ const powerUps = {
powerUps.research.currentRerollCount = 0 powerUps.research.currentRerollCount = 0
if (tech.isTechDamage && who.name === "tech") m.damage(0.11) if (tech.isTechDamage && who.name === "tech") m.damage(0.11)
if (tech.isMassEnergy) m.energy += 2; if (tech.isMassEnergy) m.energy += 2;
if (tech.isMineDrop && bullet.length < 150 && Math.random() < 0.66) { if (tech.isMineDrop && bullet.length < 150 && Math.random() < 0.60) {
if (tech.isLaserMine && input.down) { if (tech.isLaserMine && input.down) {
b.laserMine(who.position) b.laserMine(who.position)
} else { } else {

View File

@@ -121,7 +121,7 @@ const simulation = {
fpsCapDefault: 72, //use to change fpsCap back to normal after a hit from a mob fpsCapDefault: 72, //use to change fpsCap back to normal after a hit from a mob
isCommunityMaps: false, isCommunityMaps: false,
cyclePaused: 0, cyclePaused: 0,
fallHeight: 5000, //below this y position the player dies fallHeight: 6000, //below this y position the player dies
lastTimeStamp: 0, //tracks time stamps for measuring delta lastTimeStamp: 0, //tracks time stamps for measuring delta
delta: 1000 / 60, //speed of game engine //looks like it has to be 16 to match player input delta: 1000 / 60, //speed of game engine //looks like it has to be 16 to match player input
buttonCD: 0, buttonCD: 0,

View File

@@ -1238,8 +1238,8 @@ const spawn = {
ctx.moveTo(vertices[0].x, vertices[0].y); ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y); for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y); ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 20; ctx.lineWidth = 13 + 5 * Math.random();
ctx.strokeStyle = "rgba(255,255,255,0.7)"; ctx.strokeStyle = `rgba(255,255,255,${0.5+0.2*Math.random()})`;
ctx.stroke(); ctx.stroke();
} else { } else {
this.isInvulnerable = false this.isInvulnerable = false
@@ -2010,8 +2010,8 @@ const spawn = {
ctx.lineTo(vertices[0].x, vertices[0].y); ctx.lineTo(vertices[0].x, vertices[0].y);
} }
} }
ctx.lineWidth = 20; ctx.lineWidth = 13 + 5 * Math.random();
ctx.strokeStyle = "rgba(255,255,255,0.7)"; ctx.strokeStyle = `rgba(255,255,255,${0.5+0.2*Math.random()})`;
ctx.stroke(); ctx.stroke();
} else if (this.invulnerabilityCountDown > 0) { } else if (this.invulnerabilityCountDown > 0) {
this.invulnerabilityCountDown-- this.invulnerabilityCountDown--
@@ -3420,10 +3420,8 @@ const spawn = {
ctx.moveTo(vertices[0].x, vertices[0].y); ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y); for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y); ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 20; ctx.lineWidth = 13 + 5 * Math.random();
// ctx.fillStyle = `rgba(${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},0.5)` ctx.strokeStyle = `rgba(255,255,255,${0.5+0.2*Math.random()})`;
// ctx.fill();
ctx.strokeStyle = "rgba(255,255,255,0.7)";
ctx.stroke(); ctx.stroke();
} else { } else {
this.isInvulnerable = false this.isInvulnerable = false
@@ -3702,8 +3700,8 @@ const spawn = {
ctx.moveTo(vertices[0].x, vertices[0].y); ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y); for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y); ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 20; ctx.lineWidth = 13 + 5 * Math.random();
ctx.strokeStyle = "rgba(255,255,255,0.7)"; ctx.strokeStyle = `rgba(255,255,255,${0.5+0.2*Math.random()})`;
ctx.stroke(); ctx.stroke();
} }
this.checkStatus(); this.checkStatus();
@@ -3840,8 +3838,8 @@ const spawn = {
ctx.moveTo(vertices[0].x, vertices[0].y); ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y); for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y); ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 20; ctx.lineWidth = 13 + 5 * Math.random();
ctx.strokeStyle = "rgba(255,255,255,0.7)"; ctx.strokeStyle = `rgba(255,255,255,${0.5+0.2*Math.random()})`;
ctx.stroke(); ctx.stroke();
} else if (this.mass < 100) { } else if (this.mass < 100) {
Matter.Body.scale(this, 1.01, 1.01); //grow back to normal size Matter.Body.scale(this, 1.01, 1.01); //grow back to normal size
@@ -3970,8 +3968,8 @@ const spawn = {
ctx.moveTo(vertices[0].x, vertices[0].y); ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y); for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y); ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 20; ctx.lineWidth = 13 + 5 * Math.random();
ctx.strokeStyle = "rgba(255,255,255,0.7)"; ctx.strokeStyle = `rgba(255,255,255,${0.5+0.2*Math.random()})`;
ctx.stroke(); ctx.stroke();
} }
me.swordSlash = function() { me.swordSlash = function() {
@@ -3992,8 +3990,8 @@ const spawn = {
ctx.moveTo(vertices[0].x, vertices[0].y); ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y); for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y); ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 20; ctx.lineWidth = 13 + 5 * Math.random();
ctx.strokeStyle = "rgba(255,255,255,0.7)"; ctx.strokeStyle = `rgba(255,255,255,${0.5+0.2*Math.random()})`;
ctx.stroke(); ctx.stroke();
} }
me.laserSword = function(where, angle) { me.laserSword = function(where, angle) {

View File

@@ -4831,7 +4831,7 @@ const tech = {
}, },
{ {
name: "booby trap", name: "booby trap",
description: "<strong>50%</strong> chance to drop a <strong>mine</strong> from <strong>power ups</strong><br><strong>+50%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool", description: "<strong>60%</strong> chance to drop a <strong>mine</strong> from <strong>power ups</strong><br><strong>+46%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -4844,7 +4844,7 @@ const tech = {
effect() { effect() {
tech.isMineDrop = true; tech.isMineDrop = true;
if (tech.isMineDrop) b.mine(m.pos, { x: 0, y: 0 }, 0) if (tech.isMineDrop) b.mine(m.pos, { x: 0, y: 0 }, 0)
this.refundAmount += tech.addJunkTechToPool(0.5) this.refundAmount += tech.addJunkTechToPool(0.46)
}, },
refundAmount: 0, refundAmount: 0,
remove() { remove() {
@@ -5557,7 +5557,7 @@ const tech = {
// }, // },
{ {
name: "grappling hook", name: "grappling hook",
description: `<strong>harpoons</strong> attach to the <strong>map</strong> and pull you in<br><strong>rope</strong> extends much <strong>farther</strong> while you hold fire`, description: `<strong>harpoons</strong> attach to the <strong>map</strong> and pull you in<br>your <strong>rope</strong> extends while holding <strong>fire</strong>`,
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -5582,6 +5582,46 @@ const tech = {
} }
} }
}, },
// {
// name: "exchange interaction",
// description: `<strong>immune</strong> to <strong class='color-harm'>harm</strong> while <strong>grappling</strong>`,
// // link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Boson' class="link">boson</a>`,
// isGunTech: true,
// maxCount: 1,
// count: 0,
// frequency: 2,
// frequencyDefault: 2,
// allowed() {
// return tech.isGrapple && !tech.isRailEnergyGain
// },
// requires: "grappling hook, not alternator",
// effect() {
// tech.isIntangibleGrapple = true;
// },
// remove() {
// tech.isIntangibleGrapple = false
// }
// },
// {
// name: "boson quasiparticles",
// description: `<strong>intangible</strong> to <strong class='color-block'>blocks</strong> and mobs while <strong>grappling</strong><br>passing through <strong>shields</strong> drains your <strong class='color-f'>energy</strong>`,
// link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Boson' class="link">boson</a>`,
// isGunTech: true,
// maxCount: 1,
// count: 0,
// frequency: 2,
// frequencyDefault: 2,
// allowed() {
// return tech.isGrapple && !tech.isRailEnergyGain
// },
// requires: "grappling hook, not alternator",
// effect() {
// tech.isIntangibleGrapple = true;
// },
// remove() {
// tech.isIntangibleGrapple = false
// }
// },
{ {
name: "alternator", name: "alternator",
description: "<strong>harpoon</strong> and <strong>grappling hook</strong> drain no <strong class='color-f'>energy</strong><br><strong>railgun</strong> generates <strong class='color-f'>energy</strong>", //as they <strong>retract</strong><br><strong>crouch</strong> firing <strong>harpoon</strong> generates <strong class='color-f'>energy</strong>", description: "<strong>harpoon</strong> and <strong>grappling hook</strong> drain no <strong class='color-f'>energy</strong><br><strong>railgun</strong> generates <strong class='color-f'>energy</strong>", //as they <strong>retract</strong><br><strong>crouch</strong> firing <strong>harpoon</strong> generates <strong class='color-f'>energy</strong>",
@@ -7476,6 +7516,27 @@ const tech = {
}, },
remove() {} remove() {}
}, },
{
name: "harvest",
description: "convert all the mobs on this level into <strong class='color-ammo'>ammo</strong>",
maxCount: 1,
count: 0,
frequency: 0,
frequencyDefault: 0,
isJunk: true,
isNonRefundable: true,
allowed() {
return true
},
requires: "",
effect() {
for (let i = 0, len = mob.length; i < len; i++) {
powerUps.directSpawn(mob[i].position.x, mob[i].position.y, "ammo");
mob[i].death();
}
},
remove() {}
},
{ {
name: "brainstorm", name: "brainstorm",
description: "the <strong class='color-m'>tech</strong> choice menu <strong>randomizes</strong><br>every <strong>0.5</strong> seconds for <strong>10</strong> seconds", description: "the <strong class='color-m'>tech</strong> choice menu <strong>randomizes</strong><br>every <strong>0.5</strong> seconds for <strong>10</strong> seconds",
@@ -7611,6 +7672,21 @@ const tech = {
if (this.count) m.look = m.lookDefault if (this.count) m.look = m.lookDefault
} }
}, },
{
name: "Mech v4.48",
description: `open a portal to a primordial version of reality`,
maxCount: 1,
count: 0,
frequency: 0,
isNonRefundable: true,
isJunk: true,
allowed() { return true },
requires: "",
effect() {
window.open('https://scratch.mit.edu/projects/14005697/fullscreen/', '_blank')
},
remove() {}
},
{ {
name: "planetesimals", name: "planetesimals",
description: `play <strong>planetesimals</strong> <em style = 'font-size:80%;'>(an asteroids-like game)</em><br>clear <strong>levels</strong> in <strong>planetesimals</strong> to spawn <strong class='color-m'>tech</strong><br>if you <strong style="color:red;">die</strong> in <strong>planetesimals</strong> you <strong style="color:red;">die</strong> in <strong>n-gon</strong>`, description: `play <strong>planetesimals</strong> <em style = 'font-size:80%;'>(an asteroids-like game)</em><br>clear <strong>levels</strong> in <strong>planetesimals</strong> to spawn <strong class='color-m'>tech</strong><br>if you <strong style="color:red;">die</strong> in <strong>planetesimals</strong> you <strong style="color:red;">die</strong> in <strong>n-gon</strong>`,
@@ -9411,5 +9487,6 @@ const tech = {
isTimeCrystals: null, isTimeCrystals: null,
isGroundState: null, isGroundState: null,
isRailGun: null, isRailGun: null,
isGrapple: null isGrapple: null,
// isIntangibleGrapple: null
} }

View File

@@ -1,28 +1,44 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
tech grappling hook - can attack to walls and pull you towards the walls grappling hook - small quality of life improvements
harpoon extends farther as you hold down fire, but no longer has auto-steering about 30% larger, and a new shape (does more damage as a result)
continues past mobs after hitting them instead of retracting
pulls faster even at close range
sticks into walls more reliably
returns to you when you let go of fire, even when stuck
loses ammo less often
drains energy as it pulls
mobs do 4% less harm per difficulty level JUNK tech: Mech v4.48 - open a portal to a primordial version of reality (an old scratch game I wrote)
railgun/harpoon auto-targeting is smarter at long distances with multiple small targets JUNK tech: harvest - convert all the mobs on this level into ammo
but it still has trouble with moving targets pause menu stats are a bit different
booby trap only has a 100 -> 50% chance to drop a mine when picking up power ups
added fallback for browsers that don't allow local storage
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
grappling hook grappling hook
new shape, different from harpoon fire delay reduction doesn't have much effect
how to draw convex? tech: give harm immunity while being pulled?
composite make not stack with alternator? so no energy regen
tech: give no collisions, like boson composite while attached to harpoon
make not stack with alternator? so no energy regen
this was annoying to code, but probably doable
draw the hook part directly draw the hook part directly
two backwards angled spikes near the front
give player more control over motion while hanging and retracting give player more control over motion while hanging and retracting
reduce friction effects so player swing around? reduce friction effects so player swing around?
up down left right push player around? up down left right push player around?
lengthen and shrink the rope length? scale velocity dampening with distance to grapple?
scale velocity dampening with distance to grapple
get induction furnace working? tech that does less damage the more tech you have?
I'm not a fan of this tech, I'd be happy if it was basic harpoon only tech.totalCount
add coyote jump
log game m.cycle when last on ground
for jump check if game cycle is < last on ground cycle -2
setting to remove UI, except health bar
except active gun? to see ammo
checkbox in pause and in settings
tech - Plasma railgun tech - Plasma railgun
like foam, or phonon? like foam, or phonon?
@@ -34,10 +50,6 @@ pause time like invariant for other things...
bug - url sharing still broken sometimes bug - url sharing still broken sometimes
setting to remove UI, except health bar
except active gun? to see ammo
checkbox in pause and in settings
+damage for each different bot type you have +damage for each different bot type you have
disables bot upgrades? disables bot upgrades?