grappling hook 2nd update

grappling hook
  added coupling effect - 4% extra ammo per coupling
  doesn't destroy blocks, instead the player grabs blocks
  doesn't automatically retract after hitting power ups
  improved momentum conservation on yank and catching blocks, power ups
  removed accidental 55% defense for grapple field
  tech  (no images yet)
    autonomous defense - fire harpoons at nearby mobs
    rupture - explosion on impact with map, block, mob

negative mass field has horizontal block motion by default
fixed tech sorting by "allowed tech" in experiment mode
This commit is contained in:
landgreen
2023-11-25 15:26:09 -08:00
parent e9d226259e
commit ce74f420e3
8 changed files with 345 additions and 167 deletions

View File

@@ -1484,54 +1484,17 @@ const b = {
index: 3, index: 3,
isInternal: false isInternal: false
}, { }, {
x: 34, x: 37,
y: 5, y: 3,
index: 4, index: 4,
isInternal: false 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, angle: angle,
friction: 1, friction: 1,
frictionAir: 0.4, frictionAir: 0.4,
thrustMag: 0.13, thrustMag: 0.13,
dmg: 6, //damage done in addition to the damage from momentum dmg: 8, //damage done in addition to the damage from momentum
classType: "bullet", classType: "bullet",
endCycle: simulation.cycle + 70, endCycle: simulation.cycle + 70,
isSlowPull: false, isSlowPull: false,
@@ -1543,6 +1506,70 @@ const b = {
// lookFrequency: Math.floor(7 + Math.random() * 3), // 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 density: 0.004, //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed
drain: 0.001, drain: 0.001,
draw() {
const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
const sub = Vector.sub(where, this.vertices[0])
const controlPoint = Vector.add(where, Vector.mult(sub, -0.5))
//draw rope
ctx.beginPath();
ctx.moveTo(where.x, where.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);
// if (tech.isHookWire) {
// //draw wire
// const hitMob = Matter.Query.ray(mob, this.position, m.pos, 10)
// if (hitMob.length && m.immuneCycle < m.cycle) {
// for (let i = 0; i < hitMob.length; i++) {
// console.log(hitMob[i].bodyA)
// // simulation.drawList.push({ //add dmg to draw queue
// // x: path[path.length - 1].x,
// // y: path[path.length - 1].y,
// // radius: Math.sqrt(2000 * damage * best.who.damageReduction) + 2,
// // color: tech.laserColorAlpha,
// // time: simulation.drawTime
// // });
// hitMob[i].bodyA.damage(0.001)
// }
// }
// //draw glow around wire
// ctx.strokeStyle = "rgba(0,255,255,0.2)" // "#0ce"
// ctx.lineWidth = 20
// ctx.stroke();
// }
ctx.strokeStyle = "rgba(0,255,255,0.2)" // "#0ce"
ctx.lineWidth = 10
ctx.stroke();
ctx.strokeStyle = "#000" // "#0ce"
ctx.lineWidth = 0.5
ctx.stroke();
//draw harpoon spikes
// ctx.beginPath();
// ctx.lineTo(this.vertices[3].x, this.vertices[3].y);
// // const spike1 = Vector.add(this.vertices[1], Vector.mult(Vector.sub(this.vertices[1], this.vertices[2]), 3))
// // ctx.lineTo(spike1.x, spike1.y);
// const controlPoint2 = Vector.add(this.vertices[3], Vector.mult(Vector.sub(this.vertices[3], this.vertices[2]), 20))
// ctx.quadraticCurveTo(controlPoint2.x, controlPoint2.y, this.vertices[2].x, this.vertices[2].y)
// ctx.fillStyle = '#000'
// ctx.fill();
ctx.beginPath();
ctx.lineTo(this.vertices[0].x, this.vertices[0].y);
const spikeLength = 2
// const spike1 = Vector.add(this.vertices[1], Vector.mult(Vector.sub(this.vertices[1], this.vertices[2]), spikeLength))
// ctx.moveTo(this.vertices[2].x, this.vertices[2].y);
// ctx.lineTo(spike1.x, spike1.y);
// ctx.lineTo(this.vertices[3].x, this.vertices[3].y);
const spike2 = Vector.add(this.vertices[3], Vector.mult(Vector.sub(this.vertices[3], this.vertices[2]), spikeLength))
ctx.moveTo(this.vertices[2].x, this.vertices[2].y);
ctx.lineTo(spike2.x, spike2.y);
ctx.lineTo(this.vertices[1].x, this.vertices[1].y);
ctx.fillStyle = '#000'
ctx.fill();
},
beforeDmg(who) { beforeDmg(who) {
if (tech.isShieldPierce && who.isShielded) { //disable shields if (tech.isShieldPierce && who.isShielded) { //disable shields
who.isShielded = false who.isShielded = false
@@ -1565,7 +1592,9 @@ const b = {
// // this.endCycle = 0; // // this.endCycle = 0;
// } // }
if (m.fieldCDcycle < m.cycle + 40) m.fieldCDcycle = m.cycle + 40 //extra long cooldown on hitting mobs if (m.fieldCDcycle < m.cycle + 40) m.fieldCDcycle = m.cycle + 40 //extra long cooldown on hitting mobs
if (tech.isHookExplosion) b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end
this.retract() this.retract()
}, },
caughtPowerUp: null, caughtPowerUp: null,
dropCaughtPowerUp() { dropCaughtPowerUp() {
@@ -1594,35 +1623,6 @@ const b = {
this.dropCaughtPowerUp() this.dropCaughtPowerUp()
} }
}, },
draw() {
const where = {
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
}
const sub = Vector.sub(where, this.vertices[0])
const controlPoint = Vector.add(where, Vector.mult(sub, -0.5))
ctx.strokeStyle = "#000" // "#0ce"
ctx.lineWidth = 0.5
ctx.beginPath();
ctx.moveTo(where.x, where.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.stroke();
//draw harpoon spikes
const spikeLength = 2
ctx.beginPath();
const spike1 = Vector.add(this.vertices[1], Vector.mult(Vector.sub(this.vertices[1], this.vertices[2]), spikeLength))
ctx.moveTo(this.vertices[2].x, this.vertices[2].y);
ctx.lineTo(spike1.x, spike1.y);
ctx.lineTo(this.vertices[3].x, this.vertices[3].y);
const spike2 = Vector.add(this.vertices[3], Vector.mult(Vector.sub(this.vertices[3], this.vertices[2]), spikeLength))
ctx.moveTo(this.vertices[2].x, this.vertices[2].y);
ctx.lineTo(spike2.x, spike2.y);
ctx.lineTo(this.vertices[1].x, this.vertices[1].y);
ctx.fillStyle = '#000'
ctx.fill();
},
retract() { retract() {
this.do = this.returnToPlayer this.do = this.returnToPlayer
this.endCycle = simulation.cycle + 60 this.endCycle = simulation.cycle + 60
@@ -1630,7 +1630,8 @@ const b = {
if (this.angularSpeed < 0.5) this.torque += this.inertia * 0.001 * (Math.random() - 0.5) //(Math.round(Math.random()) ? 1 : -1) 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 this.collisionFilter.mask = 0//cat.map | cat.mob | cat.mobBullet | cat.mobShield // | cat.body
//recoil on pulling grapple back //recoil on pulling grapple back
const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (m.crouch ? 0.0001 : 0.0002)) const mag = this.pickUpTarget ? Math.max(this.pickUpTarget.mass, 0.5) : 0.5
const momentum = Vector.mult(Vector.sub(this.position, m.pos), mag * (m.crouch ? 0.0001 : 0.0002))
player.force.x += momentum.x player.force.x += momentum.x
player.force.y += momentum.y player.force.y += momentum.y
}, },
@@ -1642,7 +1643,20 @@ const b = {
const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (m.crouch ? 0.0001 : 0.0002)) const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (m.crouch ? 0.0001 : 0.0002))
player.force.x += momentum.x player.force.x += momentum.x
player.force.y += momentum.y player.force.y += momentum.y
if (this.pickUpTarget) {
m.holdingTarget = this.pickUpTarget
// give block to player after it returns
m.isHolding = true;
//conserve momentum when player mass changes
totalMomentum = Vector.add(Vector.mult(player.velocity, player.mass), Vector.mult(Vector.normalise(this.velocity), 15 * Math.min(20, this.pickUpTarget.mass)))
Matter.Body.setVelocity(player, Vector.mult(totalMomentum, 1 / (m.defaultMass + this.pickUpTarget.mass)));
m.definePlayerMass(m.defaultMass + this.pickUpTarget.mass * m.holdingMassScale)
//make block collide with nothing
m.holdingTarget.collisionFilter.category = 0;
m.holdingTarget.collisionFilter.mask = 0;
this.pickUpTarget = null
}
} else { } else {
if (m.energy > this.drain) m.energy -= this.drain if (m.energy > this.drain) m.energy -= this.drain
const sub = Vector.sub(this.position, m.pos) const sub = Vector.sub(this.position, m.pos)
@@ -1651,10 +1665,11 @@ const b = {
this.force.x -= returnForce.x this.force.x -= returnForce.x
this.force.y -= returnForce.y this.force.y -= returnForce.y
this.grabPowerUp() this.grabPowerUp()
this.grabBlocks()
} }
this.draw(); this.draw();
}, },
destroyBlocks() { destroyBlocks() {//not used?
const blocks = Matter.Query.collides(this, body) const blocks = Matter.Query.collides(this, body)
if (blocks.length && !blocks[0].bodyA.isNotHoldable) { if (blocks.length && !blocks[0].bodyA.isNotHoldable) {
if (blocks[0].bodyA.mass > 2.5) this.retract() if (blocks[0].bodyA.mass > 2.5) this.retract()
@@ -1679,6 +1694,32 @@ const b = {
}) })
} }
}, },
pickUpTarget: null,
grabBlocks() {
if (this.pickUpTarget) {
//position block on hook
Matter.Body.setPosition(this.pickUpTarget, Vector.add(this.vertices[2], this.velocity))
Matter.Body.setVelocity(this.pickUpTarget, { x: 0, y: 0 })
} else if (!input.down) {
const blocks = Matter.Query.collides(this, body)
if (blocks.length) {
// console.log(blocks)
for (let i = 0; i < blocks.length; i++) {
if (blocks[i].bodyA.classType === "body" && !blocks[i].bodyA.isNotHoldable && !blocks[0].bodyA.mass < 60) {
this.retract()
this.pickUpTarget = blocks[i].bodyA
if (tech.isHookExplosion) b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end
} else if (blocks[i].bodyB.classType === "body" && !blocks[i].bodyB.isNotHoldable && !blocks[0].bodyB.mass < 60) {
this.retract()
this.pickUpTarget = blocks[i].bodyB
if (tech.isHookExplosion) b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end
}
}
// if (blocks[0].bodyA.mass > 2.5 && blocks[0].bodyA.mass > 15) {
}
}
},
grabPowerUp() { //grab power ups near the tip of the harpoon grabPowerUp() { //grab power ups near the tip of the harpoon
if (this.caughtPowerUp) { if (this.caughtPowerUp) {
Matter.Body.setPosition(this.caughtPowerUp, Vector.add(this.vertices[2], this.velocity)) Matter.Body.setPosition(this.caughtPowerUp, Vector.add(this.vertices[2], this.velocity))
@@ -1695,7 +1736,7 @@ const b = {
powerUp[i].collisionFilter.mask = 0 powerUp[i].collisionFilter.mask = 0
this.thrustMag *= 0.6 this.thrustMag *= 0.6
this.endCycle += 0.5 //it pulls back slower, so this prevents it from ending early this.endCycle += 0.5 //it pulls back slower, so this prevents it from ending early
this.retract() // this.retract()
break //just pull 1 power up if possible break //just pull 1 power up if possible
} }
} }
@@ -1706,7 +1747,8 @@ const b = {
do() { do() {
if (m.fieldCDcycle < m.cycle + 5) m.fieldCDcycle = m.cycle + 5 if (m.fieldCDcycle < m.cycle + 5) m.fieldCDcycle = m.cycle + 5
if (input.field) { //&& !Matter.Query.collides(this, body).length if (input.field) { //&& !Matter.Query.collides(this, body).length
this.destroyBlocks() // this.destroyBlocks()
this.grabBlocks()
this.grabPowerUp() this.grabPowerUp()
// if (this.endCycle < simulation.cycle + 1) { //if at end of lifespan, but player is holding down field, force retraction // if (this.endCycle < simulation.cycle + 1) { //if at end of lifespan, but player is holding down field, force retraction
// this.endCycle = simulation.cycle + 30 // this.endCycle = simulation.cycle + 30
@@ -1736,6 +1778,7 @@ const b = {
if (input.field && Matter.Query.collides(this, map).length) { 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) })) 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) { if (Matter.Query.collides(this, map).length) {
if (tech.isHookExplosion) b.explosion(this.position, 150 + 50 * Math.random()); //makes bullet do explosive damage at end
Matter.Body.setVelocity(this, { x: 0, y: 0 }); Matter.Body.setVelocity(this, { x: 0, y: 0 });
Matter.Sleeping.set(this, true) Matter.Sleeping.set(this, true)
this.endCycle = simulation.cycle + 5 this.endCycle = simulation.cycle + 5

View File

@@ -204,6 +204,24 @@ function collisionChecks(event) {
// time: 25 // time: 25
// }); // });
} }
// if (true) { //fire harpoons at mobs after getting hit
// const countMax = 12
// let count = countMax
// const range = 300
// for (let i = 0; i < mob.length; i++) {
// if (count > 0 && Vector.magnitude(Vector.sub(m.pos, mob[i].position)) < range) {
// count--
// if (m.fieldCDcycle < m.cycle + 30) m.fieldCDcycle = m.cycle + 30
// const angle = Math.atan2(mob[i].position.y - player.position.y, mob[i].position.x - player.position.x);
// b.harpoon(m.pos, mob[i], angle, 0.75, true, 20) // harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) {
// for (; count > 0; count--) {
// b.harpoon(m.pos, mob[i], count * Math.PI / countMax, 0.75, true, 9) // harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) {
// bullet[bullet.length - 1].drain = 0
// }
// break
// }
// }
// }
if (tech.isStimulatedEmission) powerUps.ejectTech() if (tech.isStimulatedEmission) powerUps.ejectTech()
if (mob[k].onHit) mob[k].onHit(); if (mob[k].onHit) mob[k].onHit();
if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles

View File

@@ -524,12 +524,10 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
if (!aHasKeyword && bHasKeyword) return 1; if (!aHasKeyword && bHasKeyword) return 1;
return 0; return 0;
} }
if (find === 'guntech') { if (find === 'guntech') {
tech.tech.sort((a, b) => { tech.tech.sort((a, b) => {
if (a.isGunTech && b.isGunTech) { if (a.isGunTech && b.isGunTech) {
if (a.allowed() > b.allowed()) return -1; //sort to the top return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1;
if (!a.allowed() < b.allowed()) return 1; //sort to the bottom
} }
if (a.isGunTech && !b.isGunTech) return -1; //sort to the top if (a.isGunTech && !b.isGunTech) return -1; //sort to the top
if (!a.isGunTech && b.isGunTech) return 1; //sort to the bottom if (!a.isGunTech && b.isGunTech) return 1; //sort to the bottom
@@ -538,30 +536,30 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
} else if (find === 'fieldtech') { } else if (find === 'fieldtech') {
tech.tech.sort((a, b) => { tech.tech.sort((a, b) => {
if (a.isFieldTech && b.isFieldTech) { if (a.isFieldTech && b.isFieldTech) {
if (a.allowed() > b.allowed()) return -1; //sort to the top return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1;
if (!a.allowed() < b.allowed()) return 1; //sort to the bottom
} }
if (a.isFieldTech && !b.isFieldTech) return -1; //sort to the top if (a.isFieldTech && !b.isFieldTech) return -1; //sort to the top
if (!a.isFieldTech && b.isFieldTech) return 1; //sort to the bottom if (!a.isFieldTech && b.isFieldTech) return 1; //sort to the bottom
return 0; return 0;
}); });
} else if (find === 'allowed') { } else if (find === 'allowed') {
// tech.tech.sort((a, b) => {
// if (a.allowed() > !b.allowed()) return -1; //sort to the top
// if (!a.allowed() < b.allowed()) return 1; //sort to the bottom
// return 0;
// });
tech.tech.sort((a, b) => { tech.tech.sort((a, b) => {
if (a.allowed() > b.allowed()) return -1; //sort to the top return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1;
if (!a.allowed() < b.allowed()) return 1; //sort to the bottom
return 0;
}); });
} else if (find === 'have') { } else if (find === 'have') {
tech.tech.sort((a, b) => { tech.tech.sort((a, b) => {
if (a.count > b.count) return -1; //sort to the top return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1;
if (!a.count < b.count) return 1; //sort to the bottom
return 0; return 0;
}); });
} else if (find === 'heal') { } else if (find === 'heal') {
tech.tech.sort((a, b) => { tech.tech.sort((a, b) => {
if (a.isHealTech && b.isHealTech) { if (a.isHealTech && b.isHealTech) {
if (a.allowed() > b.allowed()) return -1; //sort to the top return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1;
if (!a.allowed() < b.allowed()) return 1; //sort to the bottom
} }
if (a.isHealTech && !b.isHealTech) return -1; //sort to the top if (a.isHealTech && !b.isHealTech) return -1; //sort to the top
if (!a.isHealTech && b.isHealTech) return 1; //sort to the bottom if (!a.isHealTech && b.isHealTech) return 1; //sort to the bottom
@@ -570,8 +568,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
} else if (find === 'bot') { } else if (find === 'bot') {
tech.tech.sort((a, b) => { tech.tech.sort((a, b) => {
if (a.isBotTech && b.isBotTech) { if (a.isBotTech && b.isBotTech) {
if (a.allowed() > b.allowed()) return -1; //sort to the top return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1;
if (!a.allowed() < b.allowed()) return 1; //sort to the bottom
} }
if (a.isBotTech && !b.isBotTech) return -1; //sort to the top if (a.isBotTech && !b.isBotTech) return -1; //sort to the top
if (!a.isBotTech && b.isBotTech) return 1; //sort to the bottom if (!a.isBotTech && b.isBotTech) return 1; //sort to the bottom
@@ -580,8 +577,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
} else if (document.getElementById("sort-input").value === 'skin') { } else if (document.getElementById("sort-input").value === 'skin') {
tech.tech.sort((a, b) => { tech.tech.sort((a, b) => {
if (a.isSkin && b.isSkin) { if (a.isSkin && b.isSkin) {
if (a.allowed() > b.allowed()) return -1; //sort to the top return (a.allowed() === b.allowed()) ? 0 : a.allowed() ? -1 : 1;
if (!a.allowed() < b.allowed()) return 1; //sort to the bottom
} }
if (a.isSkin && !b.isSkin) return -1; //sort to the top if (a.isSkin && !b.isSkin) return -1; //sort to the top
if (!a.isSkin && b.isSkin) return 1; //sort to the bottom if (!a.isSkin && b.isSkin) return 1; //sort to the bottom

View File

@@ -19,16 +19,18 @@ const level = {
// simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode // simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// tech.giveTech("performance") // tech.giveTech("performance")
// level.difficultyIncrease(3 * 4) //30 is near max on hard //60 is near max on why // level.difficultyIncrease(1 * 4) //30 is near max on hard //60 is near max on why
// spawn.setSpawnList(); // spawn.setSpawnList();
// spawn.setSpawnList(); // spawn.setSpawnList();
// m.maxHealth = m.health = 100 // m.maxHealth = m.health = 100
// m.maxEnergy = m.energy = 10000000
// tech.isRerollDamage = true // tech.isRerollDamage = true
// powerUps.research.changeRerolls(99999) // powerUps.research.changeRerolls(99999)
// m.immuneCycle = Infinity //you can't take damage // m.immuneCycle = Infinity //you can't take damage
// tech.tech[297].frequency = 100 // tech.tech[297].frequency = 100
// m.couplingChange(10) // m.couplingChange(10)
// 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.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
// tech.isHookWire = true
// m.energy = 0 // m.energy = 0
// simulation.molecularMode = 2 // simulation.molecularMode = 2
// m.damage(0.1); // m.damage(0.1);
@@ -36,10 +38,8 @@ const level = {
// 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.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 // b.guns[8].ammo = 100000000
// requestAnimationFrame(() => { tech.giveTech("MACHO") }); // requestAnimationFrame(() => { tech.giveTech("MACHO") });
// for (let i = 0; i < 1; ++i) tech.giveTech("electrostatic induction") // for (let i = 0; i < 1; ++i) tech.giveTech("autonomous defense")
// for (let i = 0; i < 1; ++i) tech.giveTech("grappling hook") // for (let i = 0; i < 1; ++i) tech.giveTech("rupture")
// 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") // for (let i = 0; i < 1; ++i) tech.giveTech("nail-bot upgrade")
// requestAnimationFrame(() => { for (let i = 0; i < 30; i++) tech.giveTech("laser-bot") }); // requestAnimationFrame(() => { for (let i = 0; i < 30; i++) tech.giveTech("laser-bot") });
// for (let i = 0; i < 1; i++) tech.giveTech("laser-bot upgrade") // for (let i = 0; i < 1; i++) tech.giveTech("laser-bot upgrade")
@@ -47,11 +47,11 @@ const level = {
// for (let i = 0; i < 1; ++i) tech.giveTech("mechanical resonance") // for (let i = 0; i < 1; ++i) tech.giveTech("mechanical resonance")
// for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); // for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling");
// level.testing(); // level.testing();
// for (let i = 0; i < 4; ++i) spawn.hopMother(1900, -500) // 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 < 5; ++i) spawn.starter(1900, -500)
// for (let i = 0; i < 1; ++i) spawn.shooterBoss(1900, -2500) // for (let i = 0; i < 1; ++i) spawn.shooterBoss(1900, -2500)
// spawn.beetleBoss(1900, -500, 25) // spawn.beetleBoss(1900, -500, 25)
// spawn.slasher2(2000, -1150) // spawn.slasher2(2000, -1150)
@@ -63,7 +63,8 @@ const level = {
// for (let i = 0; i < 40; ++i) tech.giveTech() // for (let i = 0; i < 40; ++i) tech.giveTech()
level[simulation.isTraining ? "walk" : "intro"]() //normal starting level ************************************************** level[simulation.isTraining ? "walk" : "intro"]() //normal starting level **************************************************
// spawn.bodyRect(2425, -120, 200, 200);
// console.log(body[body.length - 1].mass)
// simulation.isAutoZoom = false; //look in close // simulation.isAutoZoom = false; //look in close
// simulation.zoomScale *= 0.5; // simulation.zoomScale *= 0.5;
// simulation.setZoom(); // simulation.setZoom();

View File

@@ -2496,7 +2496,6 @@ const m = {
// set pick up target for when mouse is released // set pick up target for when mouse is released
if (body[grabbing.targetIndex]) { if (body[grabbing.targetIndex]) {
m.holdingTarget = body[grabbing.targetIndex]; m.holdingTarget = body[grabbing.targetIndex];
//
ctx.beginPath(); //draw on each valid body ctx.beginPath(); //draw on each valid body
let vertices = m.holdingTarget.vertices; let vertices = m.holdingTarget.vertices;
ctx.moveTo(vertices[0].x, vertices[0].y); ctx.moveTo(vertices[0].x, vertices[0].y);
@@ -2588,6 +2587,8 @@ const m = {
return `<strong>+${(4 * couple).toFixed(0)}%</strong> <strong class='color-block'>block</strong> collision <strong class='color-d'>damage</strong>` return `<strong>+${(4 * couple).toFixed(0)}%</strong> <strong class='color-block'>block</strong> collision <strong class='color-d'>damage</strong>`
case 9: //wormhole case 9: //wormhole
return `<span style = 'font-size:89%;'>after eating <strong class='color-block'>blocks</strong> <strong>+${(2 * couple).toFixed(0)}</strong> <strong class='color-f'>energy</strong></span>` return `<span style = 'font-size:89%;'>after eating <strong class='color-block'>blocks</strong> <strong>+${(2 * couple).toFixed(0)}</strong> <strong class='color-f'>energy</strong></span>`
case 10: //grappling hook
return `${powerUps.orb.ammo(1)} give ${(4 * couple).toFixed(0)}% more ammo`
} }
}, },
couplingChange(change = 0) { couplingChange(change = 0) {
@@ -2659,12 +2660,6 @@ const m = {
} }
} }
}, },
// <div id="cube" style="width: 4em; height: 8em;">
// <div style="transform: translate3d(1em, 0em, 0em)">1</div>
// <div style="transform: translate3d(2em, 0em, 0em)">2</div>
// <div style="transform: translate3d(3em, 0em, 0em)">3</div>
// <div style="transform: translate3d(4em, 0em, 0em)">4</div>
// </div>
{ {
name: "standing wave", name: "standing wave",
//<strong>deflecting</strong> protects you in every <strong>direction</strong> //<strong>deflecting</strong> protects you in every <strong>direction</strong>
@@ -3083,7 +3078,20 @@ const m = {
for (let i = 0, len = who.length; i < len; ++i) { for (let i = 0, len = who.length; i < len; ++i) {
sub = Vector.sub(who[i].position, m.pos); sub = Vector.sub(who[i].position, m.pos);
dist = Vector.magnitude(sub); dist = Vector.magnitude(sub);
if (dist < range) who[i].force.y -= who[i].mass * (simulation.g * mag); if (dist < range) {
who[i].force.y -= who[i].mass * (simulation.g * mag); //add a bit more then standard gravity
if (input.left) { //blocks move horizontally with the same force as the player
who[i].force.x -= m.FxAir * who[i].mass / 10; // move player left / a
} else if (input.right) {
who[i].force.x += m.FxAir * who[i].mass / 10; //move player right / d
}
}
// sub = Vector.sub(who[i].position, m.pos);
// dist = Vector.magnitude(sub);
// if (dist < range) who[i].force.y -= who[i].mass * (simulation.g * mag);
} }
} }
//control horizontal acceleration //control horizontal acceleration
@@ -3825,7 +3833,8 @@ const m = {
} }
if (tech.isRewindField) { if (tech.isRewindField) {
this.rewindCount = 0 this.rewindCount = 0
m.grabPowerUpRange2 = 300000 m.grabPowerUpRange2 = 300000// m.grabPowerUpRange2 = 200000;
m.hold = function () { m.hold = function () {
// console.log(m.fieldCDcycle) // console.log(m.fieldCDcycle)
m.grabPowerUp(); m.grabPowerUp();
@@ -4944,25 +4953,64 @@ const m = {
{ {
name: "grappling hook", 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 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`, description: `use <strong class='color-f'>energy</strong> to fire a hook that <strong>pulls</strong> player<br><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: () => { effect: () => {
m.fieldFire = true; m.fieldFire = true;
// m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping // m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping
m.fieldMeterColor = "#333" m.fieldMeterColor = "#333"
m.eyeFillColor = m.fieldMeterColor m.eyeFillColor = m.fieldMeterColor
m.fieldHarmReduction = 0.45; //55% reduction m.grabPowerUpRange2 = 300000 //m.grabPowerUpRange2 = 200000;
// m.fieldHarmReduction = 0.45; //55% reduction
m.hold = function () { m.hold = function () {
if (input.field) { if (m.isHolding) {
m.drawHold(m.holdingTarget);
m.holding();
m.throwBlock();
} else if (input.field) {
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)
if (m.fieldCDcycle < m.cycle) { if (m.fieldCDcycle < m.cycle) {
if (m.energy > 0.02) m.energy -= 0.02 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({ x: m.pos.x + 40 * Math.cos(m.angle), y: m.pos.y + 40 * Math.sin(m.angle) }, m.angle)
b.grapple(where, m.angle)
if (m.fieldCDcycle < m.cycle + 20) m.fieldCDcycle = m.cycle + 20 if (m.fieldCDcycle < m.cycle + 20) m.fieldCDcycle = m.cycle + 20
} }
m.grabPowerUp(); m.grabPowerUp();
} else {
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)
if (tech.isHookDefense && m.energy > 0.33 && m.fieldCDcycle < m.cycle) {
const maxCount = 6 //scale the number of hooks fired
let count = maxCount
const range = 300
for (let i = 0; i < mob.length; i++) {
if (!mob[i].isBadTarget &&
!mob[i].isInvulnerable &&
Vector.magnitude(Vector.sub(m.pos, mob[i].position)) < range &&
Matter.Query.ray(map, m.pos, mob[i].position).length === 0
) {
count--
m.energy -= 0.2
if (m.fieldCDcycle < m.cycle + 30) m.fieldCDcycle = m.cycle + 30
const angle = Math.atan2(mob[i].position.y - player.position.y, mob[i].position.x - player.position.x);
b.harpoon(m.pos, mob[i], angle, 0.75, true, 20) // harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) {
bullet[bullet.length - 1].drain = 0
for (; count > 0; count--) {
b.harpoon(m.pos, mob[i], angle + count * 2 * Math.PI / maxCount, 0.75, true, 10)
bullet[bullet.length - 1].drain = 0
}
break
}
}
ctx.beginPath();
ctx.arc(m.pos.x, m.pos.y, range, 0, 2 * Math.PI);
ctx.strokeStyle = "#000";
ctx.lineWidth = 0.25;
ctx.setLineDash([10, 30]);
ctx.stroke();
ctx.setLineDash([]);
}
} }
m.drawRegenEnergy() m.drawRegenEnergy()
//look for nearby mobs and fire harpoons at them
} }
} }
}, },

View File

@@ -621,17 +621,18 @@ const powerUps = {
return 17; return 17;
}, },
effect() { effect() {
const couplingExtraAmmo = m.fieldMode === 10 ? 1 + 0.04 * m.coupling : 1
if (b.inventory.length > 0) { if (b.inventory.length > 0) {
powerUps.animatePowerUpGrab('rgba(68, 102, 119,0.25)') powerUps.animatePowerUpGrab('rgba(68, 102, 119,0.25)')
if (tech.isAmmoForGun && b.activeGun !== null) { //give extra ammo to one gun only with tech logistics if (tech.isAmmoForGun && b.activeGun !== null) { //give extra ammo to one gun only with tech logistics
const target = b.guns[b.activeGun] const target = b.guns[b.activeGun]
if (target.ammo !== Infinity) { if (target.ammo !== Infinity) {
if (tech.ammoCap) { if (tech.ammoCap) {
const ammoAdded = Math.ceil(target.ammoPack * 0.7 * tech.ammoCap * 0.8) //0.7 is average const ammoAdded = Math.ceil(target.ammoPack * 0.7 * tech.ammoCap * 0.8 * couplingExtraAmmo) //0.7 is average
target.ammo = ammoAdded target.ammo = ammoAdded
// simulation.makeTextLog(`${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>=</span> ${ammoAdded}`) // simulation.makeTextLog(`${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>=</span> ${ammoAdded}`)
} else { } else {
const ammoAdded = Math.ceil((0.7 * Math.random() + 0.7 * Math.random()) * target.ammoPack * 0.8) const ammoAdded = Math.ceil((0.7 * Math.random() + 0.7 * Math.random()) * target.ammoPack * 0.8 * couplingExtraAmmo)
target.ammo += ammoAdded target.ammo += ammoAdded
// simulation.makeTextLog(`${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>+=</span> ${ammoAdded}`) // simulation.makeTextLog(`${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>+=</span> ${ammoAdded}`)
} }
@@ -642,11 +643,12 @@ const powerUps = {
const target = b.guns[b.inventory[i]] const target = b.guns[b.inventory[i]]
if (target.ammo !== Infinity) { if (target.ammo !== Infinity) {
if (tech.ammoCap) { if (tech.ammoCap) {
const ammoAdded = Math.ceil(target.ammoPack * 0.45 * tech.ammoCap) //0.45 is average const ammoAdded = Math.ceil(target.ammoPack * 0.45 * tech.ammoCap * couplingExtraAmmo) //0.45 is average
target.ammo = ammoAdded target.ammo = ammoAdded
// textLog += `${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>=</span> ${ammoAdded}<br>` // textLog += `${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>=</span> ${ammoAdded}<br>`
} else { } else { //default ammo behavior
const ammoAdded = Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack) //Math.ceil(Math.random() * target.ammoPack) const ammoAdded = Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack * couplingExtraAmmo) //Math.ceil(Math.random() * target.ammoPack)
// console.log(ammoAdded, Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack))
target.ammo += ammoAdded target.ammo += ammoAdded
// textLog += `${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>+=</span> ${ammoAdded}<br>` // textLog += `${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>+=</span> ${ammoAdded}<br>`
} }
@@ -1270,24 +1272,25 @@ const powerUps = {
} }
for (let i = 0; i < localSettings.entanglement.techIndexes.length; i++) { //add tech for (let i = 0; i < localSettings.entanglement.techIndexes.length; i++) { //add tech
let choose = localSettings.entanglement.techIndexes[i] let choose = localSettings.entanglement.techIndexes[i]
const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count + 1}x)` : ""; if (tech.tech[choose]) {
const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count + 1}x)` : "";
if (choose === null || tech.tech[choose].count + 1 > tech.tech[choose].maxCount || !tech.tech[choose].allowed()) { if (choose === null || tech.tech[choose].count + 1 > tech.tech[choose].maxCount || !tech.tech[choose].allowed()) {
// text += `<div class="choose-grid-module" style = "background-color: #efeff5; border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; margin: 1px; padding-top: 6px; padding-bottom: 6px;"><div class="grid-title">${tech.tech[choose].name} <span style = "color: #aaa;font-weight: normal;font-size:80%;">- incoherent</span></div></div>` // text += `<div class="choose-grid-module" style = "background-color: #efeff5; border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; margin: 1px; padding-top: 6px; padding-bottom: 6px;"><div class="grid-title">${tech.tech[choose].name} <span style = "color: #aaa;font-weight: normal;font-size:80%;">- incoherent</span></div></div>`
text += powerUps.incoherentTechText(choose) text += powerUps.incoherentTechText(choose)
} else { } else {
if (tech.tech[choose].isFieldTech) { if (tech.tech[choose].isFieldTech) {
text += powerUps.fieldTechText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.fieldTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isGunTech) { } else if (tech.tech[choose].isGunTech) {
text += powerUps.gunTechText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.gunTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isLore) { } else if (tech.tech[choose].isLore) {
text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>` text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choose})"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[choose].name} ${isCount}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
} else if (tech.tech[choose].isJunk) { } else if (tech.tech[choose].isJunk) {
text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.junkTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isSkin) { } else if (tech.tech[choose].isSkin) {
text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`)
} else { //normal tech } else { //normal tech
text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`)
}
} }
} }
} }

View File

@@ -4545,7 +4545,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return (!tech.isLargeHarpoon && tech.haveGunCheck("harpoon")) || tech.isNeedles return (!tech.isLargeHarpoon && tech.haveGunCheck("harpoon")) || tech.isNeedles || tech.isHookDefense
}, },
requires: "needle gun, harpoon, not Bessemer process", requires: "needle gun, harpoon, not Bessemer process",
effect() { effect() {
@@ -5149,7 +5149,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return ((tech.haveGunCheck("super balls") || tech.isSuperMine) && !tech.isSuperBounce) || (tech.haveGunCheck("harpoon") && !tech.fragments) return ((tech.haveGunCheck("super balls") || tech.isSuperMine) && !tech.isSuperBounce) || (tech.haveGunCheck("harpoon") && !tech.fragments) || tech.isHookDefense
}, },
requires: "super balls, harpoon, not fragmentation", requires: "super balls, harpoon, not fragmentation",
effect() { effect() {
@@ -5574,7 +5574,7 @@ const tech = {
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return !tech.isExplodeRadio && ((tech.haveGunCheck("harpoon") && !tech.isFoamBall) || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount || tech.isRivets || tech.blockDamage > 0.075) return !tech.isExplodeRadio && ((tech.haveGunCheck("harpoon") && !tech.isFoamBall) || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount || tech.isRivets || tech.blockDamage > 0.075 || tech.isHookDefense)
}, },
requires: "grenades, missiles, rivets, harpoon, or mass driver, not iridium-192, not polyurethane foam", requires: "grenades, missiles, rivets, harpoon, or mass driver, not iridium-192, not polyurethane foam",
effect() { effect() {
@@ -7784,7 +7784,7 @@ const tech = {
}, },
{ {
name: "inertial mass", name: "inertial mass",
description: "<strong>negative mass</strong> is larger and <strong>faster</strong><br><strong class='color-block'>blocks</strong> also move <strong>horizontally</strong> with the field", description: "<strong>negative mass</strong> is larger and <strong>faster</strong>", //<br><strong class='color-block'>blocks</strong> also move <strong>horizontally</strong> with the field
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -8052,7 +8052,7 @@ const tech = {
}, },
{ {
name: "electric generator", name: "electric generator",
description: "after <strong>deflecting</strong> mobs<br>molecular assembler generates <strong>+50</strong> <strong class='color-f'>energy</strong>", description: "after <strong>deflecting</strong> mobs<br><strong>molecular assembler</strong> generates <strong>+50</strong> <strong class='color-f'>energy</strong>",
isFieldTech: true, isFieldTech: true,
maxCount: 9, maxCount: 9,
count: 0, count: 0,
@@ -8754,6 +8754,82 @@ const tech = {
tech.isWormholeMapIgnore = false tech.isWormholeMapIgnore = false
} }
}, },
{
name: "autonomous defense",
description: "<strong>grappling hook</strong> uses <strong>20</strong> <strong class='color-f'>energy</strong><br> to fire <strong>harpoons</strong> at nearby mobs",
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldMode === 10
},
requires: "grappling hook",
effect() {
tech.isHookDefense = true
},
remove() {
tech.isHookDefense = false
}
},
{
name: "rupture",
description: "after <strong>grappling hook</strong> impacts solid objects<br>generate an <strong class='color-e'>explosion</strong>",
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldMode === 10
},
requires: "grappling hook",
effect() {
tech.isHookExplosion = true
},
remove() {
tech.isHookExplosion = false
}
},
// {
// name: "autonomous defense",
// description: "if you <strong>collide</strong> with a mob<br>fire <strong>harpoons</strong> at nearby mobs",
// isFieldTech: true,
// maxCount: 1,
// count: 0,
// frequency: 2,
// frequencyDefault: 2,
// allowed() {
// return m.fieldMode === 10 && !tech.isHookDefense
// },
// requires: "grappling hook, not automatic offense",
// effect() {
// tech.isHookDefense = true
// },
// remove() {
// tech.isHookDefense = false
// }
// },
// {
// name: "wire",
// description: "",
// isFieldTech: true,
// maxCount: 1,
// count: 0,
// frequency: 2,
// frequencyDefault: 2,
// allowed() {
// return m.fieldMode === 10
// },
// requires: "grappling hook",
// effect() {
// tech.isHookWire = true
// },
// remove() {
// tech.isHookWire = false
// }
// },
//************************************************** //**************************************************
//************************************************** experimental //************************************************** experimental
//************************************************** modes //************************************************** modes
@@ -11800,4 +11876,7 @@ const tech = {
isHealBrake: null, isHealBrake: null,
isMassProduction: null, isMassProduction: null,
isPrinter: null, isPrinter: null,
// isHookWire: null,
isHookDefense: null,
isHookExplosion: null,
} }

View File

@@ -1,39 +1,29 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
grappling hook is now a field (work in progress) grappling hook
reworked physics to allow faster speeds, but more control added coupling effect - 4% extra ammo per coupling
improved rate of power up grabbing doesn't destroy blocks, instead the player grabs blocks
more player control to hook retraction rate doesn't automatically retract after hitting power ups
changed hook shape and field image graphics improved momentum conservation on yank and catching blocks, power ups
grappling hook field coupling, more tech, bug fixes, and general polish to be added soon removed accidental 55% defense for grapple field
tech (no images yet)
autonomous defense - fire harpoons at nearby mobs
rupture - explosion on impact with map, block, mob
aerostat - 88->100% damage in air 22-> 25% damage on ground negative mass field has horizontal block motion by default
foam damage reduced 10%, ammo increased about 10% fixed tech sorting by "allowed tech" in experiment mode
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
*********************************************************** TODO ***************************************************** *********************************************************** TODO *****************************************************
grappling hook is a field grappling hook is a field
check for places that the player could get into but not out of check for places that the player could get into but not out of
maybe grapple could grab more then 1 power up? field tech ideas
grapple slices blocks hook and line stuns?
cut large blocks into 2,3 increase hook damage
use dead mob code for mobs > 5 sides hook damage aura
write code to cut large blocks in half and remove one half hook's line does damage
need several field tech generate ___ after destroying blocks
new field tech ideas energy, drones, iceIX, explosion, nails, junk bots?
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 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 disable cloaking heal? maybe you don't need to disable, just don't heal twice