wide laser
tech: antiscience - 100% damage, but lose 11 health when you pick up a tech tech: laser widebeam + output coupler can now stack up to 9x (was 1x) but it not longer works with tech: slow light propagation
This commit is contained in:
224
js/bullet.js
224
js/bullet.js
@@ -1358,6 +1358,81 @@ const b = {
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
},
|
||||
laserMine(position, velocity = { x: 0, y: -8 }) {
|
||||
const me = bullet.length;
|
||||
bullet[me] = Bodies.polygon(position.x, position.y, 3, 25, {
|
||||
bulletType: "mine",
|
||||
angle: mech.angle,
|
||||
friction: 0,
|
||||
frictionAir: 0.05,
|
||||
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()),
|
||||
drain: tech.isLaserDiode * tech.laserFieldDrain,
|
||||
isArmed: false,
|
||||
torqueMagnitude: 0.000003 * (Math.round(Math.random()) ? 1 : -1),
|
||||
range: 1500,
|
||||
endCycle: Infinity,
|
||||
classType: "bullet",
|
||||
collisionFilter: {
|
||||
category: cat.bullet,
|
||||
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
|
||||
},
|
||||
beforeDmg() {},
|
||||
onEnd() {
|
||||
if (tech.isMineAmmoBack && (!this.isArmed || Math.random() < 0.2)) { //get ammo back from tech.isMineAmmoBack
|
||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||
if (b.guns[i].name === "mine") {
|
||||
b.guns[i].ammo++
|
||||
simulation.updateGunHUD();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
do() {
|
||||
if (!(simulation.cycle % this.lookFrequency) && mech.energy > this.drain) { //find mob targets
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (
|
||||
Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)) < 2000000 &&
|
||||
mob[i].dropPowerUp &&
|
||||
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
|
||||
Matter.Query.ray(body, this.position, mob[i].position).length === 0
|
||||
) {
|
||||
this.do = this.laserSpin
|
||||
this.endCycle = simulation.cycle + 300
|
||||
// if (this.angularSpeed < 0.01) this.torque += this.inertia * this.torqueMagnitude * 5 //spin
|
||||
this.isArmed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
reflections: Math.max(0, tech.laserReflections - 2),
|
||||
laserSpin() {
|
||||
//drain energy
|
||||
if (mech.energy > this.drain) {
|
||||
mech.energy -= this.drain
|
||||
if (this.angularSpeed < 0.02) this.torque += this.inertia * this.torqueMagnitude //spin
|
||||
|
||||
//fire lasers
|
||||
ctx.strokeStyle = "#f00";
|
||||
ctx.lineWidth = 1.5
|
||||
// ctx.globalAlpha = 1;
|
||||
ctx.beginPath();
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const where = this.vertices[i]
|
||||
const endPoint = Vector.add(where, Vector.mult(Vector.normalise(Vector.sub(where, this.position)), 2500))
|
||||
b.laser(where, endPoint, tech.laserDamage * 10, this.reflections, true)
|
||||
}
|
||||
ctx.stroke();
|
||||
// ctx.globalAlpha = 1;
|
||||
}
|
||||
}
|
||||
})
|
||||
Matter.Body.setVelocity(bullet[me], velocity);
|
||||
World.add(engine.world, bullet[me]); //add bullet to world
|
||||
},
|
||||
mine(where, velocity, angle = 0, isAmmoBack = false) {
|
||||
const bIndex = bullet.length;
|
||||
bullet[bIndex] = Bodies.rectangle(where.x, where.y, 45, 16, {
|
||||
@@ -1530,7 +1605,7 @@ const b = {
|
||||
friction: 0,
|
||||
frictionAir: 0.025,
|
||||
thrust: (tech.isFastSpores ? 0.001 : 0.0004) * (1 + 0.3 * (Math.random() - 0.5)),
|
||||
dmg: tech.isMutualism ? 8 : 4, //2x bonus damage from tech.isMutualism
|
||||
dmg: tech.isMutualism ? 10 : 4, //2x bonus damage from tech.isMutualism
|
||||
lookFrequency: 100 + Math.floor(117 * Math.random()),
|
||||
classType: "bullet",
|
||||
collisionFilter: {
|
||||
@@ -1793,7 +1868,7 @@ const b = {
|
||||
) {
|
||||
//pick up nearby power ups
|
||||
if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 60000 && !simulation.isChoosing) {
|
||||
powerUps.onPickUp(this.position);
|
||||
powerUps.onPickUp(powerUp[i]);
|
||||
powerUp[i].effect();
|
||||
Matter.World.remove(engine.world, powerUp[i]);
|
||||
powerUp.splice(i, 1);
|
||||
@@ -3312,91 +3387,9 @@ const b = {
|
||||
have: false,
|
||||
fire() {
|
||||
if (tech.isLaserMine) { //laser mine
|
||||
const me = bullet.length;
|
||||
const position = mech.pos
|
||||
bullet[me] = Bodies.polygon(position.x, position.y, 3, 25, {
|
||||
bulletType: "mine",
|
||||
angle: mech.angle,
|
||||
friction: 0,
|
||||
frictionAir: 0.05,
|
||||
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()),
|
||||
drain: tech.isLaserDiode * tech.laserFieldDrain,
|
||||
isArmed: false,
|
||||
torqueMagnitude: 0.000003 * (Math.round(Math.random()) ? 1 : -1),
|
||||
range: 1500,
|
||||
endCycle: Infinity,
|
||||
classType: "bullet",
|
||||
collisionFilter: {
|
||||
category: cat.bullet,
|
||||
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
|
||||
},
|
||||
beforeDmg() {},
|
||||
onEnd() {
|
||||
if (tech.isMineAmmoBack && (!this.isArmed || Math.random() < 0.2)) { //get ammo back from tech.isMineAmmoBack
|
||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||
if (b.guns[i].name === "mine") {
|
||||
b.guns[i].ammo++
|
||||
simulation.updateGunHUD();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
do() {
|
||||
if (!(simulation.cycle % this.lookFrequency) && mech.energy > this.drain) { //find mob targets
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (
|
||||
Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)) < 2000000 &&
|
||||
mob[i].dropPowerUp &&
|
||||
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
|
||||
Matter.Query.ray(body, this.position, mob[i].position).length === 0
|
||||
) {
|
||||
this.do = this.laserSpin
|
||||
this.endCycle = simulation.cycle + 300
|
||||
// if (this.angularSpeed < 0.01) this.torque += this.inertia * this.torqueMagnitude * 5 //spin
|
||||
this.isArmed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
reflections: Math.max(0, tech.laserReflections - 2),
|
||||
laserSpin() {
|
||||
//drain energy
|
||||
if (mech.energy > this.drain) {
|
||||
mech.energy -= this.drain
|
||||
if (this.angularSpeed < 0.02) this.torque += this.inertia * this.torqueMagnitude //spin
|
||||
|
||||
//fire lasers
|
||||
ctx.strokeStyle = "#f00";
|
||||
ctx.lineWidth = 1.5
|
||||
// ctx.globalAlpha = 1;
|
||||
ctx.beginPath();
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const where = this.vertices[i]
|
||||
const endPoint = Vector.add(where, Vector.mult(Vector.normalise(Vector.sub(where, this.position)), 2500))
|
||||
b.laser(where, endPoint, tech.laserDamage * 10, this.reflections, true)
|
||||
}
|
||||
ctx.stroke();
|
||||
// ctx.globalAlpha = 1;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// if (tech.isMineSentry) {
|
||||
// bullet[me].endCycle = simulation.cycle + 480
|
||||
// bullet[me].do = bullet[me].laserSpin
|
||||
// bullet[me].isArmed = true
|
||||
// Matter.Body.setAngularVelocity(bullet[me], 3000 * bullet[me].torqueMagnitude);
|
||||
// }
|
||||
let speed = mech.crouch ? 50 : 20
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: speed * Math.cos(mech.angle),
|
||||
y: speed * Math.sin(mech.angle)
|
||||
});
|
||||
World.add(engine.world, bullet[me]); //add bullet to world
|
||||
const speed = mech.crouch ? 50 : 20
|
||||
const velocity = { x: speed * Math.cos(mech.angle), y: speed * Math.sin(mech.angle) }
|
||||
b.laserMine(mech.pos, velocity)
|
||||
} else { //normal mines
|
||||
const pos = {
|
||||
x: mech.pos.x + 30 * Math.cos(mech.angle),
|
||||
@@ -4008,9 +4001,13 @@ const b = {
|
||||
mech.fireCDcycle = mech.cycle
|
||||
mech.energy -= mech.fieldRegen + tech.laserFieldDrain * tech.isLaserDiode
|
||||
const dmg = 0.55 * tech.laserDamage // 3.5 * 0.55 = 200% more damage
|
||||
const eye = {
|
||||
x: mech.pos.x + 16 * Math.cos(mech.angle),
|
||||
y: mech.pos.y + 16 * Math.sin(mech.angle)
|
||||
}
|
||||
const wideLaser = function(where = {
|
||||
x: mech.pos.x + 20 * Math.cos(mech.angle),
|
||||
y: mech.pos.y + 20 * Math.sin(mech.angle)
|
||||
x: mech.pos.x + 30 * Math.cos(mech.angle),
|
||||
y: mech.pos.y + 30 * Math.sin(mech.angle)
|
||||
}, angle = mech.angle) {
|
||||
ctx.strokeStyle = "#f00";
|
||||
ctx.lineWidth = 8
|
||||
@@ -4018,26 +4015,35 @@ const b = {
|
||||
ctx.beginPath();
|
||||
const off = 7.5
|
||||
b.laser(where, {
|
||||
x: where.x + 3000 * Math.cos(angle),
|
||||
y: where.y + 3000 * Math.sin(angle)
|
||||
x: eye.x + 3000 * Math.cos(angle),
|
||||
y: eye.y + 3000 * Math.sin(angle)
|
||||
}, dmg, 0, true, 0.3)
|
||||
|
||||
for (let i = 1; i < tech.wideLaser; i++) {
|
||||
let whereOff = Vector.add(where, {
|
||||
x: i * off * Math.cos(angle + Math.PI / 2),
|
||||
y: i * off * Math.sin(angle + Math.PI / 2)
|
||||
})
|
||||
b.laser(whereOff, {
|
||||
x: whereOff.x + 3000 * Math.cos(angle),
|
||||
y: whereOff.y + 3000 * Math.sin(angle)
|
||||
}, dmg, 0, true, 0.3)
|
||||
if (Matter.Query.ray(map, eye, whereOff).length === 0) {
|
||||
ctx.moveTo(eye.x, eye.y)
|
||||
ctx.lineTo(whereOff.x, whereOff.y)
|
||||
b.laser(whereOff, {
|
||||
x: whereOff.x + 3000 * Math.cos(angle),
|
||||
y: whereOff.y + 3000 * Math.sin(angle)
|
||||
}, dmg, 0, true, 0.3)
|
||||
}
|
||||
whereOff = Vector.add(where, {
|
||||
x: i * off * Math.cos(angle - Math.PI / 2),
|
||||
y: i * off * Math.sin(angle - Math.PI / 2)
|
||||
})
|
||||
b.laser(whereOff, {
|
||||
x: whereOff.x + 3000 * Math.cos(angle),
|
||||
y: whereOff.y + 3000 * Math.sin(angle)
|
||||
}, dmg, 0, true, 0.3)
|
||||
if (Matter.Query.ray(map, eye, whereOff).length === 0) {
|
||||
ctx.moveTo(eye.x, eye.y)
|
||||
ctx.lineTo(whereOff.x, whereOff.y)
|
||||
b.laser(whereOff, {
|
||||
x: whereOff.x + 3000 * Math.cos(angle),
|
||||
y: whereOff.y + 3000 * Math.sin(angle)
|
||||
}, dmg, 0, true, 0.3)
|
||||
}
|
||||
}
|
||||
ctx.stroke();
|
||||
ctx.globalAlpha = 1;
|
||||
@@ -4052,21 +4058,7 @@ const b = {
|
||||
mech.fireCDcycle = mech.cycle
|
||||
mech.energy -= mech.fieldRegen + tech.laserFieldDrain * tech.isLaserDiode
|
||||
const dmg = 0.4 * tech.laserDamage // 3.5 * 0.55 = 200% more damage
|
||||
ctx.strokeStyle = "#f00";
|
||||
let spacing, len
|
||||
if (tech.wideLaser === 3) {
|
||||
ctx.lineWidth = 2
|
||||
spacing = 2
|
||||
len = 10 + tech.historyLaser * 5
|
||||
} else if (tech.wideLaser === 4) {
|
||||
ctx.lineWidth = 3
|
||||
spacing = 1
|
||||
len = 15 + tech.historyLaser * 5
|
||||
} else {
|
||||
ctx.lineWidth = 1
|
||||
spacing = 5
|
||||
len = 5 + tech.historyLaser * 5
|
||||
}
|
||||
const spacing = Math.ceil(5.2 - 0.2 * tech.historyLaser)
|
||||
ctx.beginPath();
|
||||
b.laser({
|
||||
x: mech.pos.x + 20 * Math.cos(mech.angle),
|
||||
@@ -4075,7 +4067,7 @@ const b = {
|
||||
x: mech.pos.x + 3000 * Math.cos(mech.angle),
|
||||
y: mech.pos.y + 3000 * Math.sin(mech.angle)
|
||||
}, dmg, 0, true, 0.2);
|
||||
for (let i = 1; i < len; i++) {
|
||||
for (let i = 1, len = 5 + tech.historyLaser * 5; i < len; i++) {
|
||||
const history = mech.history[(mech.cycle - i * spacing) % 600]
|
||||
b.laser({
|
||||
x: history.position.x + 20 * Math.cos(history.angle),
|
||||
@@ -4085,6 +4077,8 @@ const b = {
|
||||
y: history.position.y + 3000 * Math.sin(history.angle) - mech.yPosDifference
|
||||
}, dmg, 0, true, 0.2);
|
||||
}
|
||||
ctx.strokeStyle = "#f00";
|
||||
ctx.lineWidth = 1
|
||||
ctx.stroke();
|
||||
}
|
||||
},
|
||||
|
||||
13
js/level.js
13
js/level.js
@@ -19,14 +19,14 @@ const level = {
|
||||
// mech.setField("plasma torch")
|
||||
// b.giveGuns("laser")
|
||||
// tech.isMineSentry = true
|
||||
// tech.giveTech("foam fractionation")
|
||||
// tech.giveTech("diffuse beam")
|
||||
// tech.giveTech("missile-bot")
|
||||
// tech.giveTech("nail-bot")
|
||||
// for (let i = 0; i < 15; i++) tech.giveTech("plasma jet")
|
||||
|
||||
level.intro(); //starting level
|
||||
// level.testing(); //not in rotation
|
||||
// level.escape() //after the final boss, ending
|
||||
// level.null() //after the final boss, ending
|
||||
// level.final() //final boss level
|
||||
// level.gauntlet(); //before final boss level
|
||||
// level.testChamber() //less mobs, more puzzle
|
||||
@@ -61,11 +61,8 @@ const level = {
|
||||
b.respawnBots();
|
||||
mech.resetHistory();
|
||||
if (tech.isArmorFromPowerUps) {
|
||||
const gain = Math.min(0.03 * powerUps.totalPowerUps, 0.42)
|
||||
tech.armorFromPowerUps += gain
|
||||
tech.armorFromPowerUps += Math.min(0.03 * powerUps.totalPowerUps, 0.42)
|
||||
mech.setMaxHealth();
|
||||
// if (powerUps.totalPowerUps) simulation.makeTextLog("<span style='font-size:115%;'> max health increased by " + (gain * 100).toFixed(0) + "%</span>", 300)
|
||||
simulation.makeTextLog(`<span class='color-var'>mech</span>.<span class='color-h'>maxHealth</span> <span class='color-symbol'>+=</span> ${(gain).toFixed(2)}`)
|
||||
}
|
||||
if (tech.isHealLowHealth) {
|
||||
const len = Math.floor((mech.maxHealth - mech.health) / 0.5)
|
||||
@@ -98,7 +95,7 @@ const level = {
|
||||
//******************************************************************************************************************
|
||||
//******************************************************************************************************************
|
||||
//******************************************************************************************************************
|
||||
escape() {
|
||||
null() {
|
||||
const hazardSlime = level.hazard(-1775, 150, 3575, 650, 0.01, "hsla(160, 100%, 35%,0.75)")
|
||||
// const hazardLaser1 = level.hazard(-475, -800, 1, 800, 0.4, "#50f", true) //laser
|
||||
// const hazardLaser2 = level.hazard(475, -800, 1, 800, 0.4, "#50f", true) //laser
|
||||
@@ -165,7 +162,7 @@ const level = {
|
||||
// spawn.mapRect(450, -820, 50, 25); //edge shelf ceiling
|
||||
// spawn.bodyRect(1540, -1110, 300, 25, 0.9);
|
||||
|
||||
setTimeout(() => { simulation.makeTextLog(`test`) }, 3000);
|
||||
// setTimeout(() => { simulation.makeTextLog(`test`) }, 3000);
|
||||
|
||||
|
||||
|
||||
|
||||
64
js/lore.js
64
js/lore.js
@@ -1,5 +1,28 @@
|
||||
const lore = {
|
||||
|
||||
alfie: {
|
||||
color: "#e06",
|
||||
text: function(say, isSpeech = false) {
|
||||
simulation.makeTextLog(`input.audio(<span style="color:#888; font-size: 70%;">${Date.now()} ms</span>)<span class='color-symbol'>:</span> "<span style="color:${this.color};">${say}</span>"`, Infinity);
|
||||
if (isSpeech) this.speech(say)
|
||||
},
|
||||
speech: function(say) {
|
||||
var utterance = new SpeechSynthesisUtterance(say);
|
||||
utterance.lang = "en-GB";
|
||||
speechSynthesis.speak(utterance);
|
||||
}
|
||||
},
|
||||
zoe: {
|
||||
color: "#f50",
|
||||
text: function(say, isSpeech = false) {
|
||||
simulation.makeTextLog(`input.audio(<span style="color:#888; font-size: 70%;">${Date.now()} ms</span>)<span class='color-symbol'>:</span> "<span style="color:${this.color};">${say}</span>"`, Infinity);
|
||||
if (isSpeech) this.speech(say)
|
||||
},
|
||||
speech: function(say) {
|
||||
var utterance = new SpeechSynthesisUtterance(say);
|
||||
utterance.lang = "en-AU";
|
||||
speechSynthesis.speak(utterance);
|
||||
}
|
||||
},
|
||||
dialogue: [
|
||||
``,
|
||||
``,
|
||||
@@ -8,27 +31,18 @@ const lore = {
|
||||
|
||||
}
|
||||
}
|
||||
/* ending outline
|
||||
if no cheats
|
||||
after final boss is cleared, player enters a level with no mobs
|
||||
level maybe has some environmental damage, so player has an option to die at any time
|
||||
player can see text output between two colors of text strings (scientists)
|
||||
audio.ambient(current time and date)<br> "text"
|
||||
player reads a conversation between the two colors of text
|
||||
first time win on east or normal they talk about:
|
||||
how many runs the player has done
|
||||
they guess why
|
||||
player is asked to stand on an in game button to enable the vocoder
|
||||
they reveal the player is running simulations, and it isn't real
|
||||
they ask the player to communicate
|
||||
jump twice if you understand
|
||||
they ask the player to enter console commands
|
||||
give ammo or tech or something
|
||||
They tell the play a console command to permanently enable custom and testing mode (in local storage)
|
||||
players can use this command in the future to enable custom and testing without beating the game even if local storage is wiped
|
||||
they then tell the player the command to increase the difficulty and the command to restart the game.
|
||||
If you win on hard or why:
|
||||
they give the player and option to exit the simulation and entre the real world
|
||||
simulation.exit()
|
||||
This wipes all local storage, and closes the browser tab
|
||||
*/
|
||||
|
||||
|
||||
// speech: function(say) {
|
||||
// var utterance = new SpeechSynthesisUtterance(say);
|
||||
// //msg.voice = voices[10]; // Note: some voices don't support altering params
|
||||
// //msg.voiceURI = 'native';
|
||||
// //utterance.volume = 1; // 0 to 1
|
||||
// //utterance.rate = 1; // 0.1 to 10
|
||||
// //utterance.pitch = 1; //0 to 2
|
||||
// //utterance.text = 'Hello World';
|
||||
// //http://stackoverflow.com/questions/14257598/what-are-language-codes-for-voice-recognition-languages-in-chromes-implementati
|
||||
// //de-DE en-GB fr-FR en-US en-AU
|
||||
// utterance.lang = "en-GB";
|
||||
// speechSynthesis.speak(utterance);
|
||||
// }
|
||||
25
js/player.js
25
js/player.js
@@ -481,10 +481,9 @@ const mech = {
|
||||
},
|
||||
baseHealth: 1,
|
||||
setMaxHealth() {
|
||||
const set = mech.baseHealth + tech.bonusHealth + tech.armorFromPowerUps
|
||||
simulation.makeTextLog(`<span class='color-var'>mech</span>.maxHealth <span class='color-symbol'>=</span> ${set}`)
|
||||
mech.maxHealth = set
|
||||
if(mech.health > mech.maxHealth) mech.health = mech.maxHealth;
|
||||
mech.maxHealth = mech.baseHealth + tech.bonusHealth + tech.armorFromPowerUps
|
||||
simulation.makeTextLog(`<span class='color-var'>mech</span>.<span class='color-h'>maxHealth</span> <span class='color-symbol'>=</span> ${mech.maxHealth.toFixed(2)}`)
|
||||
if (mech.health > mech.maxHealth) mech.health = mech.maxHealth;
|
||||
mech.displayHealth();
|
||||
},
|
||||
|
||||
@@ -900,19 +899,19 @@ const mech = {
|
||||
},
|
||||
setMaxEnergy() {
|
||||
mech.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus
|
||||
simulation.makeTextLog(`<span class='color-var'>mech</span>.maxEnergy <span class='color-symbol'>=</span> ${mech.maxEnergy}`)
|
||||
simulation.makeTextLog(`<span class='color-var'>mech</span>.<span class='color-f'>maxEnergy</span> <span class='color-symbol'>=</span> ${(mech.maxEnergy.toFixed(2))}`)
|
||||
},
|
||||
fieldMeterColor: "#0cf",
|
||||
drawFieldMeter(bgColor = "rgba(0, 0, 0, 0.4)", range = 60) {
|
||||
if (mech.energy < mech.maxEnergy) {
|
||||
mech.energy += mech.fieldRegen;
|
||||
if (mech.energy < 0) mech.energy = 0
|
||||
ctx.fillStyle = bgColor;
|
||||
const xOff = mech.pos.x - mech.radius * mech.maxEnergy
|
||||
const yOff = mech.pos.y - 50
|
||||
ctx.fillRect(xOff, yOff, range * mech.maxEnergy, 10);
|
||||
ctx.fillStyle = mech.fieldMeterColor;
|
||||
ctx.fillRect(xOff, yOff, range * mech.energy, 10);
|
||||
if (mech.energy < 0) mech.energy = 0
|
||||
} else if (mech.energy > mech.maxEnergy + 0.05) {
|
||||
ctx.fillStyle = bgColor;
|
||||
const xOff = mech.pos.x - mech.radius * mech.energy
|
||||
@@ -1142,7 +1141,7 @@ const mech = {
|
||||
y: powerUp[i].velocity.y * 0.11
|
||||
});
|
||||
if (dist2 < 5000 && !simulation.isChoosing) { //use power up if it is close enough
|
||||
powerUps.onPickUp(mech.pos);
|
||||
powerUps.onPickUp(powerUp[i]);
|
||||
Matter.Body.setVelocity(player, { //player knock back, after grabbing power up
|
||||
x: player.velocity.x + powerUp[i].velocity.x / player.mass * 5,
|
||||
y: player.velocity.y + powerUp[i].velocity.y / player.mass * 5
|
||||
@@ -1502,11 +1501,12 @@ const mech = {
|
||||
mech.hold = function() {
|
||||
if (mech.energy > mech.maxEnergy - 0.02 && mech.fieldCDcycle < mech.cycle && !input.field && bullet.length < 200) {
|
||||
if (tech.isSporeField) {
|
||||
const len = Math.floor(5 + 4 * Math.random())
|
||||
mech.energy -= len * 0.105;
|
||||
// const len = Math.floor(5 + 4 * Math.random())
|
||||
const len = Math.ceil(mech.energy * 10)
|
||||
mech.energy = 0;
|
||||
for (let i = 0; i < len; i++) b.spore(mech.pos)
|
||||
} else if (tech.isMissileField) {
|
||||
mech.energy -= 0.55;
|
||||
mech.energy -= 0.5;
|
||||
b.missile({ x: mech.pos.x, y: mech.pos.y - 40 }, -Math.PI / 2, 0, 1)
|
||||
} else if (tech.isIceField) {
|
||||
mech.energy -= 0.057;
|
||||
@@ -1926,6 +1926,7 @@ const mech = {
|
||||
|
||||
if (mech.energy < mech.maxEnergy) { // replaces mech.drawFieldMeter() with custom code
|
||||
mech.energy += mech.fieldRegen;
|
||||
if (mech.energy < 0) mech.energy = 0
|
||||
const xOff = mech.pos.x - mech.radius * mech.maxEnergy
|
||||
const yOff = mech.pos.y - 50
|
||||
ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
|
||||
@@ -2145,7 +2146,7 @@ const mech = {
|
||||
y: powerUp[i].velocity.y * 0.11
|
||||
});
|
||||
if (dist2 < 5000 && !simulation.isChoosing) { //use power up if it is close enough
|
||||
powerUps.onPickUp(powerUp[i].position);
|
||||
powerUps.onPickUp(powerUp[i]);
|
||||
powerUp[i].effect();
|
||||
Matter.World.remove(engine.world, powerUp[i]);
|
||||
powerUp.splice(i, 1);
|
||||
@@ -2388,7 +2389,7 @@ const mech = {
|
||||
});
|
||||
if (dist2 < 1000 && !simulation.isChoosing) { //use power up if it is close enough
|
||||
mech.fieldRange *= 0.8
|
||||
powerUps.onPickUp(powerUp[i].position);
|
||||
powerUps.onPickUp(powerUp[i]);
|
||||
powerUp[i].effect();
|
||||
Matter.World.remove(engine.world, powerUp[i]);
|
||||
powerUp.splice(i, 1);
|
||||
|
||||
@@ -461,15 +461,16 @@ const powerUps = {
|
||||
}
|
||||
}
|
||||
},
|
||||
onPickUp(where) {
|
||||
onPickUp(who) {
|
||||
if (tech.isTechDamage && who.name === "tech") mech.damage(0.11)
|
||||
if (tech.isMassEnergy) mech.energy += 2.5;
|
||||
if (tech.isMineDrop) b.mine({
|
||||
x: where.x,
|
||||
y: where.y
|
||||
}, {
|
||||
x: 0,
|
||||
y: 0
|
||||
}, 0, tech.isMineAmmoBack)
|
||||
if (tech.isMineDrop) {
|
||||
if (tech.isLaserMine) { //laser mine
|
||||
b.laserMine(who.position)
|
||||
} else {
|
||||
b.mine(who.position, { x: 0, y: 0 }, 0, tech.isMineAmmoBack)
|
||||
}
|
||||
}
|
||||
},
|
||||
giveRandomAmmo() {
|
||||
const ammoTarget = Math.floor(Math.random() * (b.guns.length));
|
||||
|
||||
@@ -514,7 +514,6 @@ const simulation = {
|
||||
input.endKeySensing();
|
||||
b.removeAllGuns();
|
||||
simulation.isNoPowerUps = false;
|
||||
|
||||
tech.setupAllTech(); //sets tech to default values
|
||||
tech.laserBotCount = 0;
|
||||
tech.orbitBotCount = 0;
|
||||
@@ -529,23 +528,23 @@ const simulation = {
|
||||
powerUps.totalPowerUps = 0;
|
||||
powerUps.research.research = 0;
|
||||
mech.setFillColors();
|
||||
mech.maxHealth = 1
|
||||
mech.maxEnergy = 1
|
||||
mech.energy = 1
|
||||
// mech.maxHealth = 1
|
||||
// mech.maxEnergy = 1
|
||||
// mech.energy = 1
|
||||
mech.hole.isOn = false
|
||||
simulation.paused = false;
|
||||
engine.timing.timeScale = 1;
|
||||
simulation.fpsCap = simulation.fpsCapDefault;
|
||||
simulation.isAutoZoom = true;
|
||||
simulation.makeGunHUD();
|
||||
mech.drop();
|
||||
mech.holdingTarget = null
|
||||
mech.health = 0.25;
|
||||
mech.displayHealth();
|
||||
mech.alive = true;
|
||||
simulation.lastLogTime = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
level.onLevel = 0;
|
||||
level.levelsCleared = 0;
|
||||
|
||||
//resetting difficulty
|
||||
simulation.dmgScale = 0; //increases in level.difficultyIncrease
|
||||
b.dmgScale = 1; //decreases in level.difficultyIncrease
|
||||
@@ -560,6 +559,14 @@ const simulation = {
|
||||
document.getElementById("text-log").style.opacity = 0;
|
||||
document.getElementById("fade-out").style.opacity = 0;
|
||||
document.title = "n-gon";
|
||||
|
||||
mech.alive = true;
|
||||
mech.setMaxHealth()
|
||||
mech.health = 0;
|
||||
mech.addHealth(0.25)
|
||||
mech.drop();
|
||||
mech.holdingTarget = null
|
||||
|
||||
//set to default field
|
||||
mech.fieldMode = 0;
|
||||
// simulation.makeTextLog(`${simulation.SVGrightMouse}<strong style='font-size:30px;'> ${mech.fieldUpgrades[mech.fieldMode].name}</strong><br><span class='faded'></span><br>${mech.fieldUpgrades[mech.fieldMode].description}`, 600);
|
||||
@@ -573,45 +580,36 @@ const simulation = {
|
||||
// <br>input.key.field <span class='color-symbol'>=</span> ["<span class='color-text'>${input.key.field}</span>", "<span class='color-text'>right mouse</span>"]
|
||||
// <br><span class='color-var'>mech</span>.field.description <span class='color-symbol'>=</span> "<span class='color-text'>${mech.fieldUpgrades[mech.fieldMode].description}</span>"
|
||||
// `, 800);
|
||||
|
||||
|
||||
let delay = 500
|
||||
const step = 150
|
||||
setTimeout(function() {
|
||||
simulation.makeTextLog(`input.key.up<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.up}</span>", "<span class='color-text'>ArrowUp</span>"]`);
|
||||
}, delay);
|
||||
delay += step
|
||||
}, delay += step);
|
||||
setTimeout(function() {
|
||||
simulation.makeTextLog(`input.key.left<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.left}</span>", "<span class='color-text'>ArrowLeft</span>"]`);
|
||||
}, delay);
|
||||
delay += step
|
||||
}, delay += step);
|
||||
setTimeout(function() {
|
||||
simulation.makeTextLog(`input.key.down<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.down}</span>", "<span class='color-text'>ArrowDown</span>"]`);
|
||||
}, delay);
|
||||
delay += step
|
||||
}, delay += step);
|
||||
setTimeout(function() {
|
||||
simulation.makeTextLog(`input.key.right<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.right}</span>", "<span class='color-text'>ArrowRight</span>"]`);
|
||||
}, delay);
|
||||
delay += 1000
|
||||
}, delay += step);
|
||||
setTimeout(function() {
|
||||
simulation.makeTextLog(`<br><span class='color-var'>mech</span>.fieldMode <span class='color-symbol'>=</span> "<span class='color-text'>${mech.fieldUpgrades[mech.fieldMode].name}</span>"`);
|
||||
}, delay);
|
||||
delay += step
|
||||
}, delay += step);
|
||||
setTimeout(function() {
|
||||
simulation.makeTextLog(`input.key.field<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.field}</span>", "<span class='color-text'>MouseRight</span>"]`);
|
||||
}, delay);
|
||||
// delay += step
|
||||
// setTimeout(function() {
|
||||
// simulation.makeTextLog(`<span class='color-var'>mech</span>.field.description<br>"<span class='color-text'>${mech.fieldUpgrades[mech.fieldMode].description}</span>"`);
|
||||
// }, delay);
|
||||
|
||||
}, delay += step);
|
||||
|
||||
mech.setField(mech.fieldMode)
|
||||
// mech.energy = 0;
|
||||
//exit testing
|
||||
if (simulation.testing) {
|
||||
simulation.testing = false;
|
||||
simulation.loop = simulation.normalLoop
|
||||
if (simulation.isConstructionMode) {
|
||||
document.getElementById("construct").style.display = 'none'
|
||||
}
|
||||
if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'none'
|
||||
}
|
||||
simulation.isCheating = false
|
||||
simulation.firstRun = false;
|
||||
|
||||
47
js/tech.js
47
js/tech.js
@@ -77,6 +77,7 @@ const tech = {
|
||||
},
|
||||
damageFromTech() {
|
||||
let dmg = mech.fieldDamage
|
||||
if (tech.isTechDamage) dmg *= 2
|
||||
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
|
||||
if (tech.isLowEnergyDamage) dmg *= 1 + Math.max(0, 1 - mech.energy) * 0.5
|
||||
if (tech.isMaxEnergyTech) dmg *= 1.4
|
||||
@@ -185,7 +186,7 @@ const tech = {
|
||||
count: 0,
|
||||
isNonRefundable: true,
|
||||
allowed() {
|
||||
return tech.isDamageForGuns || tech.isFireRateForGuns
|
||||
return (tech.isDamageForGuns || tech.isFireRateForGuns) && (b.inventory.length + 5) < b.guns.length
|
||||
},
|
||||
requires: "arsenal or cyclic rate boost",
|
||||
effect() {
|
||||
@@ -1181,9 +1182,9 @@ const tech = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return !tech.isEnergyLoss && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isRewindGun && !tech.isSpeedHarm && mech.fieldUpgrades[mech.fieldMode].name !== "negative mass field" && !tech.isHealLowHealth
|
||||
return !tech.isEnergyLoss && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isRewindGun && !tech.isSpeedHarm && mech.fieldUpgrades[mech.fieldMode].name !== "negative mass field" && !tech.isHealLowHealth && !tech.isTechDamage
|
||||
},
|
||||
requires: "not exothermic process, piezoelectricity, CPT, 1st law, negative mass",
|
||||
requires: "not exothermic process, piezoelectricity, CPT, 1st law, negative mass , ...",
|
||||
effect: () => {
|
||||
mech.health = 0
|
||||
// mech.displayHealth();
|
||||
@@ -1282,9 +1283,9 @@ const tech = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return tech.isEnergyLoss && mech.maxEnergy < 1.1 && !tech.isMissileField && !tech.isSporeField && !tech.isRewindAvoidDeath
|
||||
return tech.isEnergyLoss && mech.maxEnergy < 1.1 && !tech.isSporeField && !tech.isRewindAvoidDeath
|
||||
},
|
||||
requires: "exothermic process, not max energy increase, CPT, missile or spore nano-scale",
|
||||
requires: "exothermic process, not max energy increase, CPT, or spore nano-scale",
|
||||
effect() {
|
||||
tech.isMaxEnergyTech = true;
|
||||
mech.setMaxEnergy()
|
||||
@@ -1400,7 +1401,7 @@ const tech = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mech.health < 0.6 || build.isCustomSelection
|
||||
return mech.health < 0.5 || build.isCustomSelection
|
||||
},
|
||||
requires: "health below 60",
|
||||
effect() {
|
||||
@@ -1409,6 +1410,21 @@ const tech = {
|
||||
remove() {
|
||||
tech.isLowHealthDmg = false;
|
||||
}
|
||||
}, {
|
||||
name: "antiscience",
|
||||
description: "increase <strong class='color-d'>damage</strong> by <strong>100%</strong><br>lose <strong>11</strong> <strong class='color-h'>health</strong> when you pick up a <strong class='color-m'>tech</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return (mech.harmReduction() < 1 || tech.healthDrain || tech.isLowHealthDmg || tech.isHealthRecovery || tech.isHealLowHealth || tech.largerHeals > 1 || tech.isPerpetualHeal) && !tech.isEnergyHealth
|
||||
},
|
||||
requires: "negative feedback or extra healing tech or harm reduction, not mass-energy",
|
||||
effect() {
|
||||
tech.isTechDamage = true;
|
||||
},
|
||||
remove() {
|
||||
tech.isTechDamage = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "entropy exchange",
|
||||
@@ -2822,7 +2838,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "mutualism",
|
||||
description: "increase <strong class='color-p' style='letter-spacing: 2px;'>spore</strong> <strong class='color-d'>damage</strong> by <strong>100%</strong><br><strong class='color-p' style='letter-spacing: 2px;'>spores</strong> borrow <strong>0.5</strong> <strong class='color-h'>health</strong> until they <strong>die</strong>",
|
||||
description: "increase <strong class='color-p' style='letter-spacing: 2px;'>spore</strong> <strong class='color-d'>damage</strong> by <strong>150%</strong><br><strong class='color-p' style='letter-spacing: 2px;'>spores</strong> borrow <strong>0.5</strong> <strong class='color-h'>health</strong> until they <strong>die</strong>",
|
||||
isGunTech: true,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -3093,9 +3109,9 @@ const tech = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.beamSplitter && !tech.isPulseLaser
|
||||
return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.beamSplitter && !tech.isPulseLaser && !tech.historyLaser
|
||||
},
|
||||
requires: "laser, not specular reflection<br>not diffraction grating",
|
||||
requires: "laser, not specular reflection, diffraction grating, slow light",
|
||||
effect() {
|
||||
if (tech.wideLaser === 0) tech.wideLaser = 3
|
||||
tech.isWideLaser = true;
|
||||
@@ -3115,14 +3131,14 @@ const tech = {
|
||||
name: "output coupler",
|
||||
description: "<strong>widen</strong> diffuse <strong class='color-laser'>laser</strong> beam by <strong>40%</strong><br>increase full beam <strong class='color-d'>damage</strong> by <strong>40%</strong>",
|
||||
isGunTech: true,
|
||||
maxCount: 1,
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return tech.haveGunCheck("laser") && tech.isWideLaser
|
||||
},
|
||||
requires: "laser, not specular reflection<br>not diffraction grating",
|
||||
effect() {
|
||||
tech.wideLaser = 4
|
||||
tech.wideLaser += 2
|
||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||
if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod()
|
||||
}
|
||||
@@ -3145,9 +3161,9 @@ const tech = {
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.beamSplitter && !tech.isPulseLaser
|
||||
return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.beamSplitter && !tech.isPulseLaser && !tech.isWideLaser
|
||||
},
|
||||
requires: "laser, not specular reflection<br>not diffraction grating",
|
||||
requires: "laser, not specular reflection, diffraction grating, diffuse beam",
|
||||
effect() {
|
||||
// this.description = `add 5 more <strong>laser</strong> beams into into your past`
|
||||
tech.historyLaser++
|
||||
@@ -3434,7 +3450,7 @@ const tech = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mech.maxEnergy > 0.99 && mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab)
|
||||
return mech.maxEnergy > 0.5 && mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab)
|
||||
},
|
||||
requires: "nano-scale manufacturing",
|
||||
effect() {
|
||||
@@ -4057,5 +4073,6 @@ const tech = {
|
||||
isIceIX: null,
|
||||
isDupDamage: null,
|
||||
isFireRateForGuns: null,
|
||||
cyclicImmunity: null
|
||||
cyclicImmunity: null,
|
||||
isTechDamage: null
|
||||
}
|
||||
15
todo.txt
15
todo.txt
@@ -1,12 +1,8 @@
|
||||
******************************************************** NEXT PATCH ********************************************************
|
||||
|
||||
tech: active cooling - 15% faster fire rate for each gun in your inventory
|
||||
tech: specialist - spawn a random power up for each gun in your inventory
|
||||
(not available in custom, requires tech: generalist)
|
||||
tech: complex spin-statistics - become immune to harm for 1s every 7s
|
||||
requires Pauli exclusion
|
||||
|
||||
even less difficulty ramp after killing final boss
|
||||
tech: antiscience - 100% damage, but lose 11 health when you pick up a tech
|
||||
tech: laser widebeam + output coupler can now stack up to 9x (was 1x)
|
||||
but it not longer works with tech: slow light propagation
|
||||
|
||||
******************************************************** BUGS ********************************************************
|
||||
|
||||
@@ -27,8 +23,7 @@ CPT check for crouch after rewind
|
||||
|
||||
******************************************************** TODO ********************************************************
|
||||
|
||||
tech "Circadian Rhythm": Become immune to harm for 1 second every 10 seconds while playing.
|
||||
|
||||
tech: can't fire while moving, get attack speed and damage
|
||||
|
||||
bot that follows the players history
|
||||
could have the same shape as the mech circle head
|
||||
@@ -437,7 +432,7 @@ ending outline
|
||||
jump twice if you understand
|
||||
they ask the player to enter console commands
|
||||
give ammo or tech or something
|
||||
They tell the play a console command to permanently enable custom and testing mode (in local storage)
|
||||
They tell the player a console command to permanently enable custom and testing mode (in local storage)
|
||||
players can use this command in the future to enable custom and testing without beating the game even if local storage is wiped
|
||||
they then tell the player the command to increase the difficulty and the command to restart the game.
|
||||
If you win on hard or why:
|
||||
|
||||
Reference in New Issue
Block a user