grapple tech

new community level shipwreck by 3xionDev

grappling hook
  tech: reel - increase block damage 400%, generate 30 energy after hooking blocks
  added tokamak to grappling hook
  updated rope graphics
  added input.up to adjust positioning while hook is attached
  added images for CIWS, rupture, autonomous defense
  aerostat: 25->15% reduced damage on ground
  rupture unlocks explosive tech
  rupture destroys blocks
  autonomous defense renamed to CIWS

field emitter 6->4 base energy regen
tech: autonomous defense - harpoon tech that fires harpoons after taking damage
degenerate matter: 75->85% defense while field is active
neutronium: 90->95% defense while field is active
unified field theory no longer has field emitter as an option
This commit is contained in:
landgreen
2023-12-03 09:59:20 -08:00
parent ce74f420e3
commit ad33cf68ea
14 changed files with 505 additions and 112 deletions

BIN
img/CIWS.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
img/autonomous defense.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
img/reel.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
img/rupture.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@@ -1498,6 +1498,10 @@ const b = {
classType: "bullet",
endCycle: simulation.cycle + 70,
isSlowPull: false,
drawStringControlMagnitude: 1000 + 1000 * Math.random(),
drawStringFlip: (Math.round(Math.random()) ? 1 : -1),
attached: false,
glowColor: tech.isHookExplosion ? "rgba(200,0,0,0.07)" : tech.isHarmReduce ? "rgba(50,100,255,0.1)" : "rgba(0,200,255,0.07)",
collisionFilter: {
category: cat.bullet,
mask: tech.isShieldPierce ? cat.body | cat.mob | cat.mobBullet : cat.body | cat.mob | cat.mobBullet | cat.mobShield,
@@ -1507,13 +1511,31 @@ const b = {
density: 0.004, //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed
drain: 0.001,
draw() {
// draw rope
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.strokeStyle = "#000" // "#0ce"
ctx.lineWidth = 0.5
ctx.beginPath();
ctx.moveTo(where.x, where.y);
if (this.attached) {
const controlPoint = Vector.add(where, Vector.mult(sub, -0.5))
ctx.quadraticCurveTo(controlPoint.x, controlPoint.y, this.vertices[0].x, this.vertices[0].y)
} else {
const long = Math.max(Vector.magnitude(sub), 60)
const perpendicular = Vector.mult(Vector.normalise(Vector.perp(sub)), this.drawStringFlip * Math.min(0.7 * long, 10 + this.drawStringControlMagnitude / (10 + Vector.magnitude(sub))))
const controlPoint = Vector.add(Vector.add(where, Vector.mult(sub, -0.5)), perpendicular)
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();
ctx.strokeStyle = this.glowColor // "#0ce"
ctx.lineWidth = 10
ctx.stroke();
ctx.strokeStyle = "#000" // "#0ce"
ctx.lineWidth = 0.5
ctx.stroke();
// ctx.lineTo(this.vertices[0].x, this.vertices[0].y);
// if (tech.isHookWire) {
// //draw wire
@@ -1536,36 +1558,16 @@ const b = {
// 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();
//draw hook
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))
const spike = Vector.add(this.vertices[3], Vector.mult(Vector.sub(this.vertices[3], this.vertices[2]), 2))
ctx.moveTo(this.vertices[2].x, this.vertices[2].y);
ctx.lineTo(spike2.x, spike2.y);
ctx.lineTo(spike.x, spike.y);
ctx.lineTo(this.vertices[1].x, this.vertices[1].y);
ctx.fillStyle = '#000'
ctx.fill();
@@ -1577,24 +1579,9 @@ 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 (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()
},
caughtPowerUp: null,
dropCaughtPowerUp() {
@@ -1624,6 +1611,7 @@ const b = {
}
},
retract() {
this.attached = false
this.do = this.returnToPlayer
this.endCycle = simulation.cycle + 60
Matter.Body.setDensity(this, 0.0005); //reduce density on return
@@ -1644,6 +1632,17 @@ const b = {
player.force.x += momentum.x
player.force.y += momentum.y
if (this.pickUpTarget) {
if (tech.isReel && this.blockDist > 150) {
// console.log(0.0003 * Math.min(this.blockDist, 1000))
m.energy += 0.00044 * Math.min(this.blockDist, 800) //max 0.352 energy
simulation.drawList.push({ //add dmg to draw queue
x: m.pos.x,
y: m.pos.y,
radius: 10,
color: m.fieldMeterColor,
time: simulation.drawTime
});
}
m.holdingTarget = this.pickUpTarget
// give block to player after it returns
m.isHolding = true;
@@ -1696,22 +1695,46 @@ const b = {
},
pickUpTarget: null,
grabBlocks() {
if (this.pickUpTarget) {
if (this.pickUpTarget) { //if always attached to a block
//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) {
} 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()
if (tech.isHookExplosion) {
b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end
const blockVertices = blocks[i].bodyA.vertices
Composite.remove(engine.world, blocks[i].bodyA)
body.splice(body.indexOf(blocks[i].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(blockVertices[0].x, blockVertices[0].y);
for (let j = 1; j < blockVertices.length; j++) ctx.lineTo(blockVertices[j].x, blockVertices[j].y);
ctx.lineTo(blockVertices[0].x, blockVertices[0].y);
ctx.lineWidth = 2;
ctx.strokeStyle = `rgba(0,0,0,${this.count / 25})`
ctx.stroke();
},
})
} else {
this.pickUpTarget = blocks[i].bodyA
if (tech.isHookExplosion) b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end
this.blockDist = Vector.magnitude(Vector.sub(this.pickUpTarget.position, m.pos))
}
} else if (blocks[i].bodyB.classType === "body" && !blocks[i].bodyB.isNotHoldable && !blocks[0].bodyB.mass < 60) {
this.retract()
this.pickUpTarget = blocks[i].bodyB
this.blockDist = Vector.magnitude(Vector.sub(this.pickUpTarget.position, m.pos))
if (tech.isHookExplosion) b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end
}
}
@@ -1779,6 +1802,7 @@ const b = {
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 (tech.isHookExplosion) b.explosion(this.position, 150 + 50 * Math.random()); //makes bullet do explosive damage at end
this.attached = true
Matter.Body.setVelocity(this, { x: 0, y: 0 });
Matter.Sleeping.set(this, true)
this.endCycle = simulation.cycle + 5
@@ -1802,14 +1826,15 @@ const b = {
if (input.down) { //down
this.isSlowPull = true
dist = 0
player.force.y += 2.5 * player.mass * simulation.g; //adjust this to control fall rate while hooked and pressing down
player.force.y += 3 * player.mass * simulation.g; //adjust this to control fall rate while hooked and pressing down
} else if (input.up) {
this.isSlowPull = false
player.force.y -= player.mass * simulation.g; //adjust this to control fall rate while hooked and pressing down
}
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)
const drag = 1 - 30 / Math.min(Math.max(100, dist), 700) - 0.1 * (player.speed > 66)
// console.log(player.speed)
Matter.Body.setVelocity(player, { x: player.velocity.x * drag, y: player.velocity.y * drag });
const pullScale = 0.0004

View File

@@ -204,24 +204,17 @@ function collisionChecks(event) {
// 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.isHarpoonDefense) { //fire harpoons at mobs after getting hit
const maxCount = 10 + 3 * tech.extraHarpoons //scale the number of hooks fired
let count = maxCount - 1
const angle = Math.atan2(mob[k].position.y - player.position.y, mob[k].position.x - player.position.x);
b.harpoon(m.pos, mob[k], angle, 0.75, true, 7) // 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[k], angle + count * 2 * Math.PI / maxCount, 0.75, true, 7)
bullet[bullet.length - 1].drain = 0
}
}
if (tech.isStimulatedEmission) powerUps.ejectTech()
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

View File

@@ -1275,7 +1275,7 @@ window.addEventListener("keydown", function (event) {
simulation.molecularMode++
m.fieldUpgrades[4].description = m.fieldUpgrades[4].setDescription()
} else {
m.setField((m.fieldMode === m.fieldUpgrades.length - 1) ? 0 : m.fieldMode + 1) //cycle to next field
m.setField((m.fieldMode === m.fieldUpgrades.length - 1) ? 1 : m.fieldMode + 1) //cycle to next field, skip field emitter
if (m.fieldMode === 4) {
simulation.molecularMode = 0
m.fieldUpgrades[4].description = m.fieldUpgrades[4].setDescription()

View File

@@ -11,7 +11,7 @@ const level = {
// playableLevels: ["pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion"],
//see level.populateLevels: (intro, ... , reservoir or factory, reactor, ... , subway, final) added later
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock"],
communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass", "cantilever", "tlinat", "ruins", "ace", "crimsonTowers", "LaunchSite"],
communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass", "cantilever", "tlinat", "ruins", "ace", "crimsonTowers", "LaunchSite", "shipwreck"],
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon", "diamagnetism"],
levels: [],
start() {
@@ -19,7 +19,7 @@ const level = {
// simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode
// simulation.isHorizontalFlipped = true
// tech.giveTech("performance")
// level.difficultyIncrease(1 * 4) //30 is near max on hard //60 is near max on why
// level.difficultyIncrease(5 * 4) //30 is near max on hard //60 is near max on why
// spawn.setSpawnList();
// spawn.setSpawnList();
// m.maxHealth = m.health = 100
@@ -38,25 +38,26 @@ 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.guns[8].ammo = 100000000
// requestAnimationFrame(() => { tech.giveTech("MACHO") });
// for (let i = 0; i < 1; ++i) tech.giveTech("autonomous defense")
// for (let i = 0; i < 1; ++i) tech.giveTech("rupture")
// for (let i = 0; i < 1; ++i) tech.giveTech("nail-bot upgrade")
// for (let i = 0; i < 1; ++i) tech.giveTech("degenerate matter")
// for (let i = 0; i < 1; ++i) tech.giveTech("reel")
// for (let i = 0; i < 1; ++i) tech.giveTech("tokamak")
// 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("uncertainty principle")
// for (let i = 0; i < 1; ++i) tech.giveTech("mechanical resonance")
// for (let i = 0; i < 1; ++i) tech.giveTech("rupture")
// for (let i = 0; i < 1; ++i) tech.giveTech("autonomous defense")
// 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 < 100; i++) powerUps.directSpawn(1750, -500, "coupling");
// level.testing();
// level.shipwreck();
// for (let i = 0; i < 4; ++i) spawn.hopMother(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.timeSkipBoss(1900, -2500)
// 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())
// for (let i = 0; i < 5; ++i) spawn.starter(1000 + 1000 * Math.random(), -500 + 300 * Math.random())
// tech.addJunkTechToPool(2)
// tech.tech[322].frequency = 100
// spawn.tetherBoss(1900, -500, { x: 1900, y: -500 })
@@ -29768,6 +29769,319 @@ const level = {
// spawn.secondaryBossChance(100, -1500)
powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
shipwreck() {
simulation.makeTextLog(`<strong>shipwreck</strong> by <span class='color-var'>3xionDev</span>`);
level.setPosToSpawn(0, -50); //normal spawn
level.exit.x = 1500;
level.exit.y = -1875;
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit
level.defaultZoom = 1800
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#05001C";
// color.map = "#444" //custom map color
spawn.mapRect(-325, 0, 650, 300);
spawn.mapRect(-275, -675, 50, 700);
spawn.mapRect(-325, -1025, 650, 300);
spawn.mapRect(-275, -750, 50, 75);
spawn.mapRect(300, 50, 675, 200);
spawn.mapRect(925, 50, 450, 150);
spawn.mapRect(275, -750, 50, 275);
spawn.mapRect(275, -325, 50, 325);
spawn.bodyRect(150, -175, 100, 100);
spawn.bodyRect(-200, -450, 100, 400);
spawn.bodyRect(-150, -650, 25, 50);
spawn.bodyRect(-200, -700, 25, 25);
spawn.bodyRect(175, -250, 75, 100);
spawn.mapRect(875, -50, 100, 100);
spawn.mapRect(350, -175, 25, 25);
spawn.mapRect(325, -175, 175, 225);
spawn.bodyRect(375, -225, 50, 50);
spawn.bodyRect(700, -450, 125, 125);
spawn.mapRect(1375, 25, 400, 100);
spawn.mapRect(1675, -175, 100, 200);
spawn.mapRect(1775, -175, 225, 100);
spawn.mapRect(1575, -75, 100, 100);
spawn.mapRect(1775, -75, 175, 100);
spawn.mapRect(1300, 125, 250, 25);
spawn.mapRect(850, 200, 225, 25);
spawn.mapRect(1100, 200, 50, 100);
spawn.mapRect(1250, 175, 50, 125);
spawn.mapRect(1950, -150, 275, 50);
spawn.mapRect(2125, -150, 25, 25);
spawn.mapRect(2125, -175, 1025, 100);
spawn.mapRect(2625, -350, 25, 25);
spawn.mapRect(2650, -325, 25, 150);
spawn.mapRect(2625, -400, 50, 250);
spawn.bodyRect(1900, -200, 325, 25);
spawn.bodyRect(2525, -275, 100, 100);
spawn.bodyRect(2575, -325, 50, 50);
spawn.mapRect(425, -75, 150, 125);
spawn.bodyRect(350, -250, 75, 75);
spawn.bodyRect(1250, -200, 25, 25);
spawn.bodyRect(1150, -350, 100, 175);
spawn.bodyRect(1375, -375, 25, 25);
spawn.bodyRect(1375, -400, 50, 100);
spawn.mapRect(2650, -400, 500, 50);
spawn.mapRect(3100, -175, 300, 50);
spawn.bodyRect(2700, -250, 75, 25);
spawn.bodyRect(2725, -275, 25, 25);
spawn.bodyRect(2750, -250, 25, 25);
spawn.bodyRect(2825, -275, 75, 100);
spawn.randomMob(3650, -250, 0);
spawn.bodyRect(2925, -225, 50, 50);
spawn.mapRect(325, -950, 25, 25);
spawn.mapRect(325, -975, 650, 200);
spawn.mapRect(975, -900, 200, 100);
spawn.mapRect(1175, -850, 100, 100);
spawn.mapRect(1275, -800, 75, 125);
spawn.mapRect(1350, -725, 25, 125);
spawn.mapRect(1225, -800, 25, 25);
spawn.mapRect(950, -925, 100, 25);
spawn.mapRect(1150, -875, 100, 25);
spawn.mapRect(1250, -825, 75, 50);
spawn.mapRect(1125, -825, 75, 50);
spawn.mapRect(1250, -775, 50, 50);
spawn.mapRect(1400, -225, 100, 200);
spawn.mapRect(1550, -150, 125, 75);
spawn.mapRect(1500, -100, 75, 75);
spawn.mapRect(1175, -225, 225, 100);
spawn.mapRect(1475, -200, 100, 100);
spawn.mapRect(1300, -175, 125, 100);
spawn.mapRect(1250, -150, 50, 200);
spawn.mapRect(1600, -275, 50, 150);
spawn.mapRect(1300, -275, 75, 75);
spawn.mapRect(1475, -375, 50, 225);
spawn.mapRect(1575, -225, 25, 100);
spawn.mapRect(1500, -325, 50, 125);
spawn.bodyRect(1400, -350, 25, 50);
spawn.bodyRect(1650, -425, 50, 50);
spawn.bodyRect(1750, -475, 25, 125);
spawn.bodyRect(1725, -575, 150, 50);
spawn.bodyRect(1625, -425, 25, 50);
spawn.bodyRect(1175, -425, 75, 75);
spawn.mapRect(325, -625, 175, 50);
spawn.mapRect(425, -800, 25, 175);
spawn.mapRect(375, -800, 25, 200);
spawn.mapRect(500, -800, 25, 225);
spawn.mapRect(475, -800, 50, 225);
spawn.mapRect(675, -875, 50, 575);
spawn.mapRect(675, -150, 25, 175);
spawn.mapRect(700, -150, 25, 75);
spawn.mapRect(675, -125, 25, 200);
spawn.bodyRect(675, -300, 50, 150);
spawn.mapRect(2125, -1025, 1025, 100);
spawn.mapRect(3050, -975, 325, 50);
spawn.mapRect(3300, -925, 75, 600);
spawn.bodyRect(3300, -325, 75, 125);
spawn.bodyRect(3325, -325, 25, 25);
spawn.mapRect(3300, -325, 75, 25);
spawn.mapRect(3325, -175, 1100, 25);
spawn.mapRect(3325, -950, 1100, 25);
spawn.mapRect(3350, -725, 225, 25);
spawn.mapRect(3500, -925, 75, 200);
spawn.mapRect(3350, -850, 175, 25);
spawn.bodyRect(4075, -625, 125, 125);
spawn.bodyRect(3850, -825, 75, 50);
spawn.bodyRect(4050, -800, 25, 50);
spawn.bodyRect(4150, -825, 75, 100);
spawn.bodyRect(3900, -800, 50, 75);
spawn.bodyRect(3575, -375, 100, 75);
spawn.bodyRect(3800, -675, 75, 100);
spawn.bodyRect(3950, -875, 250, 150);
spawn.bodyRect(3975, -700, 50, 100);
spawn.bodyRect(4150, -775, 200, 125);
spawn.bodyRect(3825, -700, 50, 125);
spawn.bodyRect(3575, -550, 125, 50);
spawn.bodyRect(3750, -550, 25, 25);
spawn.bodyRect(3600, -625, 75, 50);
spawn.bodyRect(3550, -500, 75, 50);
spawn.bodyRect(4200, -675, 75, 75);
spawn.bodyRect(4400, -600, 50, 125);
spawn.mapRect(4375, -175, 350, 25);
spawn.mapRect(4475, -200, 475, 50);
spawn.mapRect(4450, -925, 25, 25);
spawn.mapRect(4475, -950, 475, 50);
spawn.mapRect(4350, -950, 225, 25);
spawn.mapRect(4450, -925, 100, 750);
spawn.mapRect(4650, -900, 825, 700);
spawn.mapRect(5250, -825, 475, 550);
spawn.mapRect(5550, -725, 700, 350);
spawn.mapRect(6100, -625, 550, 150);
spawn.mapRect(6600, -575, 225, 50);
spawn.mapRect(1325, -875, 50, 200);
spawn.mapRect(1275, -825, 50, 25);
spawn.mapRect(1275, -875, 25, 50);
spawn.mapRect(1225, -900, 75, 25);
spawn.mapRect(1325, -900, 50, 75);
spawn.mapRect(1075, -925, 200, 75);
spawn.mapRect(1275, -975, 75, 150);
spawn.mapRect(1300, -800, 100, 150);
spawn.mapRect(1375, -725, 50, 150);
spawn.mapRect(-325, -1525, 650, 300);
spawn.mapRect(150, -1275, 50, 375);
spawn.mapRect(-100, -1350, 50, 450);
spawn.mapRect(-325, -2600, 650, 300);
spawn.mapRect(-275, -2400, 25, 50);
spawn.mapRect(-275, -2325, 50, 825);
spawn.mapRect(300, -1475, 675, 200);
spawn.bodyRect(375, -1250, 75, 75);
spawn.bodyRect(800, -1275, 25, 300);
spawn.mapRect(1950, -1000, 175, 100);
spawn.mapRect(1850, -950, 125, 125);
spawn.mapRect(1825, -875, 75, 125);
spawn.mapRect(1825, -800, 25, 125);
spawn.mapRect(1800, -750, 25, 150);
spawn.mapRect(1775, -625, 50, 150);
spawn.mapRect(2000, -900, 25, 225);
spawn.mapRect(2075, -925, 50, 400);
spawn.mapRect(1000, -825, 25, 300);
spawn.mapRect(1050, -900, 50, 25);
spawn.mapRect(1050, -925, 50, 25);
spawn.mapRect(2475, -100, 50, 350);
spawn.mapRect(2650, -100, 25, 725);
spawn.mapRect(2350, -950, 50, 350);
spawn.mapRect(775, -825, 25, 375);
spawn.mapRect(3750, -950, 25, 175);
spawn.mapRect(3625, -925, 25, 275);
spawn.mapRect(4225, -925, 50, 200);
spawn.mapRect(950, -1425, 200, 100);
spawn.mapRect(1150, -1400, 150, 75);
spawn.mapRect(1300, -1350, 25, 100);
spawn.mapRect(1275, -1350, 25, 50);
spawn.bodyRect(1300, -1250, 25, 275);
spawn.bodyRect(2600, -1575, 375, 550);
spawn.bodyRect(2625, -1300, 75, 150);
spawn.bodyRect(2700, -1475, 100, 275);
spawn.bodyRect(2525, -1200, 75, 150);
spawn.mapRect(1675, -1400, 200, 75);
spawn.mapRect(1825, -1425, 225, 100);
spawn.mapRect(1650, -1350, 75, 100);
spawn.mapRect(1700, -1275, 25, 125);
spawn.bodyRect(1225, -1425, 550, 25);
spawn.bodyRect(1300, -1650, 100, 150);
spawn.bodyRect(1600, -1675, 100, 200);
spawn.bodyRect(1575, -1525, 25, 25);
spawn.bodyRect(1450, -1575, 25, 125);
spawn.bodyRect(1500, -1650, 75, 50);
spawn.mapRect(2325, -1225, 50, 200);
spawn.mapRect(2375, -1300, 100, 275);
spawn.mapRect(2225, -1125, 125, 100);
spawn.mapRect(2300, -1150, 50, 50);
spawn.bodyRect(2250, -850, 75, 100);
spawn.mapRect(150, -2550, 800, 200);
spawn.mapRect(875, -2500, 275, 100);
spawn.mapRect(325, -2400, 75, 375);
spawn.mapRect(325, -1800, 75, 350);
spawn.bodyRect(325, -2025, 75, 225);
spawn.mapRect(-150, -2375, 25, 375);
spawn.mapRect(25, -2400, 50, 500);
spawn.mapRect(-100, -2375, 25, 225);
spawn.mapRect(200, -2350, 50, 250);
spawn.bodyRect(250, -1875, 25, 75);
spawn.bodyRect(-50, -2050, 50, 50);
spawn.mapRect(1050, -1350, 50, 150);
spawn.mapRect(575, -1325, 25, 100);
spawn.mapRect(400, -1300, 25, 75);
spawn.mapRect(525, -1300, 50, 125);
spawn.mapRect(575, -2400, 75, 275);
spawn.mapRect(650, -2325, 25, 325);
spawn.mapRect(625, -2150, 50, 75);
spawn.mapRect(625, -2375, 50, 100);
spawn.mapRect(600, -2125, 25, 25);
spawn.mapRect(650, -2075, 25, 150);
spawn.mapRect(675, -2375, 50, 200);
spawn.mapRect(650, -2200, 50, 75);
spawn.mapRect(625, -2100, 50, 75);
spawn.mapRect(1100, -2475, 950, 50);
spawn.mapRect(1325, -1825, 450, 25);
spawn.mapRect(1475, -1850, 150, 50);
spawn.mapRect(1725, -2425, 50, 600);
spawn.mapRect(1325, -2450, 50, 450);
spawn.mapRect(1475, -2425, 25, 150);
spawn.mapRect(1675, -2425, 25, 600);
spawn.bodyRect(1450, -2175, 50, 75);
spawn.bodyRect(1650, -2200, 50, 50);
spawn.mapRect(950, -1550, 75, 125);
spawn.mapRect(900, -1500, 50, 50);
spawn.mapRect(2000, -2475, 125, 50);
spawn.mapRect(2100, -2475, 1050, 100);
spawn.mapRect(3050, -2425, 300, 50);
spawn.mapRect(3225, -2400, 1350, 25);
spawn.mapRect(4475, -2400, 475, 50);
spawn.mapRect(4900, -2375, 1125, 50);
spawn.mapRect(3950, -1350, 2075, 50);
spawn.mapRect(4075, -1325, 75, 400);
spawn.mapRect(4775, -1325, 75, 425);
spawn.mapRect(6000, -2350, 1075, 1025);
spawn.mapRect(6675, -2250, 950, 825);
spawn.mapRect(7375, -2050, 700, 425);
spawn.mapRect(7850, -1900, 425, 125);
spawn.mapRect(8200, -1850, 275, 25);
spawn.mapRect(5000, -2350, 75, 400);
spawn.mapRect(5200, -2350, 25, 600);
spawn.mapRect(5600, -2325, 25, 475);
spawn.mapRect(5750, -2350, 50, 300);
spawn.mapRect(5800, -2325, 25, 400);
spawn.mapRect(5775, -2075, 25, 50);
spawn.bodyRect(5325, -2250, 75, 125);
spawn.bodyRect(5925, -1800, 75, 125);
spawn.bodyRect(5475, -1800, 75, 225);
spawn.bodyRect(5350, -2050, 175, 100);
spawn.bodyRect(5475, -2125, 75, 125);
spawn.bodyRect(5750, -1750, 100, 100);
spawn.bodyRect(5900, -1950, 175, 150);
spawn.bodyRect(4600, -1950, 150, 275);
spawn.bodyRect(4875, -1875, 150, 100);
spawn.mapRect(5675, -1600, 350, 50);
spawn.mapRect(4325, -1300, 25, 200);
spawn.mapRect(3975, -2375, 75, 350);
spawn.mapRect(4250, -2375, 25, 550);
spawn.mapRect(2875, -2400, 75, 400);
spawn.mapRect(3050, -2425, 25, 700);
spawn.mapRect(2450, -2425, 75, 550);
spawn.mapRect(3375, -2375, 25, 525);
spawn.mapRect(3325, -1125, 75, 225);
spawn.mapRect(3125, -1200, 25, 200);
spawn.mapRect(2975, -1225, 75, 225);
spawn.mapRect(1875, -2425, 50, 550);
spawn.mapRect(1900, -1925, 475, 50);
spawn.mapRect(2300, -2400, 75, 475);
spawn.bodyRect(2025, -2325, 50, 50);
spawn.bodyRect(2150, -2300, 100, 100);
spawn.bodyRect(2025, -2325, 25, 100);
spawn.bodyRect(2125, -2275, 75, 75);
spawn.bodyRect(2250, -2250, 25, 50);
spawn.bodyRect(2000, -2325, 75, 100);
spawn.bodyRect(2150, -2300, 75, 100);
spawn.bodyRect(1975, -2300, 75, 75);
spawn.bodyRect(2150, -2300, 75, 75);
spawn.bodyRect(2025, -2350, 50, 125);
spawn.bodyRect(2250, -2325, 50, 75);
spawn.randomMob(2625, -750, 0);
spawn.randomMob(3200, -725, 0);
spawn.randomMob(2900, -575, 0);
spawn.randomMob(700, -1100, 0);
spawn.randomMob(3275, -1575, 0);
spawn.randomMob(3950, -1500, 0);
spawn.randomMob(3725, -1300, 0);
spawn.randomMob(3625, -1700, 0);
spawn.randomMob(2250, -1675, 0);
spawn.randomMob(550, -1875, 0);
spawn.randomMob(1600, -700, 0);
spawn.randomMob(1050, -400, 0);
spawn.randomSmallMob(1085, -1591);
spawn.randomSmallMob(1516, -532);
spawn.randomGroup(1551, -466, 0.4);
if (simulation.difficulty > 1) spawn.randomLevelBoss(3928, -655);
spawn.secondaryBossChance(4088, -1744)
level.custom = () => {
level.exit.drawAndCheck();
level.enter.draw();
};
},
// ********************************************************************************************************
// ********************************************************************************************************
// ***************************************** training levels **********************************************

View File

@@ -1193,6 +1193,11 @@ const mobs = {
this.alive = false; //triggers mob removal in mob[i].replace(i)
if (this.isDropPowerUp) {
// if (true) {
// //killing a mob heals for the last damage you took
// }
if (this.isSoonZombie) { //spawn zombie on death
this.leaveBody = false;
let count = 5 //delay spawn cycles

View File

@@ -568,8 +568,8 @@ 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) dmg *= 0.25
if (tech.isNeutronium && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.1
if (tech.isHarmReduce && input.field) dmg *= 0.15
if (tech.isNeutronium && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.05
if (tech.isBotArmor) dmg *= 0.94 ** b.totalBots()
if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.33;
if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.3
@@ -2043,7 +2043,9 @@ const m = {
}
},
setFieldRegen() {
if (m.fieldMode === 6) {
if (m.fieldMode === 0) {
m.fieldRegen = 0.00067 //4 energy per second for field emitter
} else if (m.fieldMode === 6) {
m.fieldRegen = 0.002 //12 energy per second for time dilation
} else if (m.fieldMode === 2) {
m.fieldRegen = 0.000833 //5 energy per second perfect dia
@@ -2636,7 +2638,7 @@ const m = {
name: "field emitter",
imageNumber: Math.floor(Math.random() * 23),
description: `<em>initial field</em><br>use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs and <strong>throw</strong> <strong class='color-block'>blocks</strong>
<br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second`, // <br><strong>100</strong> max <strong class='color-f'>energy</strong>
<br>generate <strong>4</strong> <strong class='color-f'>energy</strong> per second`, // <br><strong>100</strong> max <strong class='color-f'>energy</strong>
effect: () => {
m.hold = function () {
if (m.isHolding) {
@@ -4957,7 +4959,7 @@ const m = {
effect: () => {
m.fieldFire = true;
// m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping
m.fieldMeterColor = "#333"
// m.fieldMeterColor = "#789"//"#456"
m.eyeFillColor = m.fieldMeterColor
m.grabPowerUpRange2 = 300000 //m.grabPowerUpRange2 = 200000;
// m.fieldHarmReduction = 0.45; //55% reduction

View File

@@ -621,7 +621,7 @@ const powerUps = {
return 17;
},
effect() {
const couplingExtraAmmo = m.fieldMode === 10 ? 1 + 0.04 * m.coupling : 1
const couplingExtraAmmo = (m.fieldMode === 10 || m.fieldMode === 0) ? 1 + 0.04 * m.coupling : 1
if (b.inventory.length > 0) {
powerUps.animatePowerUpGrab('rgba(68, 102, 119,0.25)')
if (tech.isAmmoForGun && b.activeGun !== null) { //give extra ammo to one gun only with tech logistics

View File

@@ -7236,6 +7236,7 @@ const spawn = {
m.walk_cycle += m.flipLegs * m.Vx //makes the legs look like they are moving fast
// if (simulation.fpsCap > 999){}
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
ctx.fillStyle = "#fff";

View File

@@ -218,7 +218,7 @@ const tech = {
}
},
hasExplosiveDamageCheck() {
return tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isBoomBotUpgrade || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb)
return tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isBoomBotUpgrade || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.isHookExplosion
},
damage: 1, //used for tech changes to player damage that don't have complex conditions
damageFromTech() {
@@ -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.75 : 2
if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.85 : 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
@@ -2047,9 +2047,9 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
return m.fieldMode !== 9 && !tech.isTokamak
return m.fieldMode !== 9 && !tech.isTokamak && !tech.isReel
},
requires: "not wormhole, tokamak",
requires: "not wormhole, reel, tokamak",
effect() {
tech.blockDamage = 0.3
},
@@ -5670,7 +5670,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return !tech.isImmuneExplosion && (build.isExperimentSelection || powerUps.research.count > 1) && (tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb))
return !tech.isImmuneExplosion && (build.isExperimentSelection || powerUps.research.count > 1) && (tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || tech.isHookExplosion || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb))
},
requires: "an explosive damage source, not rocket propelled grenade",
effect() {
@@ -6780,7 +6780,7 @@ const tech = {
name: "capacitor bank",
// description: "<strong>charge</strong> effects build up almost <strong>instantly</strong><br><em style = 'font-size:97%;'>throwing <strong class='color-block'>blocks</strong>, foam, railgun, pulse, tokamak</em>",
descriptionFunction() {
return `<strong>charge</strong> effects build up almost <strong>instantly</strong><br><em style = 'font-size:93%;'>throwing, ${tech.haveGunCheck("foam", false) ? "<strong>foam</strong>" : "foam"}, ${tech.isPlasmaBall ? "<strong>plasma ball</strong>" : "plasma ball"}, ${tech.isRailGun ? "<strong>railgun</strong>" : "railgun"}, ${tech.isPulseLaser ? "<strong>pulse</strong>" : "pulse"}, ${tech.isTokamak ? "<strong>tokamak</strong>" : "tokamak"}</em>`
return `<strong>charge</strong> effects build up almost <strong>instantly</strong><br><em style = 'font-size:93%;'><strong class='color-block'>blocks</strong>, ${tech.haveGunCheck("foam", false) ? "<strong>foam</strong>" : "foam"}, ${tech.isPlasmaBall ? "<strong>plasma ball</strong>" : "plasma ball"}, ${tech.isRailGun ? "<strong>railgun</strong>" : "railgun"}, ${tech.isPulseLaser ? "<strong>pulse</strong>" : "pulse"}, ${tech.isTokamak ? "<strong>tokamak</strong>" : "tokamak"}</em>`
},
isGunTech: true,
maxCount: 1,
@@ -6917,6 +6917,25 @@ const tech = {
tech.isRailEnergy = false;
}
},
{
name: "autonomous defense",
description: "if you <strong>collide</strong> with a <strong>mob</strong><br>fire <strong>harpoons</strong> at nearby <strong>mobs</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("harpoon")
},
requires: "harpoon",
effect() {
tech.isHarpoonDefense = true
},
remove() {
tech.isHarpoonDefense = false
}
},
{
name: "Bessemer process",
descriptionFunction() {
@@ -7718,7 +7737,7 @@ const tech = {
},
{
name: "neutronium",
description: `<strong>move</strong> and <strong>jump</strong> <strong>20%</strong> <strong>slower</strong><br>if your <strong class='color-f'>field</strong> is active <strong>+90%</strong> <strong class='color-defense'>defense</strong>`,
description: `<strong>move</strong> and <strong>jump</strong> <strong>20%</strong> <strong>slower</strong><br>if your <strong class='color-f'>field</strong> is active <strong>+95%</strong> <strong class='color-defense'>defense</strong>`,
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -7746,7 +7765,7 @@ const tech = {
},
{
name: "aerostat",
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>`,
description: `<strong>+100%</strong> <strong class='color-d'>damage</strong> while <strong>off</strong> the <strong>ground</strong><br><strong>-15%</strong> <strong class='color-d'>damage</strong> while <strong>on</strong> the <strong>ground</strong>`,
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -8102,9 +8121,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return (m.fieldMode === 5 || m.fieldMode === 4) && !tech.isPrinter
return (m.fieldMode === 5 || m.fieldMode === 4 || m.fieldMode === 10) && !tech.isPrinter && !tech.isReel
},
requires: "plasma torch, molecular assembler, not printer",
requires: "plasma torch, molecular assembler, grappling hook, not printer, reel",
effect() {
tech.isTokamak = true;
},
@@ -8114,7 +8133,7 @@ const tech = {
},
{
name: "degenerate matter",
description: "if your <strong class='color-f'>field</strong> is active<br><strong>+75%</strong> <strong class='color-defense'>defense</strong>",
description: "if your <strong class='color-f'>field</strong> is active<br><strong>+85%</strong> <strong class='color-defense'>defense</strong>",
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -8755,7 +8774,7 @@ const tech = {
}
},
{
name: "autonomous defense",
name: "CIWS",
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,
@@ -8792,8 +8811,29 @@ const tech = {
tech.isHookExplosion = false
}
},
{
name: "reel",
description: "<strong>+400%</strong> <strong class='color-block'>block</strong> collision <strong class='color-d'>damage</strong><br><strong>+30</strong> <strong class='color-f'>energy</strong> when reeling in far away <strong class='color-block'>blocks</strong>",
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return m.fieldMode === 10 && !tech.isTokamak && tech.blockDamage === 0.075
},
requires: "not mass driver",
effect() {
tech.blockDamage = 0.375
tech.isReel = true
},
remove() {
tech.blockDamage = 0.075
tech.isReel = false
}
},
// {
// name: "autonomous defense",
// name: "CIWS",
// description: "if you <strong>collide</strong> with a mob<br>fire <strong>harpoons</strong> at nearby mobs",
// isFieldTech: true,
// maxCount: 1,
@@ -11879,4 +11919,6 @@ const tech = {
// isHookWire: null,
isHookDefense: null,
isHookExplosion: null,
isHarpoonDefense: null,
isReel: null,
}

View File

@@ -1,27 +1,33 @@
******************************************************** NEXT PATCH **************************************************
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
new community level shipwreck by 3xionDev
negative mass field has horizontal block motion by default
fixed tech sorting by "allowed tech" in experiment mode
grappling hook
tech: reel - increase block damage 400%, generate 30 energy after hooking blocks
added tokamak to grappling hook
updated rope graphics
added input.up to adjust positioning while hook is attached
added images for CIWS, rupture, autonomous defense
aerostat: 25->15% reduced damage on ground
rupture unlocks explosive tech
rupture destroys blocks
autonomous defense renamed to CIWS
field emitter 6->4 base energy regen
tech: autonomous defense - harpoon tech that fires harpoons after taking damage
degenerate matter: 75->85% defense while field is active
neutronium: 90->95% defense while field is active
unified field theory no longer has field emitter as an option
*********************************************************** TODO *****************************************************
grappling hook is a field
player got stuck inside block that wasn't pick up able
grappling hook field
check for places that the player could get into but not out of
field tech ideas
hook and line stuns?
increase hook damage
hook damage aura
hook's line does damage
Buoyancy - aerostat, but for defense: +70% defense while off the ground
too similar to degenerate matter
generate ___ after destroying blocks
energy, drones, iceIX, explosion, nails, junk bots?
@@ -30,6 +36,10 @@ tech - killing a mob heals for the last damage you took
heal for 50%?
heal from mob damage or from kills?
on sucker mob death trigger radiation damage AoE and a graphic (Hawking radiation)
tech prismatic laser - cycles between different laser colors every 1-2 seconds
make phonon the default wave gun type and make a tech to switch to the normal wave beam
nerf phonon, buff wave
@@ -1095,6 +1105,7 @@ add sounds
******************************************************** LORE ********************************************************
possible names for tech
sidereal - with respect to the stars (an extra rotation for time keeping)
strange loop
holonomy - parallel transport of a vector leads to movement (applies to curved space)
hypergolic - A hypergolic propellant combination used in a rocket engine is one whose components spontaneously ignite when they come into contact with each other.