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

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);
ctx.quadraticCurveTo(controlPoint.x, controlPoint.y, this.vertices[0].x, this.vertices[0].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()
this.pickUpTarget = blocks[i].bodyA
if (tech.isHookExplosion) b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end
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
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,
}