grappling hook field

grappling hook is now a field  (work in progress)
  reworked physics to allow faster speeds, but more control
  improved rate of power up grabbing
  more player control to hook retraction rate
  changed hook shape and field image graphics
  grappling hook field coupling, more tech, bug fixes, and general polish to be added soon

aerostat - 88->100% damage in air  22-> 25% damage on ground
foam damage reduced 10%, ammo increased about 10%
after hitting an invulnerable mob (drones,spores,worms,iceIX,fleas) don't die or lose cycles
added JUNK tech: mobs! - summon 20 random mobs
added announcement of mob names in console at start of new level

bug fixes
This commit is contained in:
landgreen
2023-11-18 17:49:01 -08:00
parent 3844d00ef6
commit e9d226259e
10 changed files with 800 additions and 600 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

View File

@@ -1460,50 +1460,89 @@ const b = {
// Composite.add(engine.world, bullet[me]); //add bullet to world
// },
grapple(where, angle = m.angle, harpoonSize = 1) {
grapple(where, angle = m.angle) {
const me = bullet.length;
const returnRadius = 100 * Math.sqrt(harpoonSize)
const returnRadius = 100
bullet[me] = Bodies.fromVertices(where.x, where.y, [{
x: -50 * harpoonSize,
y: 2 * harpoonSize,
x: -40,
y: 2,
index: 0,
isInternal: false
}, {
x: -50 * harpoonSize,
y: -2 * harpoonSize,
x: -40,
y: -2,
index: 1,
isInternal: false
}, {
x: 45 * harpoonSize,
y: -3 * harpoonSize,
x: 37,
y: -2,
index: 2,
isInternal: false
}, {
x: 50 * harpoonSize,
y: 0,
x: 40,
y: -1,
index: 3,
isInternal: false
}, {
x: 45 * harpoonSize,
y: 3 * harpoonSize,
x: 34,
y: 5,
index: 4,
isInternal: false
}], {
}],
// [{
// x: -10,
// y: 2,
// index: 0,
// isInternal: false
// }, {
// x: -10,
// y: -2,
// index: 1,
// isInternal: false
// }, {
// x: 35,
// y: -3,
// index: 2,
// isInternal: false
// }, {
// x: 37,
// y: -2,
// index: 3,
// isInternal: false
// }, {
// x: 40,
// y: 0,
// index: 4,
// isInternal: false
// }, {
// x: 37,
// y: 2,
// index: 5,
// isInternal: false
// }, {
// x: 35,
// y: 3,
// index: 6,
// isInternal: false
// }],
{
angle: angle,
friction: 1,
frictionAir: 0.4,
thrustMag: 0.1,
thrustMag: 0.13,
dmg: 6, //damage done in addition to the damage from momentum
classType: "bullet",
endCycle: simulation.cycle + 70,
isSlowPull: false,
collisionFilter: {
category: cat.bullet,
mask: tech.isShieldPierce ? cat.body | cat.mob | cat.mobBullet : cat.body | cat.mob | cat.mobBullet | cat.mobShield,
},
minDmgSpeed: 4,
lookFrequency: Math.floor(7 + Math.random() * 3),
density: tech.harpoonDensity, //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed
drain: tech.isRailEnergy ? 0.0006 : 0.006,
// lookFrequency: Math.floor(7 + Math.random() * 3),
density: 0.004, //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed
drain: 0.001,
beforeDmg(who) {
if (tech.isShieldPierce && who.isShielded) { //disable shields
who.isShielded = false
@@ -1511,20 +1550,22 @@ const b = {
who.isShielded = true
});
}
if (tech.fragments) {
b.targetedNail(this.vertices[2], tech.fragments * Math.floor(2 + Math.random()))
}
if (tech.isFoamBall) {
for (let i = 0, len = 3 * this.mass; i < len; i++) {
const radius = 5 + 8 * Math.random()
const velocity = {
x: Math.max(0.5, 2 - radius * 0.1),
y: 0
}
b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius)
}
// this.endCycle = 0;
}
// if (tech.fragments) {
// b.targetedNail(this.vertices[2], tech.fragments * Math.floor(2 + Math.random()))
// }
// if (tech.isFoamBall) {
// for (let i = 0, len = 3 * this.mass; i < len; i++) {
// const radius = 5 + 8 * Math.random()
// const velocity = {
// x: Math.max(0.5, 2 - radius * 0.1),
// y: 0
// }
// b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius)
// }
// // this.endCycle = 0;
// }
if (m.fieldCDcycle < m.cycle + 40) m.fieldCDcycle = m.cycle + 40 //extra long cooldown on hitting mobs
this.retract()
},
caughtPowerUp: null,
dropCaughtPowerUp() {
@@ -1582,32 +1623,26 @@ const b = {
ctx.fillStyle = '#000'
ctx.fill();
},
returnToPlayer() {
if (Vector.magnitude(Vector.sub(this.position, m.pos)) < returnRadius) { //near player
this.endCycle = 0;
// if (m.energy < 0.05) {
// m.fireCDcycle = m.cycle + 120; //fire cooldown
// } else if (m.cycle + 15 * b.fireCDscale < m.fireCDcycle) {
// m.fireCDcycle = m.cycle + 15 * b.fireCDscale //lower cd to 25 if it is above 25
// }
if (m.energy < 0.05) this.dropCaughtPowerUp()
//recoil on catching
retract() {
this.do = this.returnToPlayer
this.endCycle = simulation.cycle + 60
Matter.Body.setDensity(this, 0.0005); //reduce density on return
if (this.angularSpeed < 0.5) this.torque += this.inertia * 0.001 * (Math.random() - 0.5) //(Math.round(Math.random()) ? 1 : -1)
this.collisionFilter.mask = 0//cat.map | cat.mob | cat.mobBullet | cat.mobShield // | cat.body
//recoil on pulling grapple back
const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (m.crouch ? 0.0001 : 0.0002))
player.force.x += momentum.x
player.force.y += momentum.y
},
returnToPlayer() {
if (m.fieldCDcycle < m.cycle + 5) m.fieldCDcycle = m.cycle + 5
if (Vector.magnitude(Vector.sub(this.position, m.pos)) < returnRadius) { //near player
this.endCycle = 0;
//recoil on catching grapple
const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (m.crouch ? 0.0001 : 0.0002))
player.force.x += momentum.x
player.force.y += momentum.y
// refund ammo
b.guns[9].ammo++;
simulation.updateGunHUD();
// 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)
@@ -1619,48 +1654,71 @@ const b = {
}
this.draw();
},
destroyBlocks() {
const blocks = Matter.Query.collides(this, body)
if (blocks.length && !blocks[0].bodyA.isNotHoldable) {
if (blocks[0].bodyA.mass > 2.5) this.retract()
const block = blocks[0].bodyA.vertices
Composite.remove(engine.world, blocks[0].bodyA)
body.splice(body.indexOf(blocks[0].bodyA), 1)
//animate the block fading away
simulation.ephemera.push({
name: "blockFadeOut",
count: 25, //cycles before it self removes
do() {
this.count--
if (this.count < 0) simulation.removeEphemera(this.name)
ctx.beginPath();
ctx.moveTo(block[0].x, block[0].y);
for (let j = 1; j < block.length; j++) ctx.lineTo(block[j].x, block[j].y);
ctx.lineTo(block[0].x, block[0].y);
ctx.lineWidth = 2;
ctx.strokeStyle = `rgba(0,0,0,${this.count / 25})`
ctx.stroke();
},
})
}
},
grabPowerUp() { //grab power ups near the tip of the harpoon
if (this.caughtPowerUp) {
Matter.Body.setPosition(this.caughtPowerUp, Vector.add(this.vertices[2], this.velocity))
Matter.Body.setVelocity(this.caughtPowerUp, {
x: 0,
y: 0
})
} else { //&& simulation.cycle % 2
Matter.Body.setVelocity(this.caughtPowerUp, { x: 0, y: 0 })
} else {
for (let i = 0, len = powerUp.length; i < len; ++i) {
const radius = powerUp[i].circleRadius + 50
if (Vector.magnitudeSquared(Vector.sub(this.vertices[2], powerUp[i].position)) < radius * radius) {
if (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal) {
this.caughtPowerUp = powerUp[i]
Matter.Body.setVelocity(powerUp[i], {
x: 0,
y: 0
})
Matter.Body.setVelocity(powerUp[i], { x: 0, y: 0 })
Matter.Body.setPosition(powerUp[i], this.vertices[2])
powerUp[i].collisionFilter.category = 0
powerUp[i].collisionFilter.mask = 0
this.thrustMag *= 0.6
this.endCycle += 0.5 //it pulls back slower, so this prevents it from ending early
this.retract()
break //just pull 1 power up if possible
}
}
}
}
m.grabPowerUp();
},
do() {
if (input.fire) { //&& !Matter.Query.collides(this, body).length
if (m.fieldCDcycle < m.cycle + 5) m.fieldCDcycle = m.cycle + 5
if (input.field) { //&& !Matter.Query.collides(this, body).length
this.destroyBlocks()
this.grabPowerUp()
if (this.endCycle < simulation.cycle + 1) { //if at end of lifespan, but player is holding down fire, force retraction
this.endCycle = simulation.cycle + 60
// m.fireCDcycle = m.cycle + 120 // cool down
this.do = this.returnToPlayer
Matter.Body.setDensity(this, 0.0005); //reduce density on return
if (this.angularSpeed < 0.5) this.torque += this.inertia * 0.001 * (Math.random() - 0.5) //(Math.round(Math.random()) ? 1 : -1)
this.collisionFilter.mask = cat.map | cat.mob | cat.mobBullet | cat.mobShield // | cat.body
}
// if (this.endCycle < simulation.cycle + 1) { //if at end of lifespan, but player is holding down field, force retraction
// this.endCycle = simulation.cycle + 30
// // m.fireCDcycle = m.cycle + 120 // cool down
// this.do = this.returnToPlayer
// Matter.Body.setDensity(this, 0.0005); //reduce density on return
// if (this.angularSpeed < 0.5) this.torque += this.inertia * 0.001 * (Math.random() - 0.5) //(Math.round(Math.random()) ? 1 : -1)
// this.collisionFilter.mask = cat.map | cat.mob | cat.mobBullet | cat.mobShield // | cat.body
// }
} else {
//if not enough energy
if (m.energy < 0.05) this.dropCaughtPowerUp()
// if (m.energy < 0.01) this.dropCaughtPowerUp()
// const returnForce = Vector.mult(Vector.normalise(Vector.sub(this.position, m.pos)), 3 * this.thrustMag * this.mass)
// this.force.x -= returnForce.x
// this.force.y -= returnForce.y
@@ -1671,103 +1729,90 @@ const b = {
// } else {
//return to player
this.do = this.returnToPlayer
this.endCycle = simulation.cycle + 60
Matter.Body.setDensity(this, 0.0005); //reduce density on return
if (this.angularSpeed < 0.5) this.torque += this.inertia * 0.001 * (Math.random() - 0.5) //(Math.round(Math.random()) ? 1 : -1)
this.collisionFilter.mask = cat.map | cat.mob | cat.mobBullet | cat.mobShield // | cat.body
//recoil on catching
const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (m.crouch ? 0.0001 : 0.0002))
player.force.x += momentum.x
player.force.y += momentum.y
this.retract()
// }
}
//grappling hook
if (input.fire && Matter.Query.collides(this, map).length) {
Matter.Body.setPosition(this, Vector.add(this.position, {
x: 20 * Math.cos(this.angle),
y: 20 * Math.sin(this.angle)
}))
if (input.field && Matter.Query.collides(this, map).length) {
Matter.Body.setPosition(this, Vector.add(this.position, { x: -20 * Math.cos(this.angle), y: -20 * Math.sin(this.angle) }))
if (Matter.Query.collides(this, map).length) {
Matter.Body.setVelocity(this, {
x: 0,
y: 0
});
Matter.Body.setVelocity(this, { x: 0, y: 0 });
Matter.Sleeping.set(this, true)
this.endCycle = simulation.cycle + 5
this.dropCaughtPowerUp()
// this.dropCaughtPowerUp()
this.do = () => {
if (m.fieldCDcycle < m.cycle + 5) m.fieldCDcycle = m.cycle + 5
// if (this.caughtPowerUp) {
// Matter.Body.setPosition(this.caughtPowerUp, Vector.add(this.vertices[2], this.velocity))
// Matter.Body.setVelocity(this.caughtPowerUp, { x: 0, y: 0 })
// }
this.grabPowerUp()
//between player nose and the grapple
const sub = Vector.sub(this.vertices[0], {
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
})
const sub = Vector.sub(this.vertices[0], { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) })
let dist = Vector.magnitude(sub)
if (input.fire) {
if (input.field) {
// m.fireCDcycle = m.cycle + 30; // cool down if out of energy
m.fireCDcycle = m.cycle + 5 + 40 * b.fireCDscale + 60 * (m.energy < 0.05)
// m.fireCDcycle = m.cycle + 5 + 40 * b.fireCDscale + 60 * (m.energy < 0.05)
// if (m.fieldCDcycle < m.cycle + 5) m.fieldCDcycle = m.cycle + 5
this.endCycle = simulation.cycle + 10
if (input.down) { //down
this.isSlowPull = true
dist = 0
player.force.y += 5 * player.mass * simulation.g;
player.force.y += 2.5 * player.mass * simulation.g; //adjust this to control fall rate while hooked and pressing down
} else if (input.up) {
this.isSlowPull = false
}
if (m.energy > this.drain) {
Matter.Body.setVelocity(player, {
x: player.velocity.x * 0.8,
y: player.velocity.y * 0.8
});
if (m.energy < this.drain) this.isSlowPull = true
// pulling friction that allowed a slight swinging, but has high linear pull at short dist
const drag = 1 - 30 / Math.min(Math.max(100, dist), 700) - 0.1 * (player.speed > 70)
// console.log(player.speed)
Matter.Body.setVelocity(player, { x: player.velocity.x * drag, y: player.velocity.y * drag });
const pullScale = 0.0004
const pull = Vector.mult(Vector.normalise(sub), pullScale * Math.min(Math.max(15, dist), this.isSlowPull ? 70 : 200))
//original pulling force with high friction and very linear pull
// Matter.Body.setVelocity(player, { x: player.velocity.x * 0.85, y: player.velocity.y * 0.85 });
// const pull = Vector.mult(Vector.normalise(sub), 0.0008 * Math.min(Math.max(15, dist), this.isSlowPull ? 100 : 200))
//need to scale the friction differently based on distance?
// if (dist > 500) {
const pull = Vector.mult(Vector.normalise(sub), 0.0008 * Math.min(Math.max(15, dist), 200))
player.force.x += pull.x
player.force.y += pull.y
// }
if (dist > 500) {
m.energy -= this.drain
if (m.energy < 0) {
this.endCycle = 0;
if (m.cycle + 50 < m.fireCDcycle) m.fireCDcycle = m.cycle + 50
// refund ammo
b.guns[9].ammo++;
simulation.updateGunHUD();
// for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
// if (b.guns[i].name === "harpoon") {
// break;
// if (m.energy < 0) this.endCycle = 0;
}
// if (tech.isImmuneGrapple && m.immuneCycle < m.cycle + 10) {
// m.immuneCycle = m.cycle + 10;
// if (m.energy > 0.001) {
// m.energy -= 0.001
// } else { //out of energy
// Matter.Sleeping.set(this, false)
// this.collisionFilter.category = 0
// this.collisionFilter.mask = 0
// this.do = this.returnToPlayer
// this.endCycle = simulation.cycle + 60
// // m.fireCDcycle = m.cycle + 120; //fire cooldown
// if (m.fieldCDcycle < m.cycle + 120) m.fieldCDcycle = m.cycle + 120
// //recoil on catching
// const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (m.crouch ? 0.0001 : 0.0002))
// player.force.x += momentum.x
// player.force.y += momentum.y
// }
// }
}
}
}
if (tech.isImmuneGrapple && m.immuneCycle < m.cycle + 10) {
m.immuneCycle = m.cycle + 10;
if (m.energy > 0.001) {
m.energy -= 0.001
} else { //out of energy
Matter.Sleeping.set(this, false)
this.collisionFilter.category = 0
this.collisionFilter.mask = 0
this.do = this.returnToPlayer
this.endCycle = simulation.cycle + 60
m.fireCDcycle = m.cycle + 120; //fire cooldown
//recoil on catching
const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (m.crouch ? 0.0001 : 0.0002))
player.force.x += momentum.x
player.force.y += momentum.y
}
}
} else {
Matter.Sleeping.set(this, false)
this.collisionFilter.category = 0
this.collisionFilter.mask = 0
this.do = this.returnToPlayer
this.endCycle = simulation.cycle + 60
//recoil on catching
const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (m.crouch ? 0.0001 : 0.0002))
player.force.x += momentum.x
player.force.y += momentum.y
this.retract()
// Matter.Sleeping.set(this, false)
// this.collisionFilter.category = 0
// this.collisionFilter.mask = 0
// this.do = this.returnToPlayer
// this.endCycle = simulation.cycle + 60
// //recoil on catching
// const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (m.crouch ? 0.0001 : 0.0002))
// player.force.x += momentum.x
// player.force.y += momentum.y
}
this.draw();
}
@@ -3178,6 +3223,9 @@ const b = {
y: 100 * (Math.random() - 0.5)
},
beforeDmg(who) {
if (who.isInvulnerable) {
Matter.Body.setVelocity(this, Vector.mult(this.velocity, 0.1));
} else {
if (tech.isSpawnBulletsOnDeath && who.alive && who.isDropPowerUp) {
setTimeout(() => {
if (!who.alive) {
@@ -3192,6 +3240,7 @@ const b = {
this.endCycle = 0; //bullet ends cycle after doing damage
}
if (this.isFreeze) mobs.statusSlow(who, 90)
}
},
onEnd() {
if (tech.isMutualism && this.isMutualismActive && !tech.isEnergyHealth) {
@@ -3295,8 +3344,10 @@ const b = {
y: 100 * (Math.random() - 0.5)
},
beforeDmg(who) {
if (!who.isInvulnerable) {
this.endCycle = 0; //bullet ends cycle after doing damage
if (this.isFreeze) mobs.statusSlow(who, 90)
}
},
onEnd() {
if (tech.isMutualism && this.isMutualismActive && !tech.isEnergyHealth) {
@@ -3304,7 +3355,7 @@ const b = {
if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth();
}
console.log(this.dmg)
// console.log(this.dmg)
},
do() {
if (this.lockedOn && this.lockedOn.alive) {
@@ -3425,6 +3476,7 @@ const b = {
minDmgSpeed: 0,
lockedOn: null,
beforeDmg(who) {
if (!who.isInvulnerable) {
if (tech.iceEnergy && !who.shield && !who.isShielded && who.isDropPowerUp && who.alive && m.immuneCycle < m.cycle) {
setTimeout(() => {
if (!who.alive) m.energy += tech.iceEnergy * 0.8
@@ -3432,6 +3484,7 @@ const b = {
}
mobs.statusSlow(who, tech.iceIXFreezeTime)
this.endCycle = simulation.cycle
}
// if (tech.isHeavyWater) mobs.statusDoT(who, 0.15, 300)
},
onEnd() { },
@@ -3507,8 +3560,9 @@ const b = {
},
beforeDmg(who) {
Matter.Body.setVelocity(this, Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), 10 + 10 * Math.random())); //push away from target
this.endCycle -= 130
this.cd = simulation.cycle + this.delay;
if (!who.isInvulnerable) {
this.endCycle -= 130
if (tech.isSporeFreeze) mobs.statusSlow(who, 90)
if (tech.isSpawnBulletsOnDeath && who.alive && who.isDropPowerUp) {
setTimeout(() => {
@@ -3528,6 +3582,7 @@ const b = {
setTimeout(() => {
this.dmg = 0
})
}
},
onEnd() {
if (tech.isMutualism && this.isMutualismActive && !tech.isEnergyHealth) {
@@ -3659,15 +3714,18 @@ const b = {
deathCycles: 110 + RADIUS * 5,
isImproved: false,
beforeDmg(who) {
if (who.isInvulnerable) {
//move away from target after hitting
const unit = Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), -20)
Matter.Body.setVelocity(this, { x: unit.x, y: unit.y });
this.lockedOn = null
} else {
if (tech.isIncendiary && simulation.cycle + this.deathCycles < this.endCycle && !tech.isForeverDrones) {
const max = Math.max(Math.min(this.endCycle - simulation.cycle - this.deathCycles, 1500), 0)
b.explosion(this.position, max * 0.1 + this.isImproved * 110 + 60 * Math.random()); //makes bullet do explosive damage at end
if (tech.isForeverDrones) {
this.endCycle = 0
b.drone({
x: m.pos.x + 30 * (Math.random() - 0.5),
y: m.pos.y + 30 * (Math.random() - 0.5)
}, 5)
b.drone({ x: m.pos.x + 30 * (Math.random() - 0.5), y: m.pos.y + 30 * (Math.random() - 0.5) }, 5)
bullet[bullet.length - 1].endCycle = Infinity
} else {
this.endCycle -= max
@@ -3682,6 +3740,7 @@ const b = {
if (simulation.cycle + this.deathCycles > this.endCycle) this.endCycle = simulation.cycle + this.deathCycles
}
}
}
},
onEnd() {
if (tech.isDroneRespawn) {
@@ -4193,6 +4252,7 @@ const b = {
};
}
bullet[me].beforeDmg = function (who) {
if (!who.isInvulnerable) {
if (tech.oneSuperBall) mobs.statusStun(who, 120) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds)
if (tech.isFoamBall) {
for (let i = 0, len = 5 * this.mass; i < len; i++) {
@@ -4235,6 +4295,7 @@ const b = {
}
requestAnimationFrame(cycle);
}
}
};
},
targetedBall(position, num = 1, speed = 42 + 12 * Math.random(), range = 1200, isRandomAim = true) {
@@ -5394,7 +5455,7 @@ const b = {
cd: 0,
fireCount: 0,
fireLimit: 5 + 2 * tech.isFoamBotUpgrade,
delay: Math.floor((150 + (tech.isFoamBotUpgrade ? 0 : 250)) * b.fireCDscale),// + 30 - 20 * tech.isFoamBotUpgrade,//20 + Math.floor(85 * b.fireCDscale) - 20 * tech.isFoamBotUpgrade,
delay: Math.floor((145 + (tech.isFoamBotUpgrade ? 0 : 230)) * b.fireCDscale),// + 30 - 20 * tech.isFoamBotUpgrade,//20 + Math.floor(85 * b.fireCDscale) - 20 * tech.isFoamBotUpgrade,
acceleration: 0.005 * (1 + 0.5 * Math.random()),
range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots(), //how far from the player the bot will move
endCycle: Infinity,
@@ -7717,7 +7778,7 @@ const b = {
return `spray bubbly <strong>foam</strong> that <strong>sticks</strong> to mobs<br><strong class='color-s'>slows</strong> mobs and does <strong class='color-d'>damage</strong> over time<br><strong>${this.ammoPack.toFixed(0)}</strong> bubbles per ${powerUps.orb.ammo()}`
},
ammo: 0,
ammoPack: 24,
ammoPack: 28,
have: false,
charge: 0,
isDischarge: false,
@@ -7842,9 +7903,9 @@ const b = {
if (tech.isRailGun) {
this.do = this.railDo
this.fire = this.railFire
} else if (tech.isGrapple) {
this.do = () => { }
this.fire = this.grappleFire
// } else if (tech.isGrapple) {
// this.do = () => { }
// this.fire = this.grappleFire
} else {
this.do = () => { }
this.fire = this.harpoonFire
@@ -8054,36 +8115,36 @@ const b = {
m.fireCDcycle = m.cycle + 10 //can't fire until mouse is released
this.charge += 0.00001
},
grappleFire() {
const harpoonSize = (tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1) //* (m.crouch ? 0.7 : 1)
const where = {
x: m.pos.x + harpoonSize * 40 * Math.cos(m.angle),
y: m.pos.y + harpoonSize * 40 * Math.sin(m.angle)
}
const num = Math.min(this.ammo, tech.extraHarpoons + 1)
if (!m.crouch && num > 1) { //multiple harpoons
const SPREAD = 0.06
let angle = m.angle - SPREAD * num / 2;
for (let i = 0; i < num; i++) {
if (this.ammo > 0) {
this.ammo--
b.grapple(where, angle, true, harpoonSize)
angle += SPREAD
}
}
this.ammo++ //make up for the ammo used up in fire()
simulation.updateGunHUD();
m.fireCDcycle = m.cycle + Math.floor(75 * b.fireCDscale) // cool down
// } else if (m.crouch) {
// b.harpoon(where, null, m.angle, harpoonSize, false, 70)
} else {
if (tech.crouchAmmoCount) tech.crouchAmmoCount = 1
b.grapple(where, m.angle, harpoonSize)
}
// grappleFire() {
// const harpoonSize = (tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1) //* (m.crouch ? 0.7 : 1)
// const where = {
// x: m.pos.x + harpoonSize * 40 * Math.cos(m.angle),
// y: m.pos.y + harpoonSize * 40 * Math.sin(m.angle)
// }
// const num = Math.min(this.ammo, tech.extraHarpoons + 1)
// if (!m.crouch && num > 1) { //multiple harpoons
// const SPREAD = 0.06
// let angle = m.angle - SPREAD * num / 2;
// for (let i = 0; i < num; i++) {
// if (this.ammo > 0) {
// this.ammo--
// b.grapple(where, angle, true, harpoonSize)
// angle += SPREAD
// }
// }
// this.ammo++ //make up for the ammo used up in fire()
// simulation.updateGunHUD();
// m.fireCDcycle = m.cycle + Math.floor(75 * b.fireCDscale) // cool down
m.fireCDcycle = m.cycle + 5 + 40 * b.fireCDscale + 60 * (m.energy < 0.05)
// // } else if (m.crouch) {
// // b.harpoon(where, null, m.angle, harpoonSize, false, 70)
// } else {
// if (tech.crouchAmmoCount) tech.crouchAmmoCount = 1
// b.grapple(where, m.angle, harpoonSize)
// }
// // m.fireCDcycle = m.cycle + Math.floor(75 * b.fireCDscale) // cool down
// m.fireCDcycle = m.cycle + 5 + 40 * b.fireCDscale + 60 * (m.energy < 0.05)
},
// },
harpoonFire() {
const where = {
x: m.pos.x + 30 * Math.cos(m.angle),

View File

@@ -28,17 +28,17 @@ const level = {
// m.immuneCycle = Infinity //you can't take damage
// tech.tech[297].frequency = 100
// m.couplingChange(10)
// m.setField("wormhole") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole
// m.setField("grappling hook") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook
// m.energy = 0
// simulation.molecularMode = 2
// m.damage(0.1);
// b.giveGuns("super balls") //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("foam") //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("harpoon") //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[8].ammo = 100000000
// requestAnimationFrame(() => { tech.giveTech("MACHO") });
// for (let i = 0; i < 1; ++i) tech.giveTech("electrostatic induction")
// for (let i = 0; i < 1; ++i) tech.giveTech("enthalpy")
// for (let i = 0; i < 10; ++i) tech.giveTech("quasiparticles")
// for (let i = 0; i < 1; ++i) tech.giveTech("grappling hook")
// for (let i = 0; i < 1; ++i) tech.giveTech("superdeterminism")
// for (let i = 0; i < 1; ++i) tech.giveTech("fine-structure constant")
// for (let i = 0; i < 1; ++i) tech.giveTech("nail-bot upgrade")
// requestAnimationFrame(() => { for (let i = 0; i < 30; i++) tech.giveTech("laser-bot") });
@@ -49,11 +49,11 @@ const level = {
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling");
// level.biohazard();
// level.testing();
// for (let i = 0; i < 4; ++i) spawn.hopMother(1900, -500)
// for (let i = 0; i < 0; ++i) spawn.hopper(1900, -500)
// for (let i = 0; i < 1; ++i) spawn.shooterBoss(1900, -2500)
// spawn.suckerBoss(1900, -500, 25)
// spawn.beetleBoss(1900, -500, 25)
// spawn.slasher2(2000, -1150)
// spawn.zombie(-3000, -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color)
// for (let i = 0; i < 20; ++i) spawn.starter(1000 + 1000 * Math.random(), -500 + 300 * Math.random())
@@ -239,6 +239,10 @@ const level = {
// <br><span class='color-var'>m</span>.field.description = "<span class='color-text'>${m.fieldUpgrades[m.fieldMode].description}</span>"
// `, 1200);
},
announceMobTypes() {
simulation.makeTextLog(`spawn<span class='color-symbol'>.</span>${spawn.pickList[0]}<span class='color-symbol'>(</span>x<span class='color-symbol'>,</span>y<span class='color-symbol'>)</span>`)
simulation.makeTextLog(`spawn<span class='color-symbol'>.</span>${spawn.pickList[1]}<span class='color-symbol'>(</span>x<span class='color-symbol'>,</span>y<span class='color-symbol'>)</span>`)
},
disableExit: false,
nextLevel() {
if (!level.disableExit) {
@@ -1874,6 +1878,7 @@ const level = {
//******************************************************************************************************************
//******************************************************************************************************************
template() {
// level.announceMobTypes()
simulation.enableConstructMode()
level.setPosToSpawn(0, -50); //normal spawn
level.exit.x = 1500;
@@ -2375,9 +2380,6 @@ const level = {
ctx.fillStyle = "rgba(68, 68, 68,0.95)"
ctx.fillRect(2030, 0, 150, 1800);
};
level.setPosToSpawn(460, -100); //normal spawn
// level.enter.x = -1000000; //hide enter graphic for first level by moving to the far left
level.exit.x = 2800;
@@ -3451,6 +3453,7 @@ const level = {
simulation.draw.drawMapPath = simulation.draw.drawMapSight
},
reservoir() {
level.announceMobTypes()
level.exit.x = 1700;
level.exit.y = -4510;
spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 25);
@@ -3966,6 +3969,7 @@ const level = {
powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
factory() {
level.announceMobTypes()
// simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// level.difficultyIncrease(10 * 4) //30 is near max on hard //60 is near max on why
@@ -4249,6 +4253,7 @@ const level = {
powerUps.spawn(5200, -1300, "ammo");
},
labs() {
level.announceMobTypes()
level.isProcedural = true //used in generating text for the level builder
level.defaultZoom = 1700
simulation.zoomTransition(level.defaultZoom)
@@ -5347,6 +5352,7 @@ const level = {
powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
pavilion() {
level.announceMobTypes()
level.isEndlessFall = true;
const vanish = []
level.exit.x = -850;
@@ -5499,6 +5505,7 @@ const level = {
}
},
testChamber() {
level.announceMobTypes()
level.setPosToSpawn(0, -50); //lower start
level.exit.y = level.enter.y - 550;
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
@@ -5757,6 +5764,7 @@ const level = {
},
lock() {
level.announceMobTypes()
level.setPosToSpawn(0, -65); //lower start
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.exit.y = 2010;
@@ -6006,6 +6014,7 @@ const level = {
powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
sewers() {
level.announceMobTypes()
const button1 = level.button(6600, 2675)
// const hazard = level.hazard(4550, 2750, 4550, 150)
const hazard = level.hazard(simulation.isHorizontalFlipped ? -4550 - 4550 : 4550, 2750, 4550, 150)
@@ -6196,6 +6205,7 @@ const level = {
},
satellite() {
level.announceMobTypes()
level.isEndlessFall = true;
const boost1 = level.boost(5825, 235, 1400)
const elevator = level.elevator(4210, -1265, 380, 50, -3450) //, 0.003, { up: 0.01, down: 0.2 }
@@ -6372,6 +6382,7 @@ const level = {
}
},
rooftops() {
level.announceMobTypes()
level.isEndlessFall = true;
// level.fallPosition = { x: 5000, y:-4000}
const elevator = level.elevator(1450, -990, 235, 45, -2000)
@@ -6560,6 +6571,7 @@ const level = {
}
},
aerie() {
level.announceMobTypes()
level.isEndlessFall = true;
const boost1 = level.boost(-425, 100, 1400)
const boost2 = level.boost(5350, 275, 2850);
@@ -6789,6 +6801,7 @@ const level = {
}
},
skyscrapers() {
level.announceMobTypes()
level.isEndlessFall = true;
const boost1 = level.boost(475, 0, 1300)
const boost2 = level.boost(4450, 0, 1300);
@@ -6927,6 +6940,7 @@ const level = {
}
},
highrise() {
level.announceMobTypes()
level.isEndlessFall = true;
const elevator1 = level.elevator(-790, -190, 180, 25, -1150, 0.0025, {
up: 0.01,
@@ -7212,6 +7226,7 @@ const level = {
}
},
warehouse() {
level.announceMobTypes()
level.isEndlessFall = true;
level.custom = () => {
ctx.fillStyle = "#444" //light fixtures
@@ -7531,6 +7546,7 @@ const level = {
}
},
office() {
level.announceMobTypes()
let button, door
let isReverse = false
if (Math.random() < 0.75) { //normal direction start in top left

View File

@@ -568,7 +568,7 @@ const m = {
if (tech.squirrelFx !== 1) dmg *= 0.78//Math.pow(0.78, (tech.squirrelFx - 1) / 0.4)
if (tech.isAddBlockMass && m.isHolding) dmg *= 0.1
if (tech.isSpeedHarm && player.speed > 0.1) dmg *= 1 - Math.min(player.speed * 0.0165, 0.66)
if (tech.isHarmReduce && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.25
if (tech.isHarmReduce && input.field) dmg *= 0.25
if (tech.isNeutronium && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.1
if (tech.isBotArmor) dmg *= 0.94 ** b.totalBots()
if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.33;
@@ -2779,14 +2779,10 @@ const m = {
effect: () => {
m.fieldMeterColor = "#48f" //"#0c5"
m.eyeFillColor = m.fieldMeterColor
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) {
@@ -2794,10 +2790,7 @@ 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();
@@ -2816,11 +2809,7 @@ const m = {
}
}
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++) {
if (mob[j].id === mob[i].shieldID) mob[j].damage(tech.blockDmg * m.dmgScale * (tech.isBlockRadiation ? 6 : 2), true)
@@ -3684,6 +3673,94 @@ const m = {
ctx.strokeStyle = "rgba(255,0,110,0.06)"
ctx.stroke();
}
// } else if (true) { //plasma sword slash
// const plasmaSweepCycles = 30
// m.plasmaSweep = 0
// m.plasmaSlashDirection = m.flipLegs//Math.random() > 0.5 ? 1 : -1;
// m.hold = function () {
// if (m.isHolding) {
// m.drawHold(m.holdingTarget);
// m.holding();
// m.throwBlock();
// m.plasmaSweep = 0
// // } else if (true) { //not hold but field button is pressed
// } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
// if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen
// m.grabPowerUp();
// m.lookForPickUp();
// //graphics
// if (m.plasmaSweep === 0) m.plasmaSlashDirection = m.flipLegs //Math.random() > 0.5 ? 1 : -1;
// const angle = m.angle //+ 1 * (m.plasmaSweep - plasmaSweepCycles / 2) / plasmaSweepCycles * m.plasmaSlashDirection
// const plasmaSweepCapped = Math.min(m.plasmaSweep, plasmaSweepCycles - 8) / plasmaSweepCycles
// const range = 100 * plasmaSweepCapped
// const arc = 1.3
// const A = { x: m.pos.x + range * Math.cos(angle - arc), y: m.pos.y + range * Math.sin(angle - arc) }
// const B = { x: m.pos.x + range * Math.cos(angle + arc), y: m.pos.y + range * Math.sin(angle + arc) }
// const controlRange = 500 * plasmaSweepCapped
// const AC = { x: m.pos.x + controlRange * Math.cos(angle - arc / 2), y: m.pos.y + controlRange * Math.sin(angle - arc / 2) }
// const BC = { x: m.pos.x + controlRange * Math.cos(angle + arc / 2), y: m.pos.y + controlRange * Math.sin(angle + arc / 2) }
// const innerControlRange = 300 * plasmaSweepCapped
// const ACinner = { x: m.pos.x + innerControlRange * Math.cos(angle - arc / 2), y: m.pos.y + innerControlRange * Math.sin(angle - arc / 2) }
// const BCinner = { x: m.pos.x + innerControlRange * Math.cos(angle + arc / 2), y: m.pos.y + innerControlRange * Math.sin(angle + arc / 2) }
// ctx.beginPath();
// ctx.moveTo(A.x, A.y)
// ctx.bezierCurveTo(AC.x, AC.y, BC.x, BC.y, B.x, B.y); //outer curve
// ctx.bezierCurveTo(BCinner.x, BCinner.y, ACinner.x, ACinner.y, A.x, A.y); //inner curve
// // ctx.strokeStyle = "#000"
// // ctx.stroke();
// ctx.fillStyle = "rgba(255,0,255,0.5)"
// ctx.fill();
// //draw control points for graphics reference
// ctx.lineWidth = '0.5'
// ctx.beginPath();
// ctx.arc(A.x, A.y, 5, 0, 2 * Math.PI);
// ctx.stroke();
// ctx.beginPath();
// ctx.arc(B.x, B.y, 5, 0, 2 * Math.PI);
// ctx.stroke();
// ctx.beginPath();
// ctx.arc(AC.x, AC.y, 5, 0, 2 * Math.PI);
// ctx.stroke();
// ctx.beginPath();
// ctx.arc(BC.x, BC.y, 5, 0, 2 * Math.PI);
// ctx.stroke();
// ctx.beginPath();
// ctx.arc(ACinner.x, ACinner.y, 5, 0, 2 * Math.PI);
// ctx.stroke();
// ctx.beginPath();
// ctx.arc(BCinner.x, BCinner.y, 5, 0, 2 * Math.PI);
// ctx.stroke();
// //mob collision detection
// collideRange = 160
// const collideCenter = {
// x: m.pos.x + collideRange * Math.cos(angle),
// y: m.pos.y + collideRange * Math.sin(angle)
// }
// ctx.beginPath();
// ctx.arc(collideCenter.x, collideCenter.y, 140, 0, 2 * Math.PI);
// ctx.stroke();
// //push mob away and slow them?
// //sweeping motion and cooldown
// m.plasmaSweep++
// if (m.plasmaSweep > plasmaSweepCycles) {
// m.plasmaSweep = 0
// if (m.fireCDcycle < m.cycle + 30) m.fieldCDcycle = m.cycle + 30
// }
// } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
// m.pickUp();
// m.plasmaSweep = 0
// } else {
// m.plasmaSweep = 0
// m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
// }
// m.drawRegenEnergy("rgba(0, 0, 0, 0.2)")
// }
} else {
m.hold = function () {
if (m.isHolding) {
@@ -4864,6 +4941,31 @@ const m = {
// m.drawRegenEnergy()
// },
},
{
name: "grappling hook",
// description: `use <strong class='color-f'>energy</strong> to pull yourself towards the <strong>map</strong><br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second`,
description: `use <strong class='color-f'>energy</strong> to fire a hook that attaches to <strong>map</strong>,<br>pulls player, <strong class='color-d'>damages</strong> mobs, and destroys <strong class='color-block'>blocks</strong><br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second`,
effect: () => {
m.fieldFire = true;
// m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping
m.fieldMeterColor = "#333"
m.eyeFillColor = m.fieldMeterColor
m.fieldHarmReduction = 0.45; //55% reduction
m.hold = function () {
if (input.field) {
if (m.fieldCDcycle < m.cycle) {
if (m.energy > 0.02) m.energy -= 0.02
const where = { x: m.pos.x + 40 * Math.cos(m.angle), y: m.pos.y + 40 * Math.sin(m.angle) }
b.grapple(where, m.angle)
if (m.fieldCDcycle < m.cycle + 20) m.fieldCDcycle = m.cycle + 20
}
m.grabPowerUp();
}
m.drawRegenEnergy()
}
}
},
],
//************************************************************************************
//************************************************************************************

View File

@@ -914,6 +914,8 @@ const powerUps = {
for (let i = 0; i < b.guns.length; i++) {
if (!b.guns[i].have) options.push(i);
}
// console.log(options.length)
if (options.length > 0 || !tech.isSuperDeterminism) {
let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + 2 * (m.fieldMode === 8)))
if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay
function removeOption(index) {
@@ -962,6 +964,7 @@ const powerUps = {
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();
}
// }
}
},

View File

@@ -232,7 +232,7 @@ const tech = {
// }
// }
if (tech.isDivisor && b.activeGun && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.77
if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.78 : 1.88
if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.75 : 2
if (tech.isDilate) dmg *= 1.5 + 0.6 * Math.sin(m.cycle * 0.0075)
if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.31 * b.inventory.length
if (powerUps.boost.endCycle > m.cycle) dmg *= 1 + powerUps.boost.damage
@@ -955,9 +955,9 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
return !m.isShipMode && !tech.isAlwaysFire, !tech.isGrapple
return !m.isShipMode && !tech.isAlwaysFire
},
requires: "not ship mode, automatic, grappling hook",
requires: "not ship mode, automatic",
effect() {
tech.isFireMoveLock = true;
b.setFireCD();
@@ -6682,10 +6682,10 @@ const tech = {
},
requires: "foam",
effect() {
tech.foamDamage += 0.011 * 0.43
tech.foamDamage += 0.01 * 0.43
},
remove() {
tech.foamDamage = 0.011;
tech.foamDamage = 0.01;
}
},
{
@@ -6831,9 +6831,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.isHarpoonPowerUp && !tech.isGrapple && !tech.isBoostReplaceAmmo
return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.isHarpoonPowerUp && !tech.isBoostReplaceAmmo
},
requires: "harpoon, not UHMWPE, induction furnace, grappling hook, quasiparticles",
requires: "harpoon, not UHMWPE, induction furnace, quasiparticles",
ammoBonus: 9,
effect() {
tech.isRailGun = true;
@@ -6852,52 +6852,52 @@ const tech = {
}
}
},
{
name: "grappling hook",
description: `<strong>harpoons</strong> attach to the <strong>map</strong> and pull you<br>your <strong>rope</strong> extends while holding <strong>fire</strong>`,
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.isHarpoonPowerUp && !tech.isRailGun && !tech.isFireMoveLock
},
requires: "harpoon, not railgun, UHMWPE, induction furnace, Higgs mechanism",
effect() {
tech.isGrapple = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "harpoon") b.guns[i].chooseFireMethod()
}
},
remove() {
if (tech.isGrapple) {
tech.isGrapple = false;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "harpoon") b.guns[i].chooseFireMethod()
}
}
}
},
{
name: "bulk modulus",
description: `while <strong>grappling</strong> become <strong>invulnerable</strong><br>drain <strong class='color-f'>energy</strong>`,
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("harpoon") && tech.isGrapple && !tech.isRailEnergy
},
requires: "grappling hook, not alternator",
effect() {
tech.isImmuneGrapple = true;
},
remove() {
tech.isImmuneGrapple = false
}
},
// {
// name: "grappling hook",
// description: `<strong>harpoons</strong> attach to the <strong>map</strong> and pull you<br>your <strong>rope</strong> extends while holding <strong>fire</strong>`,
// isGunTech: true,
// maxCount: 1,
// count: 0,
// frequency: 2,
// frequencyDefault: 2,
// allowed() {
// return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.isHarpoonPowerUp && !tech.isRailGun && !tech.isFireMoveLock
// },
// requires: "harpoon, not railgun, UHMWPE, induction furnace, Higgs mechanism",
// effect() {
// tech.isGrapple = true;
// for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
// if (b.guns[i].name === "harpoon") b.guns[i].chooseFireMethod()
// }
// },
// remove() {
// if (tech.isGrapple) {
// tech.isGrapple = false;
// for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
// if (b.guns[i].name === "harpoon") b.guns[i].chooseFireMethod()
// }
// }
// }
// },
// {
// name: "bulk modulus",
// description: `while <strong>grappling</strong> become <strong>invulnerable</strong><br>drain <strong class='color-f'>energy</strong>`,
// isGunTech: true,
// maxCount: 1,
// count: 0,
// frequency: 2,
// frequencyDefault: 2,
// allowed() {
// return tech.haveGunCheck("harpoon") && !tech.isRailEnergy
// },
// requires: "not alternator",
// effect() {
// tech.isImmuneGrapple = true;
// },
// remove() {
// tech.isImmuneGrapple = false
// }
// },
{
name: "alternator",
description: "<strong>+90%</strong> <strong>harpoon</strong> <strong class='color-f'>energy</strong> efficiency",
@@ -6907,9 +6907,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("harpoon") && !tech.isImmuneGrapple
return tech.haveGunCheck("harpoon")
},
requires: "harpoon, not bulk modulus",
requires: "harpoon",
effect() {
tech.isRailEnergy = true;
},
@@ -6994,9 +6994,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("harpoon") && !tech.isRailGun && !tech.isGrapple
return tech.haveGunCheck("harpoon") && !tech.isRailGun
},
requires: "harpoon, not grappling hook, railgun",
requires: "harpoon, not railgun",
effect() {
tech.isFilament = true;
},
@@ -7013,9 +7013,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("harpoon") && !tech.isRailGun && !tech.isGrapple
return tech.haveGunCheck("harpoon") && !tech.isRailGun
},
requires: "harpoon, not grappling hook, railgun",
requires: "harpoon, not railgun",
effect() {
tech.isHarpoonPowerUp = true
},
@@ -7657,9 +7657,9 @@ const tech = {
frequency: 3,
frequencyDefault: 3,
allowed() {
return (m.fieldMode === 8 || m.fieldMode === 2 || m.fieldMode === 3) && (build.isExperimentSelection || powerUps.research.count > 3)
return (m.fieldMode === 8 || m.fieldMode === 2 || m.fieldMode === 3 || m.fieldMode === 10) && (build.isExperimentSelection || powerUps.research.count > 3)
},
requires: "perfect diamagnetism, negative mass, pilot wave",
requires: "perfect diamagnetism, negative mass, grappling hook, pilot wave",
effect() {
tech.isFieldHarmReduction = true
for (let i = 0; i < 2; i++) {
@@ -7706,9 +7706,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return (m.fieldMode === 8 || m.fieldMode === 3) && !tech.isCloakHealLastHit
return m.fieldMode === 8 || m.fieldMode === 3
},
requires: "negative mass, pilot wave, not patch",
requires: "negative mass, pilot wave",
effect() {
tech.lastHitDamage += 4;
},
@@ -7746,16 +7746,16 @@ const tech = {
},
{
name: "aerostat",
description: `<strong>+88%</strong> <strong class='color-d'>damage</strong> while <strong>off</strong> the <strong>ground</strong><br><strong>-22%</strong> <strong class='color-d'>damage</strong> while <strong>on</strong> the <strong>ground</strong>`,
description: `<strong>+100%</strong> <strong class='color-d'>damage</strong> while <strong>off</strong> the <strong>ground</strong><br><strong>-25%</strong> <strong class='color-d'>damage</strong> while <strong>on</strong> the <strong>ground</strong>`,
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldMode === 3
return m.fieldMode === 3 || m.fieldMode === 10
},
requires: "negative mass",
requires: "negative mass, grappling hook",
effect() {
tech.isNoGroundDamage = true
},
@@ -7831,9 +7831,9 @@ const tech = {
isBotTech: true,
isNonRefundable: true,
allowed() {
return powerUps.research.count > 1 && (m.fieldMode === 4 || m.fieldMode === 8)
return powerUps.research.count > 1 && (m.fieldMode === 4 || m.fieldMode === 10 || m.fieldMode === 8)
},
requires: "molecular assembler, pilot wave",
requires: "molecular assembler, grappling hook, pilot wave",
effect() {
for (let i = 0; i < 2; i++) {
if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
@@ -7856,9 +7856,9 @@ const tech = {
isBotTech: true,
isNonRefundable: true,
allowed() {
return powerUps.research.count > 2 && (m.fieldMode === 4 || m.fieldMode === 8)
return powerUps.research.count > 2 && (m.fieldMode === 4 || m.fieldMode === 10 || m.fieldMode === 8)
},
requires: "molecular assembler, pilot wave",
requires: "molecular assembler, grappling hook, pilot wave",
effect() {
for (let i = 0; i < 3; i++) {
if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
@@ -8121,9 +8121,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return (m.fieldMode === 5 || m.fieldMode === 4 || m.fieldMode === 2 || m.fieldMode === 8)
return (m.fieldMode === 10 || m.fieldMode === 4 || m.fieldMode === 8)
},
requires: "molecular assembler, plasma torch, perfect diamagnetism, pilot wave",
requires: "plasma torch, grappling hook, pilot wave",
effect() {
tech.isHarmReduce = true
},
@@ -8479,9 +8479,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldMode === 7 && !tech.lastHitDamage && !tech.isEnergyHealth
return m.fieldMode === 7 && !tech.isEnergyHealth
},
requires: "metamaterial cloaking, not dynamic equilibrium, mass-energy",
requires: "metamaterial cloaking, not mass-energy",
effect() {
tech.isCloakHealLastHit = true;
},
@@ -8586,9 +8586,9 @@ const tech = {
frequency: 3,
frequencyDefault: 3,
allowed() {
return (m.fieldMode === 8 || m.fieldMode === 3 || m.fieldMode === 6 || m.fieldMode === 9) && (build.isExperimentSelection || powerUps.research.count > 2)
return (m.fieldMode === 8 || m.fieldMode === 6 || m.fieldMode === 9 || m.fieldMode === 10) && (build.isExperimentSelection || powerUps.research.count > 2)
},
requires: "wormhole, time dilation, negative mass, pilot wave",
requires: "wormhole, time dilation, negative mass, pilot wave, grappling hook",
effect() {
tech.fieldDuplicate = 0.11
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
@@ -10982,6 +10982,30 @@ const tech = {
},
remove() { }
},
{
name: "mobs!",
descriptionFunction() {
if (this.mobType === "") this.mobType = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]
return `spawn 20 <strong>${this.mobType}</strong> mobs`
},
maxCount: 1,
count: 0,
frequency: 0,
isNonRefundable: true,
isJunk: true,
allowed() { return true },
requires: "",
mobType: "",
effect() {
if (this.mobType === "") this.mobType = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]
for (let i = 0; i < 20; i++) {
spawn[this.mobType](m.pos.x, m.pos.y - 700)
}
simulation.makeTextLog(`spawn<span class='color-symbol'>.</span>${this.mobType}<span class='color-symbol'>(</span>x<span class='color-symbol'>,</span>y<span class='color-symbol'>)</span>`)
},
remove() { }
},
{
name: "black hole cluster",
description: `spawn <strong>30</strong> nearby <strong>black holes</strong>`,
@@ -11718,8 +11742,8 @@ const tech = {
isTimeCrystals: null,
isGroundState: null,
isRailGun: null,
isGrapple: null,
isImmuneGrapple: null,
// isGrapple: null,
// isImmuneGrapple: null,
isDronesTravel: null,
isTechDebt: null,
isPlasmaBall: null,

View File

@@ -1,44 +0,0 @@
// https://ncase.me/sight-and-light/
// redblobgames.com/articles/visibility
// https://github.com/Silverwolf90/2d-visibility/tree/master/src
// could apply to explosions, neutron bomb, player LOS
const v = {
points: [],
populate() {
v.points = [{
x: -150,
y: -950
}, {
x: 710,
y: -950
}, {
x: 710,
y: -940
}, {
x: 710,
y: -710
}, {
x: 710,
y: -700
}, {
x: -150,
y: -700
}]
},
draw() {
ctx.beginPath();
ctx.moveTo(v.points[0].x, v.points[0].y)
for (let i = 0, len = v.points.length; i < len; i++) {
ctx.lineTo(v.points[i].x, v.points[i].y)
}
// ctx.fillStyle = "#333"
ctx.globalCompositeOperation = "destination-in";
ctx.fill();
ctx.globalCompositeOperation = "source-over";
ctx.clip();
}
}
v.populate();
// console.log(v.points)

View File

@@ -1,20 +1,58 @@
******************************************************** NEXT PATCH **************************************************
new community map - LaunchSite by Des Boot
grappling hook is now a field (work in progress)
reworked physics to allow faster speeds, but more control
improved rate of power up grabbing
more player control to hook retraction rate
changed hook shape and field image graphics
grappling hook field coupling, more tech, bug fixes, and general polish to be added soon
added a short color animation after grabbing basic power ups
aerostat - 88->100% damage in air 22-> 25% damage on ground
foam damage reduced 10%, ammo increased about 10%
after hitting an invulnerable mob (drones,spores,worms,iceIX,fleas) don't die or lose cycles
added JUNK tech: mobs! - summon 20 random mobs
added announcement of mob names in console at start of new level
reduced overall damage done to player by ~6%
commodities exchange spawns 5-10 -> 6-12 power ups on cancel
residual dipolar coupling spawns 5 -> 6 coupling power ups
bots maintain relative position to player after the no camera tracking teleport
for portals and falling off level
the once every 7 seconds stuck check now also check to see if you stay stuck for 3 seconds before resetting you.
bug fixes
*********************************************************** TODO *****************************************************
grappling hook is a field
check for places that the player could get into but not out of
maybe grapple could grab more then 1 power up?
grapple slices blocks
cut large blocks into 2,3
use dead mob code for mobs > 5 sides
write code to cut large blocks in half and remove one half
need several field tech
new field tech ideas
increase hook damage
hook damage aura
hook's line does damage
make several auto targeting harpoons after taking damage
how to make them not drain energy
generate ___ after destroying blocks
energy, drones, iceIX, explosion, nails, junk bots?
coupling effect: defense?, bonus from ammo power ups, fire rate
tech - killing a mob heals for the last damage you took
disable cloaking heal? maybe you don't need to disable, just don't heal twice
heal for 50%?
heal from mob damage or from kills?
make phonon the default wave gun type and make a tech to switch to the normal wave beam
nerf phonon, buff wave
sword slash for plasma torch (giving up on this for now, had trouble making graphics look good)
activates when mouse is close to player
gradual activation
sharp cut off
use length of torch as cut off length
make it look like hollow knight slash
what about upgrades to extruder,plasma ball
give them their own version of a slash?
make a tech that buffs the slash, but it disables extruder,plasma ball
more (all) bosses need to be made of parts
good examples: spiderBoss, dragonFlyBoss, beetleBoss
methods: