harpoon
new gun harpoon
tech: filament - harpoon rope gets 1% longer for every harpoon ammo in your inventory
tech: unaaq - harpoon gets 1% longer for every harpoon ammo in your inventory
harpoon is pretty unbalanced, but I'm pushing it out so ya'll can let me know how I should balance it
more harpoon tech to come
2+ harpoons out at once
hold fire to extend rope longer
improved targeting: so it can hit the same target a few times
tech: controlled explosion - explosions shrink to prevent them from hitting you, cost 3 research
JUNK tech: true colors - set all power ups to their real world colors (just makes random colors)
This commit is contained in:
256
js/bullet.js
256
js/bullet.js
@@ -311,6 +311,9 @@ const b = {
|
||||
},
|
||||
explosion(where, radius, color = "rgba(255,25,0,0.6)") { // typically explode is used for some bullets with .onEnd
|
||||
radius *= tech.explosiveRadius
|
||||
|
||||
// radius = Math.max(0, Math.min(radius, (distanceToPlayer - 70) / b.explosionRange()))
|
||||
|
||||
let dist, sub, knock;
|
||||
let dmg = radius * 0.017 * (tech.isExplosionStun ? 0.7 : 1); //* 0.013 * (tech.isExplosionStun ? 0.7 : 1);
|
||||
if (tech.isExplosionHarm) radius *= 1.8 // 1/sqrt(2) radius -> area
|
||||
@@ -322,6 +325,7 @@ const b = {
|
||||
|
||||
if (tech.isExplodeRadio) { //radiation explosion
|
||||
radius *= 1.25; //alert range
|
||||
if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1)
|
||||
color = "rgba(25,139,170,0.25)"
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: where.x,
|
||||
@@ -359,6 +363,7 @@ const b = {
|
||||
}
|
||||
}
|
||||
} else { //normal explosions
|
||||
if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1)
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: where.x,
|
||||
y: where.y,
|
||||
@@ -1103,6 +1108,185 @@ const b = {
|
||||
b.grenade = grenadeDefault
|
||||
}
|
||||
},
|
||||
harpoon(where, target, scale = 1, isReturn = false, ropeLength = 15, speed = 0) {
|
||||
const me = bullet.length;
|
||||
let vector = "-40 2 -40 -2 30 -2 50 0 30 2"
|
||||
if (scale !== 1) vector = `${-40*scale} 2 ${-40*scale} -2 ${30*scale} -2 ${50*scale} 0 ${30*scale} 2`
|
||||
bullet[me] = Bodies.fromVertices(where.x, where.y, Vertices.fromPath(vector), {
|
||||
// bullet[me] = Bodies.rectangle(where.x, where.y, 70 * size, 4.5 * size, {
|
||||
cycle: 0,
|
||||
angle: m.angle,
|
||||
friction: 1,
|
||||
frictionAir: 0.4,
|
||||
thrustMag: 0.1,
|
||||
turnRate: isReturn ? 0.1 : 0.03, //0.015
|
||||
drawStringControlMagnitude: 3000 + 5000 * Math.random(),
|
||||
drawStringFlip: (Math.round(Math.random()) ? 1 : -1),
|
||||
dmg: 0, //damage done in addition to the damage from momentum
|
||||
classType: "bullet",
|
||||
endCycle: simulation.cycle + 50,
|
||||
collisionFilter: {
|
||||
category: cat.bullet,
|
||||
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
|
||||
},
|
||||
minDmgSpeed: 0,
|
||||
lookFrequency: Math.floor(7 + Math.random() * 3),
|
||||
density: 0.005, //0.001 is normal
|
||||
beforeDmg(who) {
|
||||
if (!who.isBadTarget) {
|
||||
if (tech.fragments) {
|
||||
b.targetedNail(this.position, tech.fragments * 5)
|
||||
} else if (isReturn) {
|
||||
this.do = this.returnToPlayer
|
||||
} else {
|
||||
this.frictionAir = 0.01
|
||||
this.do = () => {
|
||||
this.force.y += this.mass * 0.003; //gravity
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
onEnd() {},
|
||||
drawString() {
|
||||
if (isReturn) {
|
||||
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 perpendicular = Vector.mult(Vector.normalise(Vector.perp(sub)), this.drawStringFlip * Math.min(80, 10 + this.drawStringControlMagnitude / (10 + Vector.magnitude(sub))))
|
||||
const controlPoint = Vector.add(Vector.add(where, Vector.mult(sub, -0.5)), perpendicular)
|
||||
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();
|
||||
|
||||
if (m.energy > 0.003) m.energy -= 0.003
|
||||
}
|
||||
},
|
||||
returnToPlayer() {
|
||||
if (Vector.magnitude(Vector.sub(this.position, m.pos)) < 100) { //near player
|
||||
this.endCycle = 0;
|
||||
if (m.cycle + 25 * b.fireCDscale < m.fireCDcycle) m.fireCDcycle = m.cycle + 25 * b.fireCDscale
|
||||
//recoil on catching
|
||||
const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), this.mass * (m.crouch ? 0.0001 : 0.0002))
|
||||
player.force.x += momentum.x
|
||||
player.force.y += momentum.y
|
||||
// refund ammo
|
||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||
if (b.guns[i].name === "harpoon") {
|
||||
b.guns[i].ammo++;
|
||||
simulation.updateGunHUD();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if you grabbed a power up, stop it near the player
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) { //near power up
|
||||
if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 6000) {
|
||||
Matter.Body.setVelocity(powerUp[i], { x: 0, y: 0 })
|
||||
// Matter.Body.setPosition(powerUp[i], this.position)
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) { //near power up
|
||||
if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 3000) {
|
||||
Matter.Body.setVelocity(powerUp[i], this.velocity)
|
||||
Matter.Body.setPosition(powerUp[i], this.position)
|
||||
break
|
||||
}
|
||||
}
|
||||
const returnForce = Vector.mult(Vector.normalise(Vector.sub(this.position, m.pos)), this.thrustMag * this.mass)
|
||||
this.force.x -= returnForce.x
|
||||
this.force.y -= returnForce.y
|
||||
this.drawString()
|
||||
}
|
||||
},
|
||||
do() {
|
||||
if (!m.isBodiesAsleep) {
|
||||
this.cycle++
|
||||
if (isReturn && this.cycle > ropeLength) {
|
||||
if (m.energy < 0.05) { //snap rope if not enough energy
|
||||
const returnForce = Vector.mult(Vector.normalise(Vector.sub(this.position, m.pos)), 3 * this.thrustMag * this.mass)
|
||||
this.force.x -= returnForce.x
|
||||
this.force.y -= returnForce.y
|
||||
this.frictionAir = 0.003
|
||||
this.do = () => {
|
||||
this.force.y += this.mass * 0.003; //gravity
|
||||
}
|
||||
} else { //return to player
|
||||
this.do = this.returnToPlayer
|
||||
if (this.angularSpeed < 0.5) this.torque += this.inertia * 0.001 * (Math.random() - 0.5) //(Math.round(Math.random()) ? 1 : -1)
|
||||
this.collisionFilter.mask = cat.map | cat.mob | cat.mobBullet | cat.mobShield // | cat.body
|
||||
}
|
||||
}
|
||||
if (this.cycle > 30) {
|
||||
this.frictionAir = 0.003
|
||||
this.do = () => {
|
||||
this.force.y += this.mass * 0.003; //gravity
|
||||
}
|
||||
}
|
||||
|
||||
if (target) { //rotate missile towards the target
|
||||
const face = {
|
||||
x: Math.cos(this.angle),
|
||||
y: Math.sin(this.angle)
|
||||
};
|
||||
const vectorGoal = Vector.normalise(Vector.sub(this.position, target.position));
|
||||
if (Vector.cross(vectorGoal, face) > 0) {
|
||||
Matter.Body.rotate(this, this.turnRate);
|
||||
} else {
|
||||
Matter.Body.rotate(this, -this.turnRate);
|
||||
}
|
||||
}
|
||||
// else if (!(this.cycle % 2)) { //look for a target if you don't have one
|
||||
// simulation.drawList.push({ //add dmg to draw queue
|
||||
// x: this.position.x,
|
||||
// y: this.position.y,
|
||||
// radius: 10,
|
||||
// color: simulation.mobDmgColor,
|
||||
// time: simulation.drawTime
|
||||
// });
|
||||
// let closest = {
|
||||
// distance: 2000,
|
||||
// target: null
|
||||
// }
|
||||
// const dir = Vector.normalise(this.velocity) //make a vector for direction of length 1
|
||||
// for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
// if (
|
||||
// mob[i].alive && !mob[i].isBadTarget &&
|
||||
// Matter.Query.ray(map, this.position, mob[i].position).length === 0 && //check for map in Line of sight
|
||||
// Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, this.position))) > 0.55 //the dot product of diff and dir will return how much over lap between the vectors
|
||||
// ) {
|
||||
// const dist = Vector.magnitude(Vector.sub(this.position, mob[i].position))
|
||||
// if (dist < closest.distance) {
|
||||
// closest.distance = dist
|
||||
// closest.target = mob[i]
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (closest.target) {
|
||||
// target = closest.target
|
||||
// this.turnRate = 0.05
|
||||
// this.frictionAir = 0.8
|
||||
// }
|
||||
// }
|
||||
this.force.x += this.thrustMag * this.mass * Math.cos(this.angle);
|
||||
this.force.y += this.thrustMag * this.mass * Math.sin(this.angle);
|
||||
}
|
||||
this.drawString()
|
||||
},
|
||||
});
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: m.Vx / 2 + speed * Math.cos(bullet[me].angle),
|
||||
y: m.Vy / 2 + speed * Math.sin(bullet[me].angle)
|
||||
});
|
||||
Composite.add(engine.world, bullet[me]); //add bullet to world
|
||||
},
|
||||
missile(where, angle, speed, size = 1) {
|
||||
if (tech.missileSize) size *= 1.5
|
||||
const me = bullet.length;
|
||||
@@ -1438,12 +1622,12 @@ const b = {
|
||||
const reflectivity = 1 - 1 / (reflections * 1.5)
|
||||
let damage = b.dmgScale * dmg
|
||||
let best = {
|
||||
x: null,
|
||||
y: null,
|
||||
x: 1,
|
||||
y: 1,
|
||||
dist2: Infinity,
|
||||
who: null,
|
||||
v1: null,
|
||||
v2: null
|
||||
v1: 1,
|
||||
v2: 1
|
||||
};
|
||||
const path = [{
|
||||
x: where.x,
|
||||
@@ -1497,12 +1681,12 @@ const b = {
|
||||
|
||||
const checkForCollisions = function() {
|
||||
best = {
|
||||
x: null,
|
||||
y: null,
|
||||
x: 1,
|
||||
y: 1,
|
||||
dist2: Infinity,
|
||||
who: null,
|
||||
v1: null,
|
||||
v2: null
|
||||
v1: 1,
|
||||
v2: 1
|
||||
};
|
||||
vertexCollision(path[path.length - 2], path[path.length - 1], mob);
|
||||
vertexCollision(path[path.length - 2], path[path.length - 1], map);
|
||||
@@ -4436,13 +4620,11 @@ const b = {
|
||||
ammoPack: 4,
|
||||
have: false,
|
||||
fireCycle: 0,
|
||||
ammoLoaded: 0,
|
||||
do() {},
|
||||
fire() {
|
||||
const countReduction = Math.pow(0.9, tech.missileCount)
|
||||
if (m.crouch) {
|
||||
m.fireCDcycle = m.cycle + 10 * b.fireCDscale / countReduction; // cool down
|
||||
|
||||
// for (let i = 0; i < tech.missileCount; i++) {
|
||||
// b.missile(where, -Math.PI / 2 + 0.2 * (Math.random() - 0.5) * Math.sqrt(tech.missileCount), -2, Math.sqrt(countReduction))
|
||||
// bullet[bullet.length - 1].force.x += 0.004 * countReduction * (i - (tech.missileCount - 1) / 2);
|
||||
@@ -4818,7 +5000,59 @@ const b = {
|
||||
this.charge++
|
||||
m.fireCDcycle = m.cycle + Math.floor((1 + 0.35 * this.charge) * b.fireCDscale);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: "harpoon",
|
||||
description: "fire a <strong>self-steering</strong> harpoon that uses <strong class='color-f'>energy</strong><br>to <strong>retract</strong> and refund its <strong class='color-ammo'>ammo</strong> cost",
|
||||
ammo: 0,
|
||||
ammoPack: 1,
|
||||
have: false,
|
||||
fireCycle: 0,
|
||||
do() {},
|
||||
fire() {
|
||||
const where = {
|
||||
x: m.pos.x + 30 * Math.cos(m.angle),
|
||||
y: m.pos.y + 30 * Math.sin(m.angle)
|
||||
}
|
||||
const closest = {
|
||||
distance: 10000,
|
||||
target: null
|
||||
}
|
||||
//look for closest mob in player's LoS
|
||||
const dir = { x: Math.cos(m.angle), y: Math.sin(m.angle) }; //make a vector for the player's direction of length 1
|
||||
if (m.crouch) {
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, m.pos, mob[i].position).length === 0) {
|
||||
const dot = Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, m.pos))) //the dot product of diff and dir will return how much over lap between the vectors
|
||||
const dist = Vector.magnitude(Vector.sub(where, mob[i].position))
|
||||
if (dist < closest.distance && dot > 0.95 && dist * dot * dot * dot * dot > 880) { //target closest mob that player is looking at and isn't too close to target
|
||||
closest.distance = dist
|
||||
closest.target = mob[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
b.harpoon(where, closest.target, 1 + tech.isLargeHarpoon * this.ammo / 100, false)
|
||||
m.fireCDcycle = m.cycle + 50 * b.fireCDscale; // cool down
|
||||
} else {
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, m.pos, mob[i].position).length === 0) {
|
||||
const dot = Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, m.pos))) //the dot product of diff and dir will return how much over lap between the vectors
|
||||
const dist = Vector.magnitude(Vector.sub(where, mob[i].position))
|
||||
if (dist < closest.distance && dot > 0.95) { //target closest mob that player is looking at and isn't too close to target
|
||||
closest.distance = dist
|
||||
closest.target = mob[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
b.harpoon(where, closest.target, 1 + tech.isLargeHarpoon * this.ammo / 100, true, (m.crouch ? 10 : 8) * (tech.isFilament ? 1 + this.ammo / 100 : 1))
|
||||
m.fireCDcycle = m.cycle + 180 //Infinity; // cool down
|
||||
}
|
||||
const recoil = Vector.mult(Vector.normalise(Vector.sub(where, m.pos)), m.crouch ? 0.015 : 0.035)
|
||||
player.force.x -= recoil.x
|
||||
player.force.y -= recoil.y
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "rail gun",
|
||||
description: "use <strong class='color-f'>energy</strong> to launch a high-speed <strong>dense</strong> rod<br><strong>hold</strong> left mouse to charge, <strong>release</strong> to fire",
|
||||
ammo: 0,
|
||||
|
||||
12
js/level.js
12
js/level.js
@@ -15,8 +15,8 @@ const level = {
|
||||
// localSettings.levelsClearedLastGame = 10
|
||||
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
|
||||
// simulation.isHorizontalFlipped = true
|
||||
// m.setField("metamaterial cloaking")
|
||||
// b.giveGuns("spores")
|
||||
// m.setField("time dilation")
|
||||
// b.giveGuns("harpoon")
|
||||
// tech.giveTech("nematodes")
|
||||
// tech.giveTech("necrophage")
|
||||
// for (let i = 0; i < 3; i++) tech.giveTech("super sized")
|
||||
@@ -2273,7 +2273,7 @@ const level = {
|
||||
spawn.mapRect(4850, -275, 50, 175);
|
||||
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
|
||||
// spawn.starter(1900, -500, 200) //big boy
|
||||
spawn.blockBoss(1900, -500)
|
||||
// spawn.blockGroup(1900, -500)
|
||||
// for (let i = 0; i < 10; ++i) spawn.bodyRect(1600 + 5, -500, 30, 40);
|
||||
// spawn.laserBombingBoss(1900, -500)
|
||||
// for (let i = 0; i < 5; i++) spawn.focuser(1900, -500)
|
||||
@@ -2295,7 +2295,11 @@ const level = {
|
||||
// spawn.laserTargetingBoss(1600, -500)
|
||||
// spawn.striker(1200, -500)
|
||||
|
||||
// spawn.nodeGroup(1200, -500, "grenadier")
|
||||
spawn.nodeGroup(1200, -500, "grenadier")
|
||||
// spawn.nodeGroup(1800, -500, "grenadier")
|
||||
// spawn.nodeGroup(1200, 0, "grenadier")
|
||||
|
||||
|
||||
// spawn.snakeBoss(1200, -500)
|
||||
// spawn.suckerBoss(2900, -500)
|
||||
// spawn.randomMob(1600, -500)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//main object for spawning things in a level
|
||||
const spawn = {
|
||||
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture", "growBossCulture"],
|
||||
randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", "snakeSpitBoss", "laserBombingBoss", "blockBoss", "blockBoss"]) {
|
||||
randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", "snakeSpitBoss", "laserBombingBoss", "blockBoss"]) {
|
||||
// other bosses: suckerBoss, laserBoss, tetherBoss, //these need a particular level to work so they are not included in the random pool
|
||||
spawn[options[Math.floor(Math.random() * options.length)]](x, y)
|
||||
},
|
||||
@@ -696,11 +696,13 @@ const spawn = {
|
||||
me.groupingStrength = 0.0005
|
||||
me.memory = 200;
|
||||
me.isGrouper = true;
|
||||
me.seeAtDistance2 = 600 * 600
|
||||
me.seePlayerFreq = Math.floor(50 + 50 * Math.random())
|
||||
me.do = function() {
|
||||
this.gravity();
|
||||
this.checkStatus();
|
||||
if (this.seePlayer.recall) {
|
||||
this.seePlayerCheck();
|
||||
if (this.seePlayer.recall) {
|
||||
this.attraction();
|
||||
//tether to other blocks
|
||||
ctx.beginPath();
|
||||
|
||||
172
js/tech.js
172
js/tech.js
@@ -864,6 +864,28 @@
|
||||
tech.isExplosionStun = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "controlled explosion",
|
||||
description: `use ${powerUps.orb.research(3)} to dynamically <strong>reduce</strong> all<br><strong class='color-e'>explosions</strong> until they do no <strong class='color-harm'>harm</strong>`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return !tech.isImmuneExplosion && (build.isExperimentSelection || powerUps.research.count > 2) && (tech.haveGunCheck("missiles") || tech.isMissileField || tech.missileBotCount > 0 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb))
|
||||
},
|
||||
requires: "an explosive damage source, not electric reactive armor",
|
||||
effect: () => {
|
||||
tech.isSmartRadius = true;
|
||||
for (let i = 0; i < 3; i++) {
|
||||
if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
|
||||
}
|
||||
},
|
||||
remove() {
|
||||
tech.isSmartRadius = false;
|
||||
if (this.count > 0) powerUps.research.changeRerolls(3)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "electric reactive armor",
|
||||
// description: "<strong class='color-e'>explosions</strong> do no <strong class='color-harm'>harm</strong><br> while your <strong class='color-f'>energy</strong> is above <strong>98%</strong>",
|
||||
@@ -873,7 +895,7 @@
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck()
|
||||
return !tech.isSmartRadius && !tech.isExplodeRadio && tech.hasExplosiveDamageCheck()
|
||||
},
|
||||
requires: "an explosive damage source, not iridium-192",
|
||||
effect: () => {
|
||||
@@ -903,15 +925,15 @@
|
||||
},
|
||||
{
|
||||
name: "fragmentation",
|
||||
description: "some <strong class='color-e'>detonations</strong> and collisions eject <strong>nails</strong><br><em style = 'font-size: 90%'>blocks, rail gun, grenades, missiles, shotgun slugs</em>",
|
||||
description: "some <strong class='color-e'>detonations</strong> and collisions eject <strong>nails</strong><br><em style = 'font-size: 90%'>blocks, rail gun, grenades, missiles, slugs, harpoon</em>",
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || tech.missileBotCount || tech.haveGunCheck("rail gun") || (tech.haveGunCheck("shotgun") && tech.isSlugShot) || tech.throwChargeRate > 1
|
||||
return tech.haveGunCheck("harpoon") || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || tech.missileBotCount || tech.haveGunCheck("rail gun") || (tech.haveGunCheck("shotgun") && tech.isSlugShot) || tech.throwChargeRate > 1
|
||||
},
|
||||
requires: "grenades, missiles, rail gun, shotgun slugs, or mass driver",
|
||||
requires: "grenades, missiles, rail gun, shotgun slugs, harpoon, or mass driver",
|
||||
effect() {
|
||||
tech.fragments++
|
||||
},
|
||||
@@ -3881,7 +3903,6 @@
|
||||
if (b.guns[i].name === "shotgun") {
|
||||
b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 0.5);
|
||||
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * 0.5
|
||||
simulation.makeGunHUD();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3894,10 +3915,10 @@
|
||||
if (b.guns[i].name === "shotgun") {
|
||||
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack;
|
||||
b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 2);
|
||||
simulation.makeGunHUD();
|
||||
break;
|
||||
}
|
||||
}
|
||||
simulation.updateGunHUD();
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4954,6 +4975,63 @@
|
||||
tech.isAmmoFoamSize = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "filament",
|
||||
description: "increase the <strong>length</strong> of your <strong>harpoon</strong>'s <strong>rope</strong><br>by <strong>1%</strong> per harpoon <strong class='color-ammo'>ammo</strong>",
|
||||
isGunTech: true,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return tech.haveGunCheck("harpoon")
|
||||
},
|
||||
requires: "harpoon, not spear",
|
||||
effect() {
|
||||
tech.isFilament = true;
|
||||
},
|
||||
remove() {
|
||||
tech.isFilament = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "unaaq",
|
||||
description: "increase the <strong>length</strong> of your <strong>harpoon</strong><br>by <strong>1%</strong> per harpoon <strong class='color-ammo'>ammo</strong>",
|
||||
isGunTech: true,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return tech.haveGunCheck("harpoon")
|
||||
},
|
||||
requires: "harpoon",
|
||||
effect() {
|
||||
tech.isLargeHarpoon = true;
|
||||
},
|
||||
remove() {
|
||||
tech.isLargeHarpoon = false;
|
||||
}
|
||||
},
|
||||
// {
|
||||
// name: "spear",
|
||||
// description: "<strong>harpoons</strong> fired while <strong>crouched</strong><br>have no <strong>rope</strong> and improved <strong>steering</strong>",
|
||||
// isGunTech: true,
|
||||
// maxCount: 1,
|
||||
// count: 0,
|
||||
// frequency: 2,
|
||||
// frequencyDefault: 2,
|
||||
// allowed() {
|
||||
// return tech.haveGunCheck("harpoon") && !tech.isFilament
|
||||
// },
|
||||
// requires: "harpoon, not filament",
|
||||
// effect() {
|
||||
// tech.isSpear = true;
|
||||
// },
|
||||
// remove() {
|
||||
// tech.isSpear = false;
|
||||
// }
|
||||
// },
|
||||
{
|
||||
name: "half-wave rectifier",
|
||||
description: "charging the <strong>rail gun</strong> gives you <strong class='color-f'>energy</strong><br><em>instead of draining it</em>",
|
||||
@@ -6355,6 +6433,82 @@
|
||||
// },
|
||||
// remove() {}
|
||||
// },
|
||||
{
|
||||
name: "true colors",
|
||||
description: `set all power ups to their real world colors`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 0,
|
||||
isExperimentHide: true,
|
||||
isJunk: true,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
effect() {
|
||||
// const colors = shuffle(["#f7b", "#0eb", "#467", "#0cf", "hsl(246,100%,77%)", "#26a"])
|
||||
const colors = shuffle([powerUps.research.color, powerUps.heal.color, powerUps.ammo.color, powerUps.ammo.color, powerUps.field.color, powerUps.gun.color])
|
||||
powerUps.research.color = colors[0]
|
||||
powerUps.heal.color = colors[1]
|
||||
powerUps.ammo.color = colors[2]
|
||||
powerUps.field.color = colors[3]
|
||||
powerUps.tech.color = colors[4]
|
||||
powerUps.gun.color = colors[5]
|
||||
for (let i = 0; i < powerUp.length; i++) {
|
||||
switch (powerUp[i].name) {
|
||||
case "research":
|
||||
powerUp[i].color = colors[0]
|
||||
break;
|
||||
case "heal":
|
||||
powerUp[i].color = colors[1]
|
||||
break;
|
||||
case "ammo":
|
||||
powerUp[i].color = colors[2]
|
||||
break;
|
||||
case "field":
|
||||
powerUp[i].color = colors[3]
|
||||
break;
|
||||
case "tech":
|
||||
powerUp[i].color = colors[4]
|
||||
break;
|
||||
case "gun":
|
||||
powerUp[i].color = colors[5]
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
remove() {
|
||||
const colors = ["#f7b", "#0eb", "#467", "#0cf", "hsl(246,100%,77%)", "#26a"] //no shuffle
|
||||
powerUps.research.color = colors[0]
|
||||
powerUps.heal.color = colors[1]
|
||||
powerUps.ammo.color = colors[2]
|
||||
powerUps.field.color = colors[3]
|
||||
powerUps.tech.color = colors[4]
|
||||
powerUps.gun.color = colors[5]
|
||||
for (let i = 0; i < powerUp.length; i++) {
|
||||
switch (powerUp[i].name) {
|
||||
case "research":
|
||||
powerUp[i].color = colors[0]
|
||||
break;
|
||||
case "heal":
|
||||
powerUp[i].color = colors[1]
|
||||
break;
|
||||
case "ammo":
|
||||
powerUp[i].color = colors[2]
|
||||
break;
|
||||
case "field":
|
||||
powerUp[i].color = colors[3]
|
||||
break;
|
||||
case "tech":
|
||||
powerUp[i].color = colors[4]
|
||||
break;
|
||||
case "gun":
|
||||
powerUp[i].color = colors[5]
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "emergency broadcasting",
|
||||
description: "emit 2 sound sine waveforms at 853 Hz and 960 Hz<br><em>lower your volume</em>",
|
||||
@@ -7942,5 +8096,9 @@
|
||||
wormSurviveDmg: null,
|
||||
isExtraGunField: null,
|
||||
isBigField: null,
|
||||
isMineStun: null
|
||||
isMineStun: null,
|
||||
isSmartRadius: null,
|
||||
isFilament: null,
|
||||
// isSpear: null,
|
||||
isLargeHarpoon: null
|
||||
}
|
||||
57
todo.txt
57
todo.txt
@@ -1,22 +1,43 @@
|
||||
******************************************************** NEXT PATCH **************************************************
|
||||
|
||||
all explosions do 33% more damage to mobs
|
||||
and 75% more damage to player
|
||||
boom bot explosions are 16% smaller
|
||||
new gun harpoon
|
||||
tech: filament - harpoon rope gets 1% longer for every harpoon ammo in your inventory
|
||||
tech: unaaq - harpoon gets 1% longer for every harpoon ammo in your inventory
|
||||
harpoon is pretty unbalanced, but I'm pushing it out so ya'll can let me know how I should balance it
|
||||
more harpoon tech to come
|
||||
2+ harpoons out at once
|
||||
hold fire to extend rope longer
|
||||
improved targeting: so it can hit the same target a few times
|
||||
|
||||
laser-bot does 15% more damage
|
||||
missile bot fires 15% quicker
|
||||
tech: phase velocity also adds 15% wave damage (because it disables phonon is was a bad choice)
|
||||
many duplication tech add less duplication
|
||||
Maxwell's demon now requires current energy above your max to unlock
|
||||
tech: controlled explosion - explosions shrink to prevent them from hitting you, cost 3 research
|
||||
|
||||
power ups in the intro tube get pushed around a bit, this might stop them from sliding on the walls
|
||||
mines when they are stuck to walls no longer collide with blocks (to not block elevator)
|
||||
more bug fixes
|
||||
JUNK tech: true colors - set all power ups to their real world colors (just makes random colors)
|
||||
|
||||
******************************************************** TODO ********************************************************
|
||||
|
||||
JUNK tech: add a score to in game console every 10 seconds
|
||||
"Interstellar Disturbance": Cosmic String applies to mobs who cross the wormhole's path, even after initial wormholing, but at reduced damage and stun time.
|
||||
|
||||
disable zoom progress when paused
|
||||
|
||||
gun: harpoon
|
||||
if no target no thrust and no airfriction
|
||||
stuck in walls, and don't return ammo
|
||||
return to player is slower for heavier harpoons
|
||||
harpoon tech
|
||||
holding down fire lets the string extend farther,
|
||||
can't have 2+ harpoons
|
||||
it uses up ammo as extends, and returns it as it contracts?
|
||||
will this effect performance?
|
||||
fire 2+ harpoons at the same time but different angles
|
||||
2+ harpoons, with separate CDs
|
||||
can't have extended string?
|
||||
post launch tracking: more airFriction, more thrust, harder turning
|
||||
if no target found slow down and aim much better?
|
||||
tracking so good harpoon can hit a target, circle around and hit it again
|
||||
|
||||
level:lab too much walking around and too much platforming
|
||||
|
||||
set blockBoss frequency to 1x not 2x
|
||||
|
||||
tech - explode after getting hit, but while you are immune to harm
|
||||
|
||||
@@ -32,17 +53,6 @@ make a boss with a tail
|
||||
stabbers maybe
|
||||
suckers maybe
|
||||
|
||||
set blockBoss frequency to 1x not 3x
|
||||
|
||||
block groups should look for player, so the player doesn't step on them?
|
||||
remove heath bar?
|
||||
|
||||
fix simulation.CDScale // it's always zero so it does nothing
|
||||
some mobs can't see player...
|
||||
3 laser boss isn't rotating...
|
||||
it's always null
|
||||
you shouldn't of removes lookFrequency scale var...
|
||||
|
||||
tech remove all JUNK tech
|
||||
but you can't research
|
||||
maybe spend research
|
||||
@@ -436,6 +446,7 @@ level boss: fires a line intersection in a random direction every few seconds.
|
||||
******************************************************** LORE ********************************************************
|
||||
|
||||
possible names for tech
|
||||
astrophage
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user