slasher mob variants
new community training level diamagnetism by Richard0820 it's at the end of the training levels start training by click the top right button at the load screen slasher mob variant with 2 laser swords slasher mob variant with a laser spear suckerBoss pulls in powerUps and makes them orbit better shooterBoss fires faster and larger bullets wormhole 4 -> 5% duplication, and a 10% reduction in energy cost drones fire faster and aim more accurately quenching gives 10% more max health and harm snake tail mobs have 15% less health tungsten carbide properly gives 222 health in addition to the bonus max health
This commit is contained in:
48
js/bullet.js
48
js/bullet.js
@@ -2832,19 +2832,13 @@ const b = {
|
||||
}
|
||||
if (tech.isLaserPush) { //push mobs away
|
||||
const index = path.length - 1
|
||||
Matter.Body.setVelocity(best.who, {
|
||||
x: best.who.velocity.x * 0.97,
|
||||
y: best.who.velocity.y * 0.97
|
||||
});
|
||||
Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.97, y: best.who.velocity.y * 0.97 });
|
||||
const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.003 * push * Math.min(6, best.who.mass))
|
||||
Matter.Body.applyForce(best.who, path[index], force)
|
||||
}
|
||||
} else if (tech.isLaserPush && best.who.classType === "body") {
|
||||
const index = path.length - 1
|
||||
Matter.Body.setVelocity(best.who, {
|
||||
x: best.who.velocity.x * 0.97,
|
||||
y: best.who.velocity.y * 0.97
|
||||
});
|
||||
Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.97, y: best.who.velocity.y * 0.97 });
|
||||
const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.003 * push * Math.min(6, best.who.mass))
|
||||
Matter.Body.applyForce(best.who, path[index], force)
|
||||
}
|
||||
@@ -3679,7 +3673,7 @@ const b = {
|
||||
}, speed = 1) {
|
||||
const me = bullet.length;
|
||||
const THRUST = 0.0015
|
||||
const dir = m.angle + 0.4 * (Math.random() - 0.5);
|
||||
const dir = m.angle + 0.2 * (Math.random() - 0.5);
|
||||
const RADIUS = (4.5 + 3 * Math.random())
|
||||
bullet[me] = Bodies.polygon(where.x, where.y, 8, RADIUS, {
|
||||
angle: dir,
|
||||
@@ -3822,7 +3816,7 @@ const b = {
|
||||
!mob[i].isInvulnerable
|
||||
) {
|
||||
const TARGET_VECTOR = Vector.sub(this.position, mob[i].position)
|
||||
const DIST = Vector.magnitude(TARGET_VECTOR);
|
||||
const DIST = Vector.magnitude(TARGET_VECTOR)
|
||||
if (DIST < closeDist) {
|
||||
closeDist = DIST;
|
||||
this.lockedOn = mob[i]
|
||||
@@ -3931,18 +3925,12 @@ const b = {
|
||||
}
|
||||
// speed cap instead of friction to give more agility
|
||||
if (this.speed > 6) {
|
||||
Matter.Body.setVelocity(this, {
|
||||
x: this.velocity.x * 0.97,
|
||||
y: this.velocity.y * 0.97
|
||||
});
|
||||
Matter.Body.setVelocity(this, { x: this.velocity.x * 0.97, y: this.velocity.y * 0.97 });
|
||||
}
|
||||
}
|
||||
})
|
||||
Composite.add(engine.world, bullet[me]); //add bullet to world
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: speed * Math.cos(dir),
|
||||
y: speed * Math.sin(dir)
|
||||
});
|
||||
Matter.Body.setVelocity(bullet[me], { x: speed * Math.cos(dir), y: speed * Math.sin(dir) });
|
||||
},
|
||||
droneRadioactive(where = {
|
||||
x: m.pos.x + 30 * Math.cos(m.angle) + 20 * (Math.random() - 0.5),
|
||||
@@ -7732,7 +7720,7 @@ const b = {
|
||||
x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5),
|
||||
y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5)
|
||||
}, 45)
|
||||
m.fireCDcycle = m.cycle + Math.floor(50 * b.fireCDscale); // cool down
|
||||
m.fireCDcycle = m.cycle + Math.floor(45 * b.fireCDscale); // cool down
|
||||
} else {
|
||||
b.droneRadioactive({
|
||||
x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5),
|
||||
@@ -7743,16 +7731,16 @@ const b = {
|
||||
} else {
|
||||
if (m.crouch) {
|
||||
b.drone({
|
||||
x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5),
|
||||
y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5)
|
||||
}, 55)
|
||||
m.fireCDcycle = m.cycle + Math.floor(10 * b.fireCDscale); // cool down
|
||||
x: m.pos.x + 30 * Math.cos(m.angle) + 5 * (Math.random() - 0.5),
|
||||
y: m.pos.y + 30 * Math.sin(m.angle) + 5 * (Math.random() - 0.5)
|
||||
}, 50)
|
||||
m.fireCDcycle = m.cycle + Math.floor(7 * b.fireCDscale); // cool down
|
||||
} else {
|
||||
b.drone({
|
||||
x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5),
|
||||
y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5)
|
||||
}, 20)
|
||||
m.fireCDcycle = m.cycle + Math.floor(5 * b.fireCDscale); // cool down
|
||||
}, 15)
|
||||
m.fireCDcycle = m.cycle + Math.floor(4 * b.fireCDscale); // cool down
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7788,14 +7776,8 @@ const b = {
|
||||
const radius = 5 + 8 * Math.random() + (tech.isAmmoFoamSize && this.ammo < 300) * 12
|
||||
const SPEED = (m.crouch ? 1.2 : 1) * Math.max(2, 14 - radius * 0.25)
|
||||
const dir = m.angle + 0.15 * (Math.random() - 0.5)
|
||||
const velocity = {
|
||||
x: SPEED * Math.cos(dir),
|
||||
y: SPEED * Math.sin(dir)
|
||||
}
|
||||
const position = {
|
||||
x: m.pos.x + 30 * Math.cos(m.angle),
|
||||
y: m.pos.y + 30 * Math.sin(m.angle)
|
||||
}
|
||||
const velocity = { x: SPEED * Math.cos(dir), y: SPEED * Math.sin(dir) }
|
||||
const position = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
|
||||
b.foam(position, Vector.rotate(velocity, spread), radius)
|
||||
this.applyKnock(velocity)
|
||||
m.fireCDcycle = m.cycle + Math.floor(1.5 * b.fireCDscale);
|
||||
|
||||
1044
js/level.js
1044
js/level.js
File diff suppressed because it is too large
Load Diff
@@ -12,10 +12,12 @@ const mobs = {
|
||||
}
|
||||
}
|
||||
},
|
||||
draw() {
|
||||
draw() { },
|
||||
drawDefault() {
|
||||
ctx.lineWidth = 2;
|
||||
let i = mob.length;
|
||||
while (i--) {
|
||||
// if (Matter.Query.ray(map, mob[i].position, m.pos).length === 0) { //check if there is a ray between the mob and the player
|
||||
ctx.beginPath();
|
||||
const vertices = mob[i].vertices;
|
||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||
@@ -25,6 +27,7 @@ const mobs = {
|
||||
ctx.strokeStyle = mob[i].stroke;
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
// }
|
||||
}
|
||||
},
|
||||
healthBar() {
|
||||
@@ -770,8 +773,8 @@ const mobs = {
|
||||
})
|
||||
} else {
|
||||
Matter.Body.setVelocity(array[i], {
|
||||
x: array[i].velocity.x * 0.94 + curlVector.x * 0.06,
|
||||
y: array[i].velocity.y * 0.94 + curlVector.y * 0.06
|
||||
x: array[i].velocity.x * 0.95 + curlVector.x * 0.06,
|
||||
y: array[i].velocity.y * 0.95 + curlVector.y * 0.06
|
||||
})
|
||||
}
|
||||
if (isAntiGravity) array[i].force.y -= 0.8 * simulation.g * array[i].mass
|
||||
|
||||
14
js/player.js
14
js/player.js
@@ -2542,8 +2542,8 @@ const m = {
|
||||
fieldUpgrades: [{
|
||||
name: "field emitter",
|
||||
imageNumber: Math.floor(Math.random() * 23),
|
||||
description: `use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs
|
||||
<br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second`, // <br><strong>100</strong> max <strong class='color-f'>energy</strong>
|
||||
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>
|
||||
effect: () => {
|
||||
m.hold = function () {
|
||||
if (m.isHolding) {
|
||||
@@ -4174,13 +4174,13 @@ const m = {
|
||||
{
|
||||
name: "wormhole",
|
||||
//<strong class='color-worm'>wormholes</strong> attract <strong class='color-block'>blocks</strong> and power ups<br>
|
||||
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong>+4%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
|
||||
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong>+5%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
|
||||
drain: 0,
|
||||
effect: function () {
|
||||
m.fieldMeterColor = "#bbf" //"#0c5"
|
||||
m.eyeFillColor = m.fieldMeterColor
|
||||
|
||||
m.duplicateChance = 0.04
|
||||
m.duplicateChance = 0.05
|
||||
m.fieldRange = 0
|
||||
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
|
||||
|
||||
@@ -4366,7 +4366,7 @@ const m = {
|
||||
|
||||
if (input.field) {
|
||||
if (tech.isWormHolePause) {
|
||||
const drain = m.fieldRegen + 0.00004
|
||||
const drain = m.fieldRegen + 0.000035
|
||||
if (m.energy > drain) {
|
||||
m.energy -= drain
|
||||
if (m.immuneCycle < m.cycle + 1) m.immuneCycle = m.cycle + 1; //player is immune to damage for 1 cycle
|
||||
@@ -4400,9 +4400,9 @@ const m = {
|
||||
m.grabPowerUp();
|
||||
//draw possible wormhole
|
||||
if (tech.isWormholeMapIgnore && Matter.Query.ray(map, m.pos, justPastMouse).length !== 0) {
|
||||
this.drain = (0.06 + 0.006 * Math.sqrt(mag)) * 2
|
||||
this.drain = (0.05 + 0.005 * Math.sqrt(mag)) * 2
|
||||
} else {
|
||||
this.drain = tech.isFreeWormHole ? 0 : 0.06 + 0.006 * Math.sqrt(mag)
|
||||
this.drain = tech.isFreeWormHole ? 0 : 0.05 + 0.005 * Math.sqrt(mag)
|
||||
}
|
||||
const unit = Vector.perp(Vector.normalise(sub))
|
||||
const where = {
|
||||
|
||||
@@ -518,7 +518,7 @@ const powerUps = {
|
||||
m.addHealth(heal);
|
||||
if (healOutput > 0) simulation.makeTextLog(`<span class='color-var'>m</span>.health <span class='color-symbol'>+=</span> ${(healOutput).toFixed(3)}`) // <br>${m.health.toFixed(3)}
|
||||
if (tech.isOverHeal && overHeal > 0) { //tech quenching
|
||||
const scaledOverHeal = overHeal * 0.9
|
||||
const scaledOverHeal = overHeal // * 0.9
|
||||
m.damage(scaledOverHeal);
|
||||
simulation.makeTextLog(`<span class='color-var'>m</span>.health <span class='color-symbol'>-=</span> ${(scaledOverHeal).toFixed(3)}`) // <br>${m.health.toFixed(3)}
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
|
||||
301
js/spawn.js
301
js/spawn.js
@@ -20,9 +20,9 @@ const spawn = {
|
||||
},
|
||||
pickList: ["starter", "starter"],
|
||||
fullPickList: [
|
||||
"slasher", "slasher", "slasher2", "slasher3",
|
||||
"flutter", "flutter", "flutter",
|
||||
"hopper", "hopper", "hopper",
|
||||
"slasher", "slasher", "slasher",
|
||||
"stabber", "stabber", "stabber",
|
||||
"springer", "springer", "springer",
|
||||
"shooter", "shooter",
|
||||
@@ -30,8 +30,7 @@ const spawn = {
|
||||
"striker", "striker",
|
||||
"laser", "laser",
|
||||
"pulsar", "pulsar",
|
||||
"sneaker", "sneaker",
|
||||
"launcher", "launcherOne", "exploder", "sucker", "sniper", "spinner", "grower", "beamer", "spawner", "ghoster", "focuser"
|
||||
"sneaker", "launcher", "launcherOne", "exploder", "sucker", "sniper", "spinner", "grower", "beamer", "spawner", "ghoster", "focuser"
|
||||
],
|
||||
mobTypeSpawnOrder: [], //preset list of mob names calculated at the start of a run by the randomSeed
|
||||
mobTypeSpawnIndex: 0, //increases as the mob type cycles
|
||||
@@ -2437,7 +2436,7 @@ const spawn = {
|
||||
mobs.spawn(x, y, 5, radius, "rgb(0,200,180)");
|
||||
let me = mob[mob.length - 1];
|
||||
me.isBoss = true;
|
||||
me.damageReduction = 0.06 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||
me.damageReduction = 0.08 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||
me.accelMag = 0.05; //jump height
|
||||
me.g = 0.003; //required if using this.gravity
|
||||
me.frictionAir = 0.01;
|
||||
@@ -2736,7 +2735,7 @@ const spawn = {
|
||||
|
||||
me.stroke = "transparent"; //used for drawSneaker
|
||||
me.eventHorizon = 1100; //required for black hole
|
||||
me.seeAtDistance2 = (me.eventHorizon + 1200) * (me.eventHorizon + 1200); //vision limit is event horizon
|
||||
me.seeAtDistance2 = (me.eventHorizon + 3000) * (me.eventHorizon + 3000); //vision limit is event horizon
|
||||
me.accelMag = 0.00004 * simulation.accelScale;
|
||||
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body
|
||||
// me.frictionAir = 0.005;
|
||||
@@ -2848,6 +2847,15 @@ const spawn = {
|
||||
ctx.fill();
|
||||
}
|
||||
this.curl(eventHorizon);
|
||||
//attract other power ups
|
||||
for (let i = 0; i < powerUp.length; i++) { //attract heal power ups
|
||||
const sub = Vector.sub(this.position, powerUp[i].position)
|
||||
const mag = 0.0015 * Math.min(1, (Vector.magnitude(sub) - 200) / this.eventHorizon)
|
||||
const attract = Vector.mult(Vector.normalise(sub), mag * powerUp[i].mass)
|
||||
powerUp[i].force.x += attract.x;
|
||||
powerUp[i].force.y += attract.y - powerUp[i].mass * simulation.g; //negate gravity
|
||||
// Matter.Body.setVelocity(powerUp[i], Vector.mult(powerUp[i].velocity, 0.7));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5493,7 +5501,7 @@ const spawn = {
|
||||
ctx.setLineDash([]);
|
||||
}
|
||||
},
|
||||
slasher(x, y, radius = 36 + Math.ceil(Math.random() * 25)) {
|
||||
slasher(x, y, radius = 33 + Math.ceil(Math.random() * 30)) {
|
||||
mobs.spawn(x, y, 5, radius, "rgb(201,202,225)");
|
||||
let me = mob[mob.length - 1];
|
||||
Matter.Body.rotate(me, 2 * Math.PI * Math.random());
|
||||
@@ -5537,10 +5545,8 @@ const spawn = {
|
||||
this.swordVertex = i
|
||||
}
|
||||
}
|
||||
// this.laserAngle = 7 / 10 * Math.PI + this.swordVertex / 5 * 2 * Math.PI - Math.PI / 2
|
||||
this.laserAngle = this.swordVertex / 5 * 2 * Math.PI + 0.6283
|
||||
this.sword = this.swordGrow
|
||||
// Matter.Body.setVelocity(this, { x: 0, y: 0 });
|
||||
this.accelMag = 0
|
||||
}
|
||||
}
|
||||
@@ -5617,6 +5623,260 @@ const spawn = {
|
||||
ctx.setLineDash([]);
|
||||
}
|
||||
},
|
||||
slasher2(x, y, radius = 33 + Math.ceil(Math.random() * 30)) {
|
||||
mobs.spawn(x, y, 6, radius, "rgb(180,199,245)");
|
||||
let me = mob[mob.length - 1];
|
||||
Matter.Body.rotate(me, 2 * Math.PI * Math.random());
|
||||
me.accelMag = 0.0009 * simulation.accelScale;
|
||||
me.torqueMagnitude = -0.000012 * me.inertia //* (Math.random() > 0.5 ? -1 : 1);
|
||||
me.frictionStatic = 0;
|
||||
me.friction = 0;
|
||||
me.frictionAir = 0.035;
|
||||
me.delay = 140 * simulation.CDScale;
|
||||
me.cd = 0;
|
||||
me.swordRadius = 0;
|
||||
me.swordVertex = 1
|
||||
me.swordRadiusMax = 275 + 3.5 * simulation.difficulty;
|
||||
me.swordRadiusGrowRate = me.swordRadiusMax * (0.011 + 0.0002 * simulation.difficulty)
|
||||
me.isSlashing = false;
|
||||
me.swordDamage = 0.03 * simulation.dmgScale
|
||||
me.laserAngle = 3 * Math.PI / 5
|
||||
const seeDistance2 = 200000
|
||||
spawn.shield(me, x, y);
|
||||
me.onDamage = function () { };
|
||||
me.do = function () {
|
||||
this.checkStatus();
|
||||
this.seePlayerByHistory(15);
|
||||
this.attraction();
|
||||
this.sword() //does various things depending on what stage of the sword swing
|
||||
};
|
||||
me.swordWaiting = function () {
|
||||
if (
|
||||
this.seePlayer.recall &&
|
||||
this.cd < simulation.cycle &&
|
||||
this.distanceToPlayer2() < seeDistance2 &&
|
||||
Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 &&
|
||||
Matter.Query.ray(body, this.position, this.playerPosRandomY()).length === 0
|
||||
) {
|
||||
this.laserAngle = -Math.PI / 6
|
||||
this.sword = this.swordGrow
|
||||
this.accelMag = 0
|
||||
}
|
||||
}
|
||||
me.sword = me.swordWaiting //base function that changes during different aspects of the sword swing
|
||||
me.swordGrow = function () {
|
||||
this.laserSword(this.vertices[0], this.angle + this.laserAngle);
|
||||
this.laserSword(this.vertices[3], this.angle + this.laserAngle + Math.PI);
|
||||
this.swordRadius += this.swordRadiusGrowRate
|
||||
if (this.swordRadius > this.swordRadiusMax || this.isStunned) {
|
||||
this.sword = this.swordSlash
|
||||
this.spinCount = 0
|
||||
}
|
||||
}
|
||||
me.swordSlash = function () {
|
||||
this.laserSword(this.vertices[0], this.angle + this.laserAngle);
|
||||
this.laserSword(this.vertices[3], this.angle + this.laserAngle + Math.PI);
|
||||
|
||||
this.torque += this.torqueMagnitude;
|
||||
this.spinCount++
|
||||
if (this.spinCount > 100 || this.isStunned) {
|
||||
this.sword = this.swordWaiting
|
||||
this.swordRadius = 0
|
||||
this.accelMag = 0.001 * simulation.accelScale;
|
||||
this.cd = simulation.cycle + this.delay;
|
||||
}
|
||||
}
|
||||
me.laserSword = function (where, angle) {
|
||||
const vertexCollision = function (v1, v1End, domain) {
|
||||
for (let i = 0; i < domain.length; ++i) {
|
||||
let v = domain[i].vertices;
|
||||
const len = v.length - 1;
|
||||
for (let j = 0; j < len; j++) {
|
||||
results = simulation.checkLineIntersection(v1, v1End, v[j], v[j + 1]);
|
||||
if (results.onLine1 && results.onLine2) {
|
||||
const dx = v1.x - results.x;
|
||||
const dy = v1.y - results.y;
|
||||
const dist2 = dx * dx + dy * dy;
|
||||
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[j], v2: v[j + 1] };
|
||||
}
|
||||
}
|
||||
results = simulation.checkLineIntersection(v1, v1End, v[0], v[len]);
|
||||
if (results.onLine1 && results.onLine2) {
|
||||
const dx = v1.x - results.x;
|
||||
const dy = v1.y - results.y;
|
||||
const dist2 = dx * dx + dy * dy;
|
||||
if (dist2 < best.dist2) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[0], v2: v[len] };
|
||||
}
|
||||
}
|
||||
};
|
||||
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
|
||||
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
|
||||
vertexCollision(where, look, body); // vertexCollision(where, look, mob);
|
||||
vertexCollision(where, look, map);
|
||||
if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]);
|
||||
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
|
||||
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
|
||||
m.damage(this.swordDamage);
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: best.x,
|
||||
y: best.y,
|
||||
radius: this.swordDamage * 1500,
|
||||
color: "rgba(80,0,255,0.5)",
|
||||
time: 20
|
||||
});
|
||||
}
|
||||
if (best.dist2 === Infinity) best = look;
|
||||
ctx.beginPath(); //draw beam
|
||||
ctx.moveTo(where.x, where.y);
|
||||
ctx.lineTo(best.x, best.y);
|
||||
ctx.strokeStyle = "rgba(100,100,255,0.1)"; // Purple path
|
||||
ctx.lineWidth = 15;
|
||||
ctx.stroke();
|
||||
ctx.strokeStyle = "rgba(100,100,255,0.5)"; // Purple path
|
||||
ctx.lineWidth = 4;
|
||||
ctx.setLineDash([70 + 300 * Math.random(), 55 * Math.random()]);
|
||||
ctx.stroke(); // Draw it
|
||||
ctx.setLineDash([]);
|
||||
}
|
||||
},
|
||||
slasher3(x, y, radius = 33 + Math.ceil(Math.random() * 30)) {
|
||||
const sides = 6
|
||||
mobs.spawn(x, y, sides, radius, "rgb(180,215,235)");
|
||||
let me = mob[mob.length - 1];
|
||||
Matter.Body.rotate(me, 2 * Math.PI * Math.random());
|
||||
me.accelMag = 0.0005 * simulation.accelScale;
|
||||
me.frictionStatic = 0;
|
||||
me.friction = 0;
|
||||
me.frictionAir = 0.02;
|
||||
me.delay = 150 * simulation.CDScale;
|
||||
me.cd = 0;
|
||||
me.cycle = 0;
|
||||
me.swordVertex = 1
|
||||
me.swordRadiusInitial = radius / 2;
|
||||
me.swordRadius = me.swordRadiusInitial;
|
||||
me.swordRadiusMax = 750 + 6 * simulation.difficulty;
|
||||
me.swordRadiusGrowRateInitial = 1.08
|
||||
me.swordRadiusGrowRate = me.swordRadiusGrowRateInitial//me.swordRadiusMax * (0.009 + 0.0002 * simulation.difficulty)
|
||||
me.isSlashing = false;
|
||||
me.swordDamage = 0.04 * simulation.dmgScale
|
||||
me.laserAngle = 3 * Math.PI / 5
|
||||
const seeDistance2 = me.swordRadiusMax * me.swordRadiusMax
|
||||
spawn.shield(me, x, y);
|
||||
me.onDamage = function () { };
|
||||
me.do = function () {
|
||||
this.checkStatus();
|
||||
this.seePlayerByHistory(15);
|
||||
this.sword() //does various things depending on what stage of the sword swing
|
||||
};
|
||||
me.swordWaiting = function () {
|
||||
this.attraction();
|
||||
if (
|
||||
this.seePlayer.recall &&
|
||||
this.cd < simulation.cycle &&
|
||||
this.distanceToPlayer2() < seeDistance2 &&
|
||||
Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 &&
|
||||
Matter.Query.ray(body, this.position, this.playerPosRandomY()).length === 0
|
||||
) {
|
||||
//find vertex closest to the player
|
||||
let dist = Infinity
|
||||
for (let i = 0, len = this.vertices.length; i < len; i++) {
|
||||
const D = Vector.magnitudeSquared(Vector.sub({ x: this.vertices[i].x, y: this.vertices[i].y }, m.pos))
|
||||
if (D < dist) {
|
||||
dist = D
|
||||
this.swordVertex = i
|
||||
}
|
||||
}
|
||||
this.laserAngle = this.swordVertex / sides * 2 * Math.PI + Math.PI / sides
|
||||
this.sword = this.swordGrow
|
||||
this.cycle = 0
|
||||
this.swordRadius = this.swordRadiusInitial
|
||||
//slow velocity but don't stop
|
||||
Matter.Body.setVelocity(this, Vector.mult(this.velocity, 0.5))
|
||||
//set angular velocity to 50%
|
||||
// Matter.Body.setAngularVelocity(this, this.angularVelocity * 0.5)
|
||||
//gently rotate towards the player with a torque, use cross product to decided clockwise or counterclockwise
|
||||
const laserStartVector = Vector.sub(this.position, this.vertices[this.swordVertex])
|
||||
const playerVector = Vector.sub(this.position, m.pos)
|
||||
const cross = Matter.Vector.cross(laserStartVector, playerVector)
|
||||
this.torque = 0.00002 * this.inertia * (cross > 0 ? 1 : -1)
|
||||
}
|
||||
}
|
||||
me.sword = me.swordWaiting //base function that changes during different aspects of the sword swing
|
||||
me.swordGrow = function () {
|
||||
this.laserSpear(this.vertices[this.swordVertex], this.angle + this.laserAngle);
|
||||
Matter.Body.setVelocity(this, Vector.mult(this.velocity, 0.9))
|
||||
// this.swordRadius += this.swordRadiusGrowRate
|
||||
this.cycle++
|
||||
// this.swordRadius = this.swordRadiusMax * Math.sin(this.cycle * 0.03)
|
||||
this.swordRadius *= this.swordRadiusGrowRate
|
||||
|
||||
if (this.swordRadius > this.swordRadiusMax) this.swordRadiusGrowRate = 1 / this.swordRadiusGrowRateInitial
|
||||
// if (this.swordRadius > this.swordRadiusMax) this.swordRadiusGrowRate = -Math.abs(this.swordRadiusGrowRate)
|
||||
if (this.swordRadius < this.swordRadiusInitial || this.isStunned) {
|
||||
// this.swordRadiusGrowRate = Math.abs(this.swordRadiusGrowRate)
|
||||
this.swordRadiusGrowRate = this.swordRadiusGrowRateInitial
|
||||
this.sword = this.swordWaiting
|
||||
this.swordRadius = 0
|
||||
this.cd = simulation.cycle + this.delay;
|
||||
}
|
||||
}
|
||||
me.laserSpear = function (where, angle) {
|
||||
const vertexCollision = function (v1, v1End, domain) {
|
||||
for (let i = 0; i < domain.length; ++i) {
|
||||
let v = domain[i].vertices;
|
||||
const len = v.length - 1;
|
||||
for (let j = 0; j < len; j++) {
|
||||
results = simulation.checkLineIntersection(v1, v1End, v[j], v[j + 1]);
|
||||
if (results.onLine1 && results.onLine2) {
|
||||
const dx = v1.x - results.x;
|
||||
const dy = v1.y - results.y;
|
||||
const dist2 = dx * dx + dy * dy;
|
||||
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[j], v2: v[j + 1] };
|
||||
}
|
||||
}
|
||||
results = simulation.checkLineIntersection(v1, v1End, v[0], v[len]);
|
||||
if (results.onLine1 && results.onLine2) {
|
||||
const dx = v1.x - results.x;
|
||||
const dy = v1.y - results.y;
|
||||
const dist2 = dx * dx + dy * dy;
|
||||
if (dist2 < best.dist2) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[0], v2: v[len] };
|
||||
}
|
||||
}
|
||||
};
|
||||
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
|
||||
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
|
||||
vertexCollision(where, look, body); // vertexCollision(where, look, mob);
|
||||
vertexCollision(where, look, map);
|
||||
if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]);
|
||||
if (best.who && (best.who === playerBody || best.who === playerHead)) {
|
||||
this.swordRadiusGrowRate = 1 / this.swordRadiusGrowRateInitial //!!!! this retracts the sword if it hits the player
|
||||
|
||||
if (m.immuneCycle < m.cycle) {
|
||||
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
|
||||
m.damage(this.swordDamage);
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: best.x,
|
||||
y: best.y,
|
||||
radius: this.swordDamage * 1500,
|
||||
color: "rgba(80,0,255,0.5)",
|
||||
time: 20
|
||||
});
|
||||
}
|
||||
}
|
||||
if (best.dist2 === Infinity) best = look;
|
||||
ctx.beginPath(); //draw beam
|
||||
ctx.moveTo(where.x, where.y);
|
||||
ctx.lineTo(best.x, best.y);
|
||||
ctx.strokeStyle = "rgba(100,100,255,0.1)"; // Purple path
|
||||
ctx.lineWidth = 15;
|
||||
ctx.stroke();
|
||||
ctx.strokeStyle = "rgba(100,100,255,0.5)"; // Purple path
|
||||
ctx.lineWidth = 4;
|
||||
ctx.setLineDash([70 + 300 * Math.random(), 55 * Math.random()]);
|
||||
ctx.stroke(); // Draw it
|
||||
ctx.setLineDash([]);
|
||||
}
|
||||
},
|
||||
sneakBoss(x, y, radius = 70) {
|
||||
mobs.spawn(x, y, 5, radius, "transparent");
|
||||
let me = mob[mob.length - 1];
|
||||
@@ -5961,10 +6221,7 @@ const spawn = {
|
||||
me.friction = 0;
|
||||
me.frictionAir = 0.05;
|
||||
me.lookTorque = 0.0000025 * (Math.random() > 0.5 ? -1 : 1);
|
||||
me.fireDir = {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
me.fireDir = { x: 0, y: 0 };
|
||||
me.onDeath = function () { //helps collisions functions work better after vertex have been changed
|
||||
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices))
|
||||
}
|
||||
@@ -5998,7 +6255,7 @@ const spawn = {
|
||||
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
|
||||
me.isVerticesChange = true
|
||||
me.memory = 240;
|
||||
me.fireFreq = 0.009 + 0.0004 * Math.min(40, simulation.difficulty); //bigger number means more shots per second
|
||||
me.fireFreq = 0.01 + 0.0005 * Math.min(40, simulation.difficulty); //bigger number means more shots per second
|
||||
me.noseLength = 0;
|
||||
me.fireAngle = 0;
|
||||
me.accelMag = 0.005 * simulation.accelScale;
|
||||
@@ -6027,14 +6284,11 @@ const spawn = {
|
||||
//set direction to turn to fire
|
||||
if (!(simulation.cycle % this.seePlayerFreq)) {
|
||||
this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position));
|
||||
this.fireDir.y -= Math.abs(this.seePlayer.position.x - this.position.x) / 2500; //gives the bullet an arc //was / 1600
|
||||
this.fireDir.y -= Math.abs(this.seePlayer.position.x - this.position.x) / 5000; //gives the bullet an arc //was / 1600
|
||||
}
|
||||
//rotate towards fireAngle
|
||||
const angle = this.angle + Math.PI / 2;
|
||||
const dot = Vector.dot({
|
||||
x: Math.cos(angle),
|
||||
y: Math.sin(angle)
|
||||
}, this.fireDir)
|
||||
const dot = Vector.dot({ x: Math.cos(angle), y: Math.sin(angle) }, this.fireDir)
|
||||
// c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
|
||||
const threshold = 0.1;
|
||||
if (dot > threshold) {
|
||||
@@ -6044,12 +6298,9 @@ const spawn = {
|
||||
} else if (this.noseLength > 1.5 && dot > -0.2 && dot < 0.2) {
|
||||
//fire
|
||||
for (let i = 0, len = 2 + 0.07 * simulation.difficulty; i < len; i++) {
|
||||
spawn.bullet(this.vertices[1].x, this.vertices[1].y, 7 + Math.ceil(this.radius / 25));
|
||||
const spread = Vector.rotate({
|
||||
x: Math.sqrt(len) + 4,
|
||||
y: 0
|
||||
}, 2 * Math.PI * Math.random())
|
||||
const dir = Vector.add(Vector.mult(this.fireDir, 15), spread)
|
||||
spawn.bullet(this.vertices[1].x, this.vertices[1].y, 10 + Math.ceil(this.radius / 25));
|
||||
const spread = Vector.rotate({ x: Math.sqrt(len) + 4, y: 0 }, 2 * Math.PI * Math.random())
|
||||
const dir = Vector.add(Vector.mult(this.fireDir, 25), spread)
|
||||
Matter.Body.setVelocity(mob[mob.length - 1], dir);
|
||||
}
|
||||
this.noseLength = 0;
|
||||
@@ -7326,7 +7577,7 @@ const spawn = {
|
||||
mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)");
|
||||
let me = mob[mob.length - 1];
|
||||
me.collisionFilter.mask = cat.bullet | cat.player //| cat.mob //| cat.body
|
||||
me.damageReduction = 0.024
|
||||
me.damageReduction = 0.028
|
||||
Matter.Body.setDensity(me, 0.0001); //normal is 0.001
|
||||
|
||||
// me.accelMag = 0.0007 * simulation.accelScale;
|
||||
|
||||
59
js/tech.js
59
js/tech.js
@@ -325,7 +325,7 @@ const tech = {
|
||||
tech.hardLanding = 70
|
||||
tech.isFallingDamage = true;
|
||||
m.setMaxHealth();
|
||||
m.addHealth(1 / simulation.healScale)
|
||||
m.addHealth(2.22 / simulation.healScale)
|
||||
m.skin.tungsten()
|
||||
},
|
||||
remove() {
|
||||
@@ -3013,7 +3013,10 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "induction brake",
|
||||
description: `after using ${powerUps.orb.heal()} <strong class='color-s'>slow</strong> nearby mobs for <strong>15</strong> seconds<br>spawn ${powerUps.orb.heal(4)}`,
|
||||
descriptionFunction() {
|
||||
return `after using ${powerUps.orb.heal()} <strong class='color-s'>slow</strong> nearby mobs for <strong>15</strong> seconds<br>spawn ${powerUps.orb.heal(4)}`
|
||||
},
|
||||
// description: `after using ${powerUps.orb.heal()} <strong class='color-s'>slow</strong> nearby mobs for <strong>15</strong> seconds<br>spawn ${powerUps.orb.heal(4)}`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -3096,7 +3099,10 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "accretion",
|
||||
description: `${powerUps.orb.heal(1)} follow you, even between levels<br>spawn ${powerUps.orb.heal(5)}`,
|
||||
descriptionFunction() {
|
||||
return `${powerUps.orb.heal(1)} follow you, even between levels<br>spawn ${powerUps.orb.heal(5)}`
|
||||
},
|
||||
// description: `${powerUps.orb.heal(1)} follow you, even between levels<br>spawn ${powerUps.orb.heal(5)}`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -3270,7 +3276,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "Hilbert space",
|
||||
description: "<strong>+91%</strong> <strong class='color-d'>damage</strong><br>after a <strong>collision</strong> enter an <strong class='alt'>alternate reality</strong>",
|
||||
description: "<strong>+99%</strong> <strong class='color-d'>damage</strong><br>after a <strong>collision</strong> enter an <strong class='alt'>alternate reality</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -3280,7 +3286,7 @@ const tech = {
|
||||
return !tech.isResearchReality && !tech.isSwitchReality
|
||||
},
|
||||
requires: "not Ψ(t) collapse, many-worlds",
|
||||
damage: 1.91,
|
||||
damage: 1.99,
|
||||
effect() {
|
||||
tech.damage *= this.damage
|
||||
tech.isCollisionRealitySwitch = true;
|
||||
@@ -3454,7 +3460,10 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "mass production",
|
||||
description: `<strong class='color-m'>tech</strong> always have <strong>+3</strong> choices to spawn<br>${powerUps.orb.research(5)} ${powerUps.orb.ammo(8)} or ${powerUps.orb.heal(8)}`,
|
||||
descriptionFunction() {
|
||||
return `<strong class='color-m'>tech</strong> always have <strong>+3</strong> choices to spawn<br>${powerUps.orb.ammo(8)} ${powerUps.orb.heal(8)} or ${powerUps.orb.research(5)}`
|
||||
},
|
||||
// description: `<strong class='color-m'>tech</strong> always have <strong>+3</strong> choices to spawn<br>${powerUps.orb.ammo(8)} ${powerUps.orb.heal(8)} or ${powerUps.orb.research(5)}`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -3502,7 +3511,9 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "heals",
|
||||
description: `spawn ${powerUps.orb.heal(8)}`,
|
||||
descriptionFunction() {
|
||||
return `spawn ${powerUps.orb.heal(8)}`
|
||||
},
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 0,
|
||||
@@ -9036,7 +9047,7 @@ const tech = {
|
||||
// },
|
||||
{
|
||||
name: "return",
|
||||
description: "return to the introduction level<br>reduce combat <strong>difficulty</strong> by <strong>2 levels</strong>",
|
||||
description: "return to the start of the game<br>reduce combat <strong>difficulty</strong> by <strong>2 levels</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 0,
|
||||
@@ -9500,21 +9511,7 @@ const tech = {
|
||||
}
|
||||
},
|
||||
remove() {
|
||||
mobs.draw = () => {
|
||||
ctx.lineWidth = 2;
|
||||
let i = mob.length;
|
||||
while (i--) {
|
||||
ctx.beginPath();
|
||||
const vertices = mob[i].vertices;
|
||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||
for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y);
|
||||
ctx.lineTo(vertices[0].x, vertices[0].y);
|
||||
ctx.fillStyle = mob[i].fill;
|
||||
ctx.strokeStyle = mob[i].stroke;
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
mobs.draw = mobs.drawDefault
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -9546,21 +9543,7 @@ const tech = {
|
||||
}
|
||||
},
|
||||
remove() {
|
||||
mobs.draw = () => {
|
||||
ctx.lineWidth = 2;
|
||||
let i = mob.length;
|
||||
while (i--) {
|
||||
ctx.beginPath();
|
||||
const vertices = mob[i].vertices;
|
||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||
for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y);
|
||||
ctx.lineTo(vertices[0].x, vertices[0].y);
|
||||
ctx.fillStyle = mob[i].fill;
|
||||
ctx.strokeStyle = mob[i].stroke;
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
mobs.draw = mobs.drawDefault
|
||||
}
|
||||
},
|
||||
// draw() {
|
||||
|
||||
74
todo.txt
74
todo.txt
@@ -1,15 +1,33 @@
|
||||
******************************************************** NEXT PATCH **************************************************
|
||||
|
||||
new community levels:
|
||||
tlinat by Richard0820
|
||||
ruins by SiddhUPe
|
||||
new community training level diamagnetism by Richard0820
|
||||
it's at the end of the training levels
|
||||
start training by click the top right button at the load screen
|
||||
|
||||
tech: mass production - tech have +3 choices to spawn ammo, research, or heals
|
||||
slasher mob variant with 2 laser swords
|
||||
slasher mob variant with a laser spear
|
||||
|
||||
suckerBoss pulls in powerUps and makes them orbit better
|
||||
shooterBoss fires faster and larger bullets
|
||||
|
||||
wormhole 4 -> 5% duplication, and a 10% reduction in energy cost
|
||||
drones fire faster and aim more accurately
|
||||
quenching gives 10% more max health and harm
|
||||
snake tail mobs have 15% less health
|
||||
tungsten carbide properly gives 222 health in addition to the bonus max health
|
||||
|
||||
*********************************************************** TODO *****************************************************
|
||||
|
||||
make a mob similar to slasher
|
||||
because it's just a very well made mob.
|
||||
use cross product rotation for other mobs?
|
||||
snipers, shooters?
|
||||
//gently rotate towards the player with a torque, use cross product to decided clockwise or counterclockwise
|
||||
const laserStartVector = Vector.sub(this.position, this.vertices[this.swordVertex])
|
||||
const playerVector = Vector.sub(this.position, m.pos)
|
||||
const cross = Matter.Vector.cross(laserStartVector, playerVector)
|
||||
this.torque = 0.00002 * this.inertia * (cross > 0 ? 1 : -1)
|
||||
|
||||
block manufacturing - molecular assembler tech
|
||||
Holding r-click will create a slowly increasing in size block, which will be thrown on release
|
||||
|
||||
super-bot: fires super balls
|
||||
|
||||
@@ -24,8 +42,6 @@ tech: after a needle hits a mobs
|
||||
reset your fire CD?
|
||||
2x damage for each consecutive mob hit?
|
||||
|
||||
improve flatland performance?
|
||||
|
||||
mob non-combat behaviors, like Rain World
|
||||
gathering
|
||||
blocks
|
||||
@@ -62,10 +78,6 @@ use ephemera to replace some bad code
|
||||
damage and defense bars
|
||||
disable and enable ephemera with settings
|
||||
|
||||
drones target anything that moves: speed > 1
|
||||
including player, blocks?, mobs, power ups
|
||||
maybe target the fastest mobs?
|
||||
|
||||
perfect diamagnatism - invulnerable while field is active?
|
||||
also drain energy while field is active?
|
||||
|
||||
@@ -75,11 +87,6 @@ mobs attack mines
|
||||
|
||||
tech circular polarization - wave gun bullets move in a circle
|
||||
|
||||
tech: choose next map by name after exiting current map
|
||||
use modified tech selection code?
|
||||
this might be too much work without much reward
|
||||
JUNK only? or maybe combine with other buff
|
||||
|
||||
Tech: relativity
|
||||
Simulation speed scales with movement speed. When still, time moves at 0.4 speed, at full walking speed it’s 1. (So if you’re falling or something and you move faster the simulation will be faster than usual)
|
||||
Also a damage and/or defense boost to make it worth using
|
||||
@@ -94,7 +101,6 @@ extend brainstorming animation timers to fps cap?
|
||||
perfect diamagnatism could bounce on mobs, or even map elements?
|
||||
could work like a rocket jump?
|
||||
|
||||
|
||||
tech: Bose Einstein condensate - freezes enemies in pilot wave, and drains some energy?
|
||||
|
||||
make super balls with Zectron deflectable with field
|
||||
@@ -103,17 +109,8 @@ make super balls with Zectron deflectable with field
|
||||
set mob health bar colors based on status effects?
|
||||
make mob damage immunity a mob status effect?
|
||||
|
||||
physics notes: add link to double slit content
|
||||
https://www.youtube.com/watch?v=v_uBaBuarEM
|
||||
|
||||
tech: rail gun area damage effect, but for all harpoon mode
|
||||
|
||||
laser momentum pushed back on player?
|
||||
might just be annoying
|
||||
|
||||
JUNK - overwrite mob draw function so mobs only draw if they can connect a ray from player to mob
|
||||
gonna cause lag?
|
||||
|
||||
mob status effect - vulnerability
|
||||
mobs take 4x damage for __ time
|
||||
afterwards mobs go back to normal damage taken
|
||||
@@ -129,8 +126,6 @@ tech: sporangium that grow little trees
|
||||
the trees have an area of effect damage for about 6-10 seconds
|
||||
maybe something similar to radioactive drones, but maybe a few smaller shapes
|
||||
|
||||
harpoon tech that makes auto aim work much better
|
||||
|
||||
hookBoss fires a hook that pulls player towards it
|
||||
hook does a bit of damage
|
||||
player targeted unless cloaking
|
||||
@@ -213,13 +208,9 @@ Tech:when relay switch/flip flop is on, turn ammo powerups into boosts, when rel
|
||||
JUNK: what the golf?
|
||||
trying to throw a block throws you instead
|
||||
|
||||
look for other tech that would benefit from a 3rd line of description text
|
||||
|
||||
tech for lens - you can only fire through the lens
|
||||
and some buff? damage or energy?
|
||||
|
||||
hopMom fight make platforming with hop bullets harder?
|
||||
|
||||
complete blowSuckBoss... or don't
|
||||
|
||||
tech: laser reflections increase damage
|
||||
@@ -227,14 +218,6 @@ tech: laser reflections increase damage
|
||||
JUNK tech different effects based on night or day
|
||||
use system time
|
||||
|
||||
buffing your deflecting for 1 second after pressing the field button
|
||||
2 second cooldown on the effect to prevent spamming it
|
||||
buff: giving energy or doing damage makes sense
|
||||
maybe this could be a rework for bremstralung
|
||||
|
||||
replace field descriptions with a function call so they can have dynamic text
|
||||
add in dynamic coupling text as a 4th line
|
||||
|
||||
Boss that shoots out a ring of bullets, then after a few seconds it gravitates the bullets back
|
||||
|
||||
coupling
|
||||
@@ -404,12 +387,6 @@ super balls do more damage after bouncing?
|
||||
how to check for bounce?
|
||||
maybe just increases damage after hitting a mob
|
||||
|
||||
Make environmental damages also damage mobs
|
||||
So if a mob passes through laser, it gets damaged
|
||||
|
||||
dark mode:
|
||||
look at Tinyfolks, 20 minutes till dawn
|
||||
|
||||
super short range foam that acts like flame thrower
|
||||
high fire rate
|
||||
short life spawn
|
||||
@@ -428,8 +405,7 @@ laser tech where bots move around and follow you while firing lasers in the dire
|
||||
beam is similar to diffuse beam
|
||||
|
||||
|
||||
block manufacturing - molecular assembler tech
|
||||
Holding r-click will create a slowly increasing in size block, which will be thrown on release
|
||||
|
||||
|
||||
double research
|
||||
|
||||
|
||||
Reference in New Issue
Block a user