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:
landgreen
2021-09-11 08:02:09 -07:00
parent 7f3fb1c214
commit f7cd48c3ff
6 changed files with 456 additions and 47 deletions

View File

@@ -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,