tokamak
tech: tokamak - instead of throwing a block convert it into energy and a pulse explosion requires plasma standing wave field no longer gives 25% harm reduction standing wave field can now block through walls bug fixes
This commit is contained in:
@@ -1578,7 +1578,7 @@ const b = {
|
||||
restitution: 0.5,
|
||||
dmg: 0, // 0.14 //damage done in addition to the damage from momentum
|
||||
minDmgSpeed: 2,
|
||||
lookFrequency: 60 + Math.floor(7 * Math.random()),
|
||||
lookFrequency: 67 + Math.floor(7 * Math.random()),
|
||||
drain: 0.7 * tech.isLaserDiode * tech.laserFieldDrain,
|
||||
isArmed: false,
|
||||
torqueMagnitude: 0.000003 * (Math.round(Math.random()) ? 1 : -1),
|
||||
@@ -1611,7 +1611,7 @@ const b = {
|
||||
Matter.Query.ray(body, this.position, mob[i].position).length === 0
|
||||
) {
|
||||
this.do = this.laserSpin
|
||||
this.endCycle = simulation.cycle + 300
|
||||
this.endCycle = simulation.cycle + 360
|
||||
// if (this.angularSpeed < 0.01) this.torque += this.inertia * this.torqueMagnitude * 5 //spin
|
||||
this.isArmed = true
|
||||
}
|
||||
|
||||
10
js/level.js
10
js/level.js
@@ -15,11 +15,11 @@ const level = {
|
||||
// simulation.zoomScale = 1000;
|
||||
// simulation.setZoom();
|
||||
// simulation.enableConstructMode() //used to build maps in testing mode
|
||||
// m.setField("standing wave harmonics")
|
||||
// m.setField("plasma torch")
|
||||
// for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics")
|
||||
// b.giveGuns("laser")
|
||||
// tech.isExplodeRadio = true
|
||||
// for (let i = 0; i < 5; i++) tech.giveTech("spherical harmonics")
|
||||
// tech.giveTech("expansion")
|
||||
// tech.giveTech("Z-pinch")
|
||||
// tech.giveTech("MACHO")
|
||||
// tech.giveTech("potential well")
|
||||
// for (let i = 0; i < 3; i++) tech.giveTech("packet length")
|
||||
@@ -55,7 +55,7 @@ const level = {
|
||||
// level.vats() //community level
|
||||
// level["n-gon"]() //community level
|
||||
// level.tunnel() //community level
|
||||
// tech.giveTech("undefined")
|
||||
// for (let i = 0; i < 7; i++) tech.giveTech("undefined")
|
||||
// lore.techCount = 6
|
||||
// localSettings.loreCount = 1;
|
||||
// localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
|
||||
@@ -1152,7 +1152,7 @@ const level = {
|
||||
spawn.bodyRect(x + 5, y - 260 + i * blockSize, 30, blockSize);
|
||||
}
|
||||
}
|
||||
// blockDoor(710, -710);
|
||||
blockDoor(710, -710);
|
||||
// for (let i = 0; i < 30; i++) powerUps.directSpawn(710, -710, "tech");
|
||||
|
||||
spawn.mapRect(2500, -1200, 200, 750); //right wall
|
||||
|
||||
149
js/player.js
149
js/player.js
@@ -1135,58 +1135,73 @@ const m = {
|
||||
//throw the body
|
||||
m.fieldCDcycle = m.cycle + 15;
|
||||
m.isHolding = false;
|
||||
//bullet-like collisions
|
||||
m.holdingTarget.collisionFilter.category = tech.isBlockBullets ? cat.bullet : cat.body;
|
||||
m.holdingTarget.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield;
|
||||
//check every second to see if player is away from thrown body, and make solid
|
||||
const solid = function(that) {
|
||||
const dx = that.position.x - player.position.x;
|
||||
const dy = that.position.y - player.position.y;
|
||||
if (that.speed < 3 && dx * dx + dy * dy > 10000 && that !== m.holdingTarget) {
|
||||
that.collisionFilter.category = cat.body; //make solid
|
||||
that.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet; //can hit player now
|
||||
} else {
|
||||
setTimeout(solid, 40, that);
|
||||
|
||||
if (tech.isBlockExplosion && m.throwCharge > 5) { //remove the block body and pulse in the direction you are facing
|
||||
//m.throwCharge > 5 seems to be when the field full colors in a block you are holding
|
||||
m.throwCharge = 0;
|
||||
m.throwCycle = m.cycle + 180 //used to detect if a block was thrown in the last 3 seconds
|
||||
m.definePlayerMass() //return to normal player mass
|
||||
m.energy += 3 * Math.sqrt(m.holdingTarget.mass)
|
||||
//remove block before pulse, so it doesn't get in the way
|
||||
for (let i = 0; i < body.length; i++) {
|
||||
if (body[i] === m.holdingTarget) {
|
||||
Matter.World.remove(engine.world, body[i]);
|
||||
body.splice(i, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
setTimeout(solid, 200, m.holdingTarget);
|
||||
|
||||
const charge = Math.min(m.throwCharge / 5, 1)
|
||||
//***** scale throw speed with the first number, 80 *****
|
||||
let speed = 80 * charge * Math.min(1, 0.8 / Math.pow(m.holdingTarget.mass, 0.25));
|
||||
|
||||
if (Matter.Query.collides(m.holdingTarget, map).length !== 0) {
|
||||
speed *= 0.7 //drop speed by 30% if touching map
|
||||
if (Matter.Query.ray(map, m.holdingTarget.position, m.pos).length !== 0) speed = 0 //drop to zero if the center of the block can't see the center of the player through the map
|
||||
//|| Matter.Query.ray(body, m.holdingTarget.position, m.pos).length > 1
|
||||
}
|
||||
|
||||
m.throwCharge = 0;
|
||||
m.throwCycle = m.cycle + 180 //used to detect if a block was thrown in the last 3 seconds
|
||||
Matter.Body.setVelocity(m.holdingTarget, {
|
||||
x: player.velocity.x * 0.5 + Math.cos(m.angle) * speed,
|
||||
y: player.velocity.y * 0.5 + Math.sin(m.angle) * speed
|
||||
});
|
||||
//player recoil //stronger in x-dir to prevent jump hacking
|
||||
|
||||
Matter.Body.setVelocity(player, {
|
||||
x: player.velocity.x - Math.cos(m.angle) * speed / (m.crouch ? 30 : 10) * Math.sqrt(m.holdingTarget.mass),
|
||||
y: player.velocity.y - Math.sin(m.angle) * speed / 30 * Math.sqrt(m.holdingTarget.mass)
|
||||
});
|
||||
m.definePlayerMass() //return to normal player mass
|
||||
|
||||
if (tech.isAddBlockMass) {
|
||||
const expand = function(that, massLimit) {
|
||||
if (that.mass < massLimit) {
|
||||
const scale = 1.05;
|
||||
Matter.Body.scale(that, scale, scale);
|
||||
setTimeout(expand, 20, that, massLimit);
|
||||
b.pulse(50 * Math.pow(m.holdingTarget.mass, 0.25), m.angle)
|
||||
} else { //normal throw
|
||||
//bullet-like collisions
|
||||
m.holdingTarget.collisionFilter.category = tech.isBlockBullets ? cat.bullet : cat.body;
|
||||
m.holdingTarget.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield;
|
||||
//check every second to see if player is away from thrown body, and make solid
|
||||
const solid = function(that) {
|
||||
const dx = that.position.x - player.position.x;
|
||||
const dy = that.position.y - player.position.y;
|
||||
if (that.speed < 3 && dx * dx + dy * dy > 10000 && that !== m.holdingTarget) {
|
||||
that.collisionFilter.category = cat.body; //make solid
|
||||
that.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet; //can hit player now
|
||||
} else {
|
||||
setTimeout(solid, 40, that);
|
||||
}
|
||||
};
|
||||
expand(m.holdingTarget, Math.min(20, m.holdingTarget.mass * 3))
|
||||
setTimeout(solid, 200, m.holdingTarget);
|
||||
|
||||
const charge = Math.min(m.throwCharge / 5, 1)
|
||||
//***** scale throw speed with the first number, 80 *****
|
||||
let speed = 80 * charge * Math.min(1, 0.8 / Math.pow(m.holdingTarget.mass, 0.25));
|
||||
|
||||
if (Matter.Query.collides(m.holdingTarget, map).length !== 0) {
|
||||
speed *= 0.7 //drop speed by 30% if touching map
|
||||
if (Matter.Query.ray(map, m.holdingTarget.position, m.pos).length !== 0) speed = 0 //drop to zero if the center of the block can't see the center of the player through the map
|
||||
//|| Matter.Query.ray(body, m.holdingTarget.position, m.pos).length > 1
|
||||
}
|
||||
|
||||
m.throwCharge = 0;
|
||||
m.throwCycle = m.cycle + 180 //used to detect if a block was thrown in the last 3 seconds
|
||||
Matter.Body.setVelocity(m.holdingTarget, {
|
||||
x: player.velocity.x * 0.5 + Math.cos(m.angle) * speed,
|
||||
y: player.velocity.y * 0.5 + Math.sin(m.angle) * speed
|
||||
});
|
||||
//player recoil //stronger in x-dir to prevent jump hacking
|
||||
|
||||
Matter.Body.setVelocity(player, {
|
||||
x: player.velocity.x - Math.cos(m.angle) * speed / (m.crouch ? 30 : 10) * Math.sqrt(m.holdingTarget.mass),
|
||||
y: player.velocity.y - Math.sin(m.angle) * speed / 30 * Math.sqrt(m.holdingTarget.mass)
|
||||
});
|
||||
m.definePlayerMass() //return to normal player mass
|
||||
|
||||
if (tech.isAddBlockMass) {
|
||||
const expand = function(that, massLimit) {
|
||||
if (that.mass < massLimit) {
|
||||
const scale = 1.05;
|
||||
Matter.Body.scale(that, scale, scale);
|
||||
setTimeout(expand, 20, that, massLimit);
|
||||
}
|
||||
};
|
||||
expand(m.holdingTarget, Math.min(20, m.holdingTarget.mass * 3))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} else {
|
||||
m.isHolding = false
|
||||
@@ -1353,11 +1368,8 @@ const m = {
|
||||
},
|
||||
pushMobs360(range) { // find mobs in range in any direction
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (
|
||||
Vector.magnitude(Vector.sub(mob[i].position, m.pos)) - mob[i].radius < range &&
|
||||
!mob[i].isShielded &&
|
||||
Matter.Query.ray(map, mob[i].position, m.pos).length === 0
|
||||
) {
|
||||
if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) - mob[i].radius < range && !mob[i].isShielded) {
|
||||
// && Matter.Query.ray(map, mob[i].position, m.pos).length === 0
|
||||
mob[i].locatePlayer();
|
||||
m.pushMass(mob[i]);
|
||||
}
|
||||
@@ -1495,25 +1507,16 @@ const m = {
|
||||
},
|
||||
{
|
||||
name: "standing wave harmonics",
|
||||
description: "<strong>3</strong> oscillating <strong>shields</strong> are permanently active<br><strong>deflecting</strong> drains <strong class='color-f'>energy</strong> with no <strong>cool down</strong><br>reduce <strong class='color-harm'>harm</strong> and deflecting <strong>recoil</strong> by <strong>25%</strong>",
|
||||
description: "<strong>3</strong> oscillating <strong>shields</strong> are permanently active<br><strong>deflecting</strong> drains <strong class='color-f'>energy</strong> with no <strong>cool down</strong><br><strong>deflecting</strong> has <strong>75%</strong> less <strong>recoil</strong>", //<strong class='color-harm'>harm</strong> and
|
||||
effect: () => {
|
||||
// m.fieldHarmReduction = 0.80;
|
||||
m.fieldBlockCD = 0;
|
||||
m.fieldHarmReduction = 0.75;
|
||||
// m.fieldHarmReduction = 0.75;
|
||||
m.blockingRecoil = 1 //4 is normal
|
||||
m.fieldRange = 175
|
||||
m.fieldShieldingScale = Math.pow(0.5, (tech.harmonics - 3))
|
||||
m.harmonicRadius = 1 //for smoothing function when player holds mouse (for harmonicAtomic)
|
||||
m.harmonic3Phase = () => { //normal standard 3 different 2-d circles
|
||||
if (tech.isStandingWaveExpand) {
|
||||
if (input.field) {
|
||||
const oldHarmonicRadius = m.harmonicRadius
|
||||
m.harmonicRadius = 0.985 * m.harmonicRadius + 0.015 * 2.5
|
||||
m.energy -= 0.3 * (m.harmonicRadius - oldHarmonicRadius)
|
||||
} else {
|
||||
m.harmonicRadius = 0.998 * m.harmonicRadius + 0.002 * 1
|
||||
}
|
||||
}
|
||||
const fieldRange1 = (0.7 + 0.3 * Math.sin(m.cycle / 23)) * m.fieldRange * m.harmonicRadius
|
||||
const fieldRange2 = (0.63 + 0.37 * Math.sin(m.cycle / 37)) * m.fieldRange * m.harmonicRadius
|
||||
const fieldRange3 = (0.65 + 0.35 * Math.sin(m.cycle / 47)) * m.fieldRange * m.harmonicRadius
|
||||
@@ -1533,15 +1536,6 @@ const m = {
|
||||
m.harmonicAtomic = () => { //several ellipses spinning about different axises
|
||||
const rotation = simulation.cycle * 0.002
|
||||
const phase = simulation.cycle * 0.03
|
||||
if (tech.isStandingWaveExpand) {
|
||||
if (input.field) {
|
||||
const oldHarmonicRadius = m.harmonicRadius
|
||||
m.harmonicRadius = 0.985 * m.harmonicRadius + 0.015 * 2.5
|
||||
m.energy -= 0.3 * (m.harmonicRadius - oldHarmonicRadius)
|
||||
} else {
|
||||
m.harmonicRadius = 0.998 * m.harmonicRadius + 0.002 * 1
|
||||
}
|
||||
}
|
||||
const radius = m.fieldRange * m.harmonicRadius //+ 20 * Math.sin(m.cycle * 0.05)
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeStyle = "rgba(110,170,200,0.9)"
|
||||
@@ -1585,6 +1579,15 @@ const m = {
|
||||
m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
|
||||
}
|
||||
if (m.energy > 0.1 && m.fieldCDcycle < m.cycle) {
|
||||
if (tech.isStandingWaveExpand) {
|
||||
if (input.field) {
|
||||
const oldHarmonicRadius = m.harmonicRadius
|
||||
m.harmonicRadius = 0.985 * m.harmonicRadius + 0.015 * 2.5
|
||||
m.energy -= 0.45 * (m.harmonicRadius - oldHarmonicRadius)
|
||||
} else {
|
||||
m.harmonicRadius = 0.997 * m.harmonicRadius + 0.003 * 1
|
||||
}
|
||||
}
|
||||
m.harmonicShield()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// game Object ********************************************************
|
||||
//*********************************************************************
|
||||
const simulation = {
|
||||
loop() {}, //main game loop, gets se tto normal or testing loop
|
||||
loop() {}, //main game loop, gets set to normal or testing loop
|
||||
normalLoop() {
|
||||
simulation.gravity();
|
||||
Engine.update(engine, simulation.delta);
|
||||
@@ -525,18 +525,9 @@ const simulation = {
|
||||
level.levels.push("tunnel");
|
||||
level.levels = shuffle(level.levels); //shuffles order of maps
|
||||
level.levels.splice(0, 9); //remove some random levels to make up for adding the community levels
|
||||
|
||||
lore.techCount = 0; //remove undefined tech for community maps
|
||||
for (let i = 0, len = tech.tech.length; i < len; i++) {
|
||||
if (tech.tech[i].isLore) {
|
||||
tech.tech[i].frequency = 0;
|
||||
tech.tech[i].count = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
level.levels = shuffle(level.levels); //shuffles order of maps
|
||||
}
|
||||
|
||||
level.levels.unshift("intro"); //add level to the start of the randomized levels list
|
||||
level.levels.push("gauntlet"); //add level to the end of the randomized levels list
|
||||
level.levels.push("final"); //add level to the end of the randomized levels list
|
||||
@@ -657,6 +648,7 @@ const simulation = {
|
||||
simulation.fpsInterval = 1000 / simulation.fpsCap;
|
||||
simulation.then = Date.now();
|
||||
requestAnimationFrame(cycle); //starts game loop
|
||||
|
||||
},
|
||||
clearTimeouts() {
|
||||
let id = window.setTimeout(function() {}, 0);
|
||||
|
||||
237
js/spawn.js
237
js/spawn.js
@@ -242,120 +242,127 @@ const spawn = {
|
||||
me.isBoss = true;
|
||||
me.frictionAir = 0.01;
|
||||
me.memory = Infinity;
|
||||
me.hasRunDeathScript = false
|
||||
me.locatePlayer();
|
||||
const density = 0.25
|
||||
Matter.Body.setDensity(me, density); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
// spawn.shield(me, x, y, 1);
|
||||
me.onDeath = function() {
|
||||
if (!this.hasRunDeathScript) {
|
||||
this.hasRunDeathScript = true
|
||||
//make a block body to replace this one
|
||||
//this body is too big to leave behind in the normal way mobs.replace()
|
||||
const len = body.length;
|
||||
const v = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //might help with vertex collision issue, not sure
|
||||
body[len] = Matter.Bodies.fromVertices(this.position.x, this.position.y, v);
|
||||
Matter.Body.setVelocity(body[len], { x: 0, y: -3 });
|
||||
Matter.Body.setAngularVelocity(body[len], this.angularVelocity);
|
||||
body[len].collisionFilter.category = cat.body;
|
||||
body[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet;
|
||||
body[len].classType = "body";
|
||||
World.add(engine.world, body[len]); //add to world
|
||||
const expand = function(that, massLimit) {
|
||||
const scale = 1.05;
|
||||
Matter.Body.scale(that, scale, scale);
|
||||
if (that.mass < massLimit) setTimeout(expand, 20, that, massLimit);
|
||||
};
|
||||
expand(body[len], 200)
|
||||
|
||||
//make a block body to replace this one
|
||||
//this body is too big to leave behind in the normal way mobs.replace()
|
||||
const len = body.length;
|
||||
const v = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //might help with vertex collision issue, not sure
|
||||
body[len] = Matter.Bodies.fromVertices(this.position.x, this.position.y, v);
|
||||
Matter.Body.setVelocity(body[len], { x: 0, y: -3 });
|
||||
Matter.Body.setAngularVelocity(body[len], this.angularVelocity);
|
||||
body[len].collisionFilter.category = cat.body;
|
||||
body[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet;
|
||||
body[len].classType = "body";
|
||||
World.add(engine.world, body[len]); //add to world
|
||||
const expand = function(that, massLimit) {
|
||||
const scale = 1.05;
|
||||
Matter.Body.scale(that, scale, scale);
|
||||
if (that.mass < massLimit) setTimeout(expand, 20, that, massLimit);
|
||||
};
|
||||
expand(body[len], 200)
|
||||
function unlockExit() {
|
||||
if (simulation.isHorizontalFlipped) {
|
||||
level.exit.x = -5500 - 100;
|
||||
} else {
|
||||
level.exit.x = 5500;
|
||||
}
|
||||
level.exit.y = -330;
|
||||
Matter.World.remove(engine.world, map[map.length - 1]);
|
||||
map.splice(map.length - 1, 1);
|
||||
simulation.draw.setPaths(); //redraw map draw path
|
||||
}
|
||||
|
||||
function unlockExit() {
|
||||
level.exit.x = 5500;
|
||||
level.exit.y = -330;
|
||||
Matter.World.remove(engine.world, map[map.length - 1]);
|
||||
map.splice(map.length - 1, 1);
|
||||
simulation.draw.setPaths(); //redraw map draw path
|
||||
}
|
||||
//add lore level as next level if player took lore tech earlier in the game
|
||||
if (lore.techCount > (lore.techGoal - 1) && !simulation.isCheating) {
|
||||
simulation.makeTextLog(`<span class="lore-text">undefined</span> <span class='color-symbol'>=</span> ${lore.techCount}/${lore.techGoal}<br>level.levels.push("<span class='lore-text'>null</span>")`);
|
||||
level.levels.push("null")
|
||||
//remove block map element so exit is clear
|
||||
unlockExit()
|
||||
} else { //reset game
|
||||
let count = 0
|
||||
|
||||
//add lore level as next level if player took lore tech earlier in the game
|
||||
if (lore.techCount > (lore.techGoal - 1) && !simulation.isCheating) {
|
||||
simulation.makeTextLog(`<span class="lore-text">undefined</span> <span class='color-symbol'>=</span> ${lore.techCount}/${lore.techGoal}<br>level.levels.push("<span class='lore-text'>null</span>")`);
|
||||
level.levels.push("null")
|
||||
//remove block map element so exit is clear
|
||||
unlockExit()
|
||||
} else { //reset game
|
||||
let count = 0
|
||||
|
||||
function loop() {
|
||||
if (!simulation.paused) {
|
||||
count++
|
||||
if (count < 600) {
|
||||
if (count === 1) simulation.makeTextLog(`<em>//enter testing mode to set level.levels.length to <strong>Infinite</strong></em>`);
|
||||
if (!(count % 60)) simulation.makeTextLog(`simulation.analysis <span class='color-symbol'>=</span> ${(count/60- Math.random()).toFixed(3)}`);
|
||||
} else if (count === 600) {
|
||||
simulation.makeTextLog(`simulation.analysis <span class='color-symbol'>=</span> 1 <em>//analysis complete</em>`);
|
||||
} else if (count === 720) {
|
||||
simulation.makeTextLog(`<span class="lore-text">undefined</span> <span class='color-symbol'>=</span> ${lore.techCount}/${lore.techGoal}`)
|
||||
} else if (count === 900) {
|
||||
simulation.makeTextLog(`World.clear(engine.world) <em>//simulation successful</em>`);
|
||||
} else if (count === 1140) {
|
||||
// tech.isImmortal = false;
|
||||
// m.death()
|
||||
// m.alive = false;
|
||||
// simulation.paused = true;
|
||||
// m.health = 0;
|
||||
// m.displayHealth();
|
||||
document.getElementById("health").style.display = "none"
|
||||
document.getElementById("health-bg").style.display = "none"
|
||||
document.getElementById("text-log").style.opacity = 0; //fade out any active text logs
|
||||
document.getElementById("fade-out").style.opacity = 1; //slowly fades out
|
||||
// build.shareURL(false)
|
||||
function loop() {
|
||||
if (!simulation.paused) {
|
||||
count++
|
||||
if (count < 600) {
|
||||
if (count === 1) simulation.makeTextLog(`<em>//enter testing mode to set level.levels.length to <strong>Infinite</strong></em>`);
|
||||
if (!(count % 60)) simulation.makeTextLog(`simulation.analysis <span class='color-symbol'>=</span> ${(count/60- Math.random()).toFixed(3)}`);
|
||||
} else if (count === 600) {
|
||||
simulation.makeTextLog(`simulation.analysis <span class='color-symbol'>=</span> 1 <em>//analysis complete</em>`);
|
||||
} else if (count === 720) {
|
||||
simulation.makeTextLog(`<span class="lore-text">undefined</span> <span class='color-symbol'>=</span> ${lore.techCount}/${lore.techGoal}`)
|
||||
} else if (count === 900) {
|
||||
simulation.makeTextLog(`World.clear(engine.world) <em>//simulation successful</em>`);
|
||||
} else if (count === 1140) {
|
||||
// tech.isImmortal = false;
|
||||
// m.death()
|
||||
// m.alive = false;
|
||||
// simulation.paused = true;
|
||||
// m.health = 0;
|
||||
// m.displayHealth();
|
||||
document.getElementById("health").style.display = "none"
|
||||
document.getElementById("health-bg").style.display = "none"
|
||||
document.getElementById("text-log").style.opacity = 0; //fade out any active text logs
|
||||
document.getElementById("fade-out").style.opacity = 1; //slowly fades out
|
||||
// build.shareURL(false)
|
||||
setTimeout(function() {
|
||||
simulation.paused = true;
|
||||
World.clear(engine.world);
|
||||
Engine.clear(engine);
|
||||
simulation.splashReturn();
|
||||
}, 6000);
|
||||
return
|
||||
}
|
||||
}
|
||||
if (simulation.testing) {
|
||||
unlockExit()
|
||||
setTimeout(function() {
|
||||
simulation.paused = true;
|
||||
World.clear(engine.world);
|
||||
Engine.clear(engine);
|
||||
simulation.splashReturn();
|
||||
}, 6000);
|
||||
return
|
||||
simulation.makeTextLog(`level.levels.length <span class='color-symbol'>=</span> <strong>Infinite</strong>`);
|
||||
}, 1500);
|
||||
} else {
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
}
|
||||
if (simulation.testing) {
|
||||
unlockExit()
|
||||
setTimeout(function() {
|
||||
simulation.makeTextLog(`level.levels.length <span class='color-symbol'>=</span> <strong>Infinite</strong>`);
|
||||
}, 1500);
|
||||
} else {
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
// for (let i = 0; i < 3; i++)
|
||||
level.difficultyIncrease(simulation.difficultyMode) //ramp up damage
|
||||
//remove power Ups, to avoid spamming console
|
||||
function removeAll(array) {
|
||||
for (let i = 0; i < array.length; ++i) Matter.World.remove(engine.world, array[i]);
|
||||
}
|
||||
removeAll(powerUp);
|
||||
powerUp = [];
|
||||
// for (let i = 0; i < 3; i++)
|
||||
level.difficultyIncrease(simulation.difficultyMode) //ramp up damage
|
||||
//remove power Ups, to avoid spamming console
|
||||
function removeAll(array) {
|
||||
for (let i = 0; i < array.length; ++i) Matter.World.remove(engine.world, array[i]);
|
||||
}
|
||||
removeAll(powerUp);
|
||||
powerUp = [];
|
||||
|
||||
//pull in particles
|
||||
for (let i = 0, len = body.length; i < len; ++i) {
|
||||
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, body[i].position)), 65)
|
||||
const pushUp = Vector.add(velocity, { x: 0, y: -0.5 })
|
||||
Matter.Body.setVelocity(body[i], Vector.add(body[i].velocity, pushUp));
|
||||
}
|
||||
//damage all mobs
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (mob[i] !== this) mob[i].damage(Infinity, true);
|
||||
}
|
||||
//pull in particles
|
||||
for (let i = 0, len = body.length; i < len; ++i) {
|
||||
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, body[i].position)), 65)
|
||||
const pushUp = Vector.add(velocity, { x: 0, y: -0.5 })
|
||||
Matter.Body.setVelocity(body[i], Vector.add(body[i].velocity, pushUp));
|
||||
}
|
||||
//damage all mobs
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (mob[i] !== this) mob[i].damage(Infinity, true);
|
||||
}
|
||||
|
||||
//draw stuff
|
||||
for (let i = 0, len = 22; i < len; i++) {
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: this.position.x,
|
||||
y: this.position.y,
|
||||
radius: (i + 1) * 150,
|
||||
color: `rgba(255,255,255,0.17)`,
|
||||
time: 5 * (len - i + 1)
|
||||
});
|
||||
//draw stuff
|
||||
for (let i = 0, len = 22; i < len; i++) {
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: this.position.x,
|
||||
y: this.position.y,
|
||||
radius: (i + 1) * 150,
|
||||
color: `rgba(255,255,255,0.17)`,
|
||||
time: 5 * (len - i + 1)
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
me.onDamage = function() {};
|
||||
@@ -448,7 +455,7 @@ const spawn = {
|
||||
}
|
||||
const len = (this.totalCycles / 400 + simulation.difficulty / 2 - 30) / 15
|
||||
for (let i = 0; i < len; i++) {
|
||||
spawn.randomLevelBoss(3000 + 2000 * (Math.random() - 0.5), -1100 + 200 * (Math.random() - 0.5))
|
||||
spawn.randomLevelBoss(-3000 + 2000 * (Math.random() - 0.5), -1100 + 200 * (Math.random() - 0.5))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1760,8 +1767,8 @@ const spawn = {
|
||||
y: me.position.y
|
||||
},
|
||||
bodyB: me,
|
||||
stiffness: 0.001,
|
||||
damping: 1
|
||||
stiffness: 0.0001,
|
||||
damping: 0.3
|
||||
});
|
||||
World.add(engine.world, me.constraint);
|
||||
}, 2000); //add in a delay in case the level gets flipped left right
|
||||
@@ -1876,18 +1883,18 @@ const spawn = {
|
||||
mobs.spawn(x, y, 3, radius, "#f08");
|
||||
let me = mob[mob.length - 1];
|
||||
|
||||
setTimeout(() => { //fix mob in place, but allow rotation
|
||||
me.constraint = Constraint.create({
|
||||
pointA: {
|
||||
x: me.position.x,
|
||||
y: me.position.y
|
||||
},
|
||||
bodyB: me,
|
||||
stiffness: 0.0001,
|
||||
damping: 1
|
||||
});
|
||||
World.add(engine.world, me.constraint);
|
||||
}, 2000); //add in a delay in case the level gets flipped left right
|
||||
// setTimeout(() => { //fix mob in place, but allow rotation
|
||||
// me.constraint = Constraint.create({
|
||||
// pointA: {
|
||||
// x: me.position.x,
|
||||
// y: me.position.y
|
||||
// },
|
||||
// bodyB: me,
|
||||
// stiffness: 0.00001,
|
||||
// damping: 0.1
|
||||
// });
|
||||
// World.add(engine.world, me.constraint);
|
||||
// }, 2000); //add in a delay in case the level gets flipped left right
|
||||
|
||||
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
|
||||
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
|
||||
|
||||
113
js/tech.js
113
js/tech.js
@@ -14,6 +14,14 @@
|
||||
}
|
||||
}
|
||||
lore.techCount = 0;
|
||||
if (simulation.isCommunityMaps || simulation.isCheating) {
|
||||
for (let i = 0, len = tech.tech.length; i < len; i++) {
|
||||
if (tech.tech[i].isLore) {
|
||||
tech.tech[i].frequency = 0;
|
||||
tech.tech[i].count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// tech.removeJunkTechFromPool();
|
||||
// tech.removeLoreTechFromPool();
|
||||
// tech.addLoreTechToPool();
|
||||
@@ -742,7 +750,7 @@
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
allowed() {
|
||||
return tech.explosiveRadius === 1 && !tech.isSmallExplosion && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1)
|
||||
return tech.explosiveRadius === 1 && !tech.isSmallExplosion && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isBlockExplosion)
|
||||
},
|
||||
requires: "an explosive damage source, not ammonium nitrate or nitroglycerin",
|
||||
effect: () => {
|
||||
@@ -759,7 +767,7 @@
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
allowed() {
|
||||
return !tech.isExplodeRadio && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1)
|
||||
return !tech.isExplodeRadio && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isBlockExplosion)
|
||||
},
|
||||
requires: "an explosive damage source, not iridium-192",
|
||||
effect: () => {
|
||||
@@ -776,7 +784,7 @@
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
allowed() {
|
||||
return !tech.isExplodeRadio && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1)
|
||||
return !tech.isExplodeRadio && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isBlockExplosion)
|
||||
},
|
||||
requires: "an explosive damage source, not iridium-192",
|
||||
effect: () => {
|
||||
@@ -794,7 +802,7 @@
|
||||
frequency: 2,
|
||||
isBadRandomOption: true,
|
||||
allowed() {
|
||||
return !tech.isRewindGrenade && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField)
|
||||
return !tech.isRewindGrenade && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.isBlockExplosion)
|
||||
},
|
||||
requires: "an explosive damage source, not causality bombs",
|
||||
effect: () => {
|
||||
@@ -812,7 +820,7 @@
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
allowed() {
|
||||
return !tech.isExplodeRadio && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1)
|
||||
return !tech.isExplodeRadio && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isBlockExplosion)
|
||||
},
|
||||
requires: "an explosive damage source, not iridium-192",
|
||||
effect() {
|
||||
@@ -830,7 +838,7 @@
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
allowed() {
|
||||
return tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isMissileField || tech.isExplodeMob || tech.isPulseLaser
|
||||
return tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isMissileField || tech.isExplodeMob || tech.isPulseLaser || tech.isBlockExplosion
|
||||
},
|
||||
requires: "an explosive damage source",
|
||||
effect: () => {
|
||||
@@ -881,7 +889,7 @@
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
allowed() {
|
||||
return (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1) && !tech.sporesOnDeath && !tech.nailsDeathMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.iceIXOnDeath
|
||||
return (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isBlockExplosion) && !tech.sporesOnDeath && !tech.nailsDeathMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.iceIXOnDeath
|
||||
},
|
||||
requires: "an explosive damage source, no other mob death tech",
|
||||
effect: () => {
|
||||
@@ -3063,27 +3071,6 @@
|
||||
},
|
||||
remove() {}
|
||||
},
|
||||
{
|
||||
name: "booby trap",
|
||||
description: "drop a <strong>mine</strong> after picking up a <strong>power up</strong><br>add <strong>9</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
frequencyDefault: 1,
|
||||
allowed() {
|
||||
return tech.duplicationChance() > 0
|
||||
},
|
||||
requires: "some power up duplication",
|
||||
effect() {
|
||||
tech.isMineDrop = true;
|
||||
if (tech.isMineDrop) b.mine(m.pos, { x: 0, y: 0 }, 0, tech.isMineAmmoBack)
|
||||
tech.addJunkTechToPool(13)
|
||||
},
|
||||
remove() {
|
||||
tech.isMineDrop = false;
|
||||
if (this.count > 0) tech.removeJunkTechFromPool(13)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "unified field theory",
|
||||
description: `in the <strong>pause</strong> menu, change your <strong class='color-f'>field</strong><br>by <strong>clicking</strong> on your <strong class='color-f'>field's</strong> box`,
|
||||
@@ -4079,6 +4066,27 @@
|
||||
tech.isMineSentry = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "booby trap",
|
||||
description: "drop a <strong>mine</strong> after picking up a <strong>power up</strong><br>add <strong>13</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return tech.isMineSentry === true || tech.isLaserMine === true || tech.isMineAmmoBack === true
|
||||
},
|
||||
requires: "some mine tech",
|
||||
effect() {
|
||||
tech.isMineDrop = true;
|
||||
if (tech.isMineDrop) b.mine(m.pos, { x: 0, y: 0 }, 0, tech.isMineAmmoBack)
|
||||
tech.addJunkTechToPool(13)
|
||||
},
|
||||
remove() {
|
||||
tech.isMineDrop = false;
|
||||
if (this.count > 0) tech.removeJunkTechFromPool(13)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "mycelial fragmentation",
|
||||
description: "<strong class='color-p' style='letter-spacing: 2px;'>sporangium</strong> release an extra <strong class='color-p' style='letter-spacing: 2px;'>spore</strong><br> once a <strong>second</strong> during their <strong>growth</strong> phase",
|
||||
@@ -4613,35 +4621,14 @@
|
||||
//************************************************** field
|
||||
//************************************************** tech
|
||||
//**************************************************
|
||||
// {
|
||||
// name: "frequency resonance",
|
||||
// description: "<strong>standing wave harmonics</strong> shield is retuned<br>increase <strong>size</strong> and <strong>deflecting</strong> efficiency by <strong>50%</strong>",
|
||||
// isFieldTech: true,
|
||||
// maxCount: 9,
|
||||
// count: 0,
|
||||
// frequency: 2,
|
||||
// allowed() {
|
||||
// return m.fieldUpgrades[m.fieldMode].name === "standing wave harmonics"
|
||||
// },
|
||||
// requires: "standing wave harmonics",
|
||||
// effect() {
|
||||
// tech.frequencyResonance = this.count + 1 // +1 because count updates later
|
||||
// m.fieldRange = 175 + 175 * 0.25 * tech.frequencyResonance
|
||||
// m.fieldShieldingScale = Math.pow(0.5, tech.frequencyResonance)
|
||||
// },
|
||||
// remove() {
|
||||
// m.fieldRange = 175;
|
||||
// m.fieldShieldingScale = 1;
|
||||
// tech.frequencyResonance = 0
|
||||
// }
|
||||
// },
|
||||
|
||||
{
|
||||
name: "spherical harmonics",
|
||||
description: "<strong>standing wave</strong> oscillates in a 3rd dimension<br>increasing <strong>deflecting</strong> efficiency by <strong>40%</strong>",
|
||||
isFieldTech: true,
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
frequency: 4,
|
||||
frequency: 3,
|
||||
allowed() {
|
||||
return m.fieldUpgrades[m.fieldMode].name === "standing wave harmonics"
|
||||
},
|
||||
@@ -4659,7 +4646,7 @@
|
||||
},
|
||||
{
|
||||
name: "expansion",
|
||||
description: "using <strong>standing wave</strong> field drains <strong class='color-f'>energy</strong><br>to temporarily <strong>expand</strong> its <strong>radius</strong>",
|
||||
description: "using <strong>standing wave</strong> field uses <strong class='color-f'>energy</strong><br>to temporarily <strong>expand</strong> its <strong>radius</strong>",
|
||||
// description: "use <strong class='color-f'>energy</strong> to <strong>expand</strong> <strong>standing wave</strong><br>the field slowly <strong>contracts</strong> when not used",
|
||||
isFieldTech: true,
|
||||
maxCount: 1,
|
||||
@@ -5053,6 +5040,24 @@
|
||||
tech.isPlasmaRange = 1;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "tokamak",
|
||||
description: "throwing a <strong class='color-block'>block</strong> convert it into <strong class='color-f'>energy</strong><br>and a <strong class='color-laser'>laser</strong> pulse <strong class='color-e'>explosion</strong> cluster",
|
||||
isFieldTech: true,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
allowed() {
|
||||
return m.fieldUpgrades[m.fieldMode].name === "plasma torch"
|
||||
},
|
||||
requires: "plasma torch",
|
||||
effect() {
|
||||
tech.isBlockExplosion = true;
|
||||
},
|
||||
remove() {
|
||||
tech.isBlockExplosion = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "micro-extruder",
|
||||
description: "<strong class='color-plasma'>plasma</strong> <strong>torch</strong> extrudes a thin <strong class='color-plasma'>hot</strong> wire<br>increases <strong class='color-d'>damage</strong>, <strong class='color-f'>energy</strong> drain, and <strong>lag</strong>",
|
||||
@@ -6876,7 +6881,6 @@
|
||||
droneCycleReduction: null,
|
||||
droneEnergyReduction: null,
|
||||
isNoHeals: null,
|
||||
// frequencyResonance: null,
|
||||
isAlwaysFire: null,
|
||||
isDroneRespawn: null,
|
||||
deathSpawns: null,
|
||||
@@ -6897,5 +6901,6 @@
|
||||
isSneakAttack: null,
|
||||
isFallingDamage: null,
|
||||
harmonics: null,
|
||||
isStandingWaveExpand: null
|
||||
isStandingWaveExpand: null,
|
||||
isBlockExplosion: null
|
||||
}
|
||||
35
todo.txt
35
todo.txt
@@ -1,9 +1,17 @@
|
||||
******************************************************** NEXT PATCH ********************************************************
|
||||
|
||||
tech: tokamak - instead of throwing a block convert it into energy and a pulse explosion
|
||||
requires plasma
|
||||
|
||||
standing wave field no longer gives 25% harm reduction
|
||||
standing wave field can now block through walls
|
||||
|
||||
bug fixes
|
||||
|
||||
******************************************************** BUGS ********************************************************
|
||||
|
||||
a couple times people have reported the final boss dropping extra bodies on death
|
||||
|
||||
figure out how to undo ship mode
|
||||
if you die in ship mode it spawns with m.look set to non ship methods
|
||||
look is set in many tech and in startGame
|
||||
@@ -26,23 +34,24 @@ is there a way to check if the player is stuck inside the map or block
|
||||
|
||||
******************************************************** TODO ********************************************************
|
||||
|
||||
spherical harmonics improve blocking efficiency
|
||||
9x stacks
|
||||
gain cool multi ellipse atomic graphic
|
||||
1st stack gives 3x atomic graphic
|
||||
more stacks give more ellipse for atomic graphic
|
||||
spherical harmonics unlocks tech that increases shield radius when you hold field input
|
||||
throwing a block removes the block and fires a pulse with a size that scales with the size of the block
|
||||
must have a charge above some threshold
|
||||
plasma field tech
|
||||
gain 100 energy?
|
||||
|
||||
tech plasma : plasma length increases then decreases as you hold down the field button (like stabbing with a spear)
|
||||
grows to 1.5 longer after 0.3 seconds, then returns to normal length over 1 second, until field is pressed again
|
||||
extra energy is drained when field is longer
|
||||
|
||||
what about the single axis graphic?
|
||||
tech: at the start of a new level remove 5 research and spawn a second boss
|
||||
|
||||
what about the single axis graphic? (find the code in standing wave harmonic)
|
||||
maybe just save it for a mob
|
||||
maybe use it on lore
|
||||
|
||||
tech: picking up heal power ups when at full health does harm equal to the heal values
|
||||
benefit on pick up: get 1% damage
|
||||
|
||||
draw a rotating ring, like a 3-D spinning ring effect
|
||||
an ellipse the has sine function on one of it's parameters
|
||||
|
||||
buttons can now on/off boosts
|
||||
|
||||
energy conservation 6% damage recovered as energy
|
||||
@@ -50,8 +59,6 @@ energy conservation 6% damage recovered as energy
|
||||
junk tech
|
||||
|
||||
Weak Anthropic Principle: you get a second chance at life, but ....
|
||||
|
||||
negative effect: remove air control
|
||||
|
||||
mob: molecule shapes - 2 separate mobs joined by a bond
|
||||
use constraints: just spawn 2x or 3x groupings
|
||||
@@ -193,10 +200,6 @@ flavor - your bullets destroy blocks
|
||||
power ups
|
||||
spores
|
||||
|
||||
tech plasma : plasma length increases then decreases as you hold down the field button (like stabbing with a spear)
|
||||
grows to 1.5 longer after 0.3 seconds, then returns to normal length over 1 second, until field is pressed again
|
||||
extra energy is drained when field is longer
|
||||
|
||||
using a reroll gives 3 options for tech, and 3 options for guns/fields/tech
|
||||
or 6 options for tech (rewrite tech selection to work with 1-6 options)
|
||||
the second stack of 3 tech could have repeats, so you don't have to write new tech code
|
||||
|
||||
Reference in New Issue
Block a user