isotropic radiator

"pressure wave" renamed "phonon"
  tech packet length removed
  most wave beam tech is now compatible with phonon

wave beam tech: isotropic radiator - phonon has shorter range but expands in every direction

drone tech: torque bursts - teleport towards targets and do 30% more collision damage

irradiated drones do 33% more damage, 33% less collisions damage
   5% more ammo, 30% less range, don't lose duration on collisions

pseudoscience only gets 3 free rerolls per tech
This commit is contained in:
landgreen
2021-07-15 06:14:56 -07:00
parent 95adf9fa06
commit f590cfc99e
11 changed files with 324 additions and 296 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -2039,8 +2039,8 @@ const b = {
friction: 0.05, friction: 0.05,
frictionAir: 0, frictionAir: 0,
restitution: 1, restitution: 1,
dmg: 0.24, //damage done in addition to the damage from momentum dmg: 0.24 + 0.12 * tech.isDroneTeleport, //damage done in addition to the damage from momentum
lookFrequency: 80 + Math.floor(23 * Math.random()), lookFrequency: 70 + Math.floor(17 * Math.random()),
endCycle: simulation.cycle + Math.floor((950 + 420 * Math.random()) * tech.isBulletsLastLonger * tech.droneCycleReduction) + 140 + RADIUS * 5, endCycle: simulation.cycle + Math.floor((950 + 420 * Math.random()) * tech.isBulletsLastLonger * tech.droneCycleReduction) + 140 + RADIUS * 5,
classType: "bullet", classType: "bullet",
collisionFilter: { collisionFilter: {
@@ -2110,11 +2110,24 @@ const b = {
} }
} }
} }
//blink towards mobs
if (tech.isDroneTeleport && this.lockedOn) {
const sub = Vector.sub(this.lockedOn.position, this.position);
const distMag = Vector.magnitude(sub);
const unit = Vector.normalise(sub)
Matter.Body.setVelocity(this, Vector.mult(unit, Math.max(20, this.speed * 1.5)));
ctx.beginPath();
ctx.moveTo(this.position.x, this.position.y);
Matter.Body.translate(this, Vector.mult(unit, Math.min(350, distMag - this.lockedOn.radius + 10)));
ctx.lineTo(this.position.x, this.position.y);
ctx.lineWidth = RADIUS * 2;
ctx.strokeStyle = "rgba(0,0,0,0.5)";
ctx.stroke();
}
//power ups //power ups
if (!this.isImproved && !simulation.isChoosing && !tech.isExtraMaxEnergy) { if (!this.isImproved && !simulation.isChoosing && !tech.isExtraMaxEnergy) {
if (this.lockedOn) { if (this.lockedOn) {
//grab, but don't lock onto nearby power up for (let i = 0, len = powerUp.length; i < len; ++i) { //grab, but don't lock onto nearby power up
for (let i = 0, len = powerUp.length; i < len; ++i) {
if ( if (
Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 &&
(powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) && (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) &&
@@ -2223,8 +2236,8 @@ const b = {
inertia: Infinity, inertia: Infinity,
friction: 0, friction: 0,
frictionAir: 0, frictionAir: 0,
restitution: 0.8 + 0.199 * Math.random(), restitution: 0.4 + 0.199 * Math.random(),
dmg: 0.24, //damage done in addition to the damage from momentum dmg: 0, //0.24 damage done in addition to the damage from momentum and radiation
lookFrequency: 120 + Math.floor(23 * Math.random()), lookFrequency: 120 + Math.floor(23 * Math.random()),
endCycle: simulation.cycle + Math.floor((900 + 120 * Math.random()) * tech.isBulletsLastLonger / tech.droneRadioDamage) + 140 + RADIUS * 5, endCycle: simulation.cycle + Math.floor((900 + 120 * Math.random()) * tech.isBulletsLastLonger / tech.droneRadioDamage) + 140 + RADIUS * 5,
classType: "bullet", classType: "bullet",
@@ -2239,7 +2252,7 @@ const b = {
deathCycles: 110 + RADIUS * 5, deathCycles: 110 + RADIUS * 5,
isImproved: false, isImproved: false,
radioRadius: 0, radioRadius: 0,
maxRadioRadius: 355 + Math.floor(150 * Math.random()), maxRadioRadius: 300 + Math.floor(100 * Math.random()),
beforeDmg(who) { beforeDmg(who) {
const unit = Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), -20) //move away from target after hitting const unit = Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), -20) //move away from target after hitting
Matter.Body.setVelocity(this, { Matter.Body.setVelocity(this, {
@@ -2247,10 +2260,10 @@ const b = {
y: unit.y y: unit.y
}); });
this.lockedOn = null this.lockedOn = null
if (this.endCycle > simulation.cycle + this.deathCycles) { // if (this.endCycle > simulation.cycle + this.deathCycles) {
this.endCycle -= 60 // this.endCycle -= 60
if (simulation.cycle + this.deathCycles > this.endCycle) this.endCycle = simulation.cycle + this.deathCycles // if (simulation.cycle + this.deathCycles > this.endCycle) this.endCycle = simulation.cycle + this.deathCycles
} // }
}, },
onEnd() { onEnd() {
if (tech.isDroneRespawn) { if (tech.isDroneRespawn) {
@@ -2280,7 +2293,7 @@ const b = {
//aoe damage to mobs //aoe damage to mobs
for (let i = 0, len = mob.length; i < len; i++) { for (let i = 0, len = mob.length; i < len; i++) {
if (Vector.magnitude(Vector.sub(mob[i].position, this.position)) < this.radioRadius + mob[i].radius) { if (Vector.magnitude(Vector.sub(mob[i].position, this.position)) < this.radioRadius + mob[i].radius) {
let dmg = b.dmgScale * 0.06 * tech.droneRadioDamage //neutron bombs dmg = 0.09 let dmg = b.dmgScale * 0.1 * tech.droneRadioDamage //neutron bombs dmg = 0.09
if (Matter.Query.ray(map, mob[i].position, this.position).length > 0) dmg *= 0.25 //reduce damage if a wall is in the way if (Matter.Query.ray(map, mob[i].position, this.position).length > 0) dmg *= 0.25 //reduce damage if a wall is in the way
if (mob[i].shield) dmg *= 3 // to make up for the /5 that shields normally take if (mob[i].shield) dmg *= 3 // to make up for the /5 that shields normally take
mob[i].damage(dmg); mob[i].damage(dmg);
@@ -2695,12 +2708,7 @@ const b = {
} }
for (let i = 0, len = totalPermanentBots - totalTechToConvert; i < len; i++) tech.tech[index].effect(); //also convert any permanent bots that didn't come from a tech for (let i = 0, len = totalPermanentBots - totalTechToConvert; i < len; i++) tech.tech[index].effect(); //also convert any permanent bots that didn't come from a tech
//in experiment mode set the unselect color for bot tech that was converted //in experiment mode set the unselect color for bot tech that was converted
if (build.isExperimentSelection) { // if (build.isExperimentSelection) { }
}
}, },
clearPermanentBots() { clearPermanentBots() {
for (let i = 0; i < bullet.length; i++) { for (let i = 0; i < bullet.length; i++) {
@@ -3991,7 +3999,10 @@ const b = {
propagationRate: 20, propagationRate: 20,
waves: [], //used in longitudinal mode waves: [], //used in longitudinal mode
chooseFireMethod() { //set in simulation.startGame chooseFireMethod() { //set in simulation.startGame
if (tech.isLongitudinal) { if (tech.is360Longitudinal) {
this.fire = this.fire360Longitudinal
this.do = this.do360Longitudinal
} else if (tech.isLongitudinal) {
this.fire = this.fireLongitudinal this.fire = this.fireLongitudinal
this.do = this.doLongitudinal this.do = this.doLongitudinal
} else { } else {
@@ -4000,10 +4011,94 @@ const b = {
} }
}, },
do() {}, do() {},
doLongitudinal() { do360Longitudinal() {
ctx.strokeStyle = "rgba(0,0,0,0.2)" //"000"; ctx.strokeStyle = "rgba(0,0,0,0.6)" //"000";
ctx.lineWidth = 2 ctx.lineWidth = 2 * tech.wavePacketDamage
ctx.beginPath(); ctx.beginPath();
const end = 75 * Math.sqrt(tech.isBulletsLastLonger) * tech.waveBeamSpeed / Math.sqrt(tech.waveReflections * 0.5) //should equal about 1060
const damage = 2 * b.dmgScale * tech.wavePacketDamage * tech.waveBeamDamage //damage is lower for large radius mobs, since they feel the waves longer
for (let i = this.waves.length - 1; i > -1; i--) {
//draw wave
ctx.moveTo(this.waves[i].position.x + this.waves[i].radius, this.waves[i].position.y)
ctx.arc(this.waves[i].position.x, this.waves[i].position.y, this.waves[i].radius, 0, 2 * Math.PI);
// collisions
if (!m.isBodiesAsleep) {
for (let j = 0, len = mob.length; j < len; j++) {
const dist = Vector.magnitude(Vector.sub(this.waves[i].position, mob[j].position))
const r = mob[j].radius + 30
if (dist + r > this.waves[i].radius && dist - r < this.waves[i].radius) {
//make them shake around
if (!mob[j].isBadTarget) {
mob[j].force.x += 0.01 * (Math.random() - 0.5) * mob[j].mass
mob[j].force.y += 0.01 * (Math.random() - 0.5) * mob[j].mass
}
if (!mob[j].isShielded) {
Matter.Body.setVelocity(mob[j], { //friction
x: mob[j].velocity.x * 0.93,
y: mob[j].velocity.y * 0.93
});
//draw vibes
let vertices = mob[j].vertices;
const vibe = 50 + mob[j].radius * 0.15
ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
for (let k = 1; k < vertices.length; k++) {
ctx.lineTo(vertices[k].x + vibe * (Math.random() - 0.5), vertices[k].y + vibe * (Math.random() - 0.5));
}
ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
//damage
mob[j].locatePlayer();
mob[j].damage(damage / Math.sqrt(mob[j].radius));
}
}
}
for (let j = 0, len = body.length; j < len; j++) {
const dist = Vector.magnitude(Vector.sub(this.waves[i].position, body[j].position))
const r = 20
if (dist + r > this.waves[i].radius && dist - r < this.waves[i].radius) {
//make them shake around
body[j].force.x += 0.01 * (Math.random() - 0.5) * body[j].mass
body[j].force.y += (0.01 * (Math.random() - 0.5) - simulation.g * 0.25) * body[j].mass //remove force of gravity
//draw vibes
let vertices = body[j].vertices;
const vibe = 25
ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
for (let k = 1; k < vertices.length; k++) {
ctx.lineTo(vertices[k].x + vibe * (Math.random() - 0.5), vertices[k].y + vibe * (Math.random() - 0.5));
}
ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
}
}
this.waves[i].radius += tech.waveBeamSpeed * this.waves[i].expanding //expand / move
}
// if (this.waves[i].radius > end) this.waves.splice(i, 1) //end
if (this.waves[i].radius > end) {
this.waves[i].expanding = -1
this.waves[i].reflection--
if (this.waves[i].reflection < 1) this.waves.splice(i, 1) //end
} else if (this.waves[i].radius < 25) {
this.waves[i].expanding = 1
this.waves[i].reflection--
if (this.waves[i].reflection < 1) this.waves.splice(i, 1) //end
}
}
ctx.stroke();
},
fire360Longitudinal() {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 3 : 8) * b.fireCDscale); // cool down
this.waves.push({
position: { x: m.pos.x, y: m.pos.y, },
radius: 25,
reflection: tech.waveReflections,
expanding: true
})
},
doLongitudinal() {
ctx.strokeStyle = "rgba(0,0,0,0.6)" //"000";
ctx.lineWidth = 2 * tech.wavePacketDamage
ctx.beginPath();
const end = 125 * tech.isBulletsLastLonger * tech.waveBeamSpeed / Math.sqrt(tech.waveReflections * 0.5) //should equal about 1767
const damage = 2 * b.dmgScale * tech.wavePacketDamage * tech.waveBeamDamage //damage is lower for large radius mobs, since they feel the waves longer
for (let i = this.waves.length - 1; i > -1; i--) { for (let i = this.waves.length - 1; i > -1; i--) {
const v1 = Vector.add(this.waves[i].position, Vector.mult(this.waves[i].unit1, this.waves[i].radius)) const v1 = Vector.add(this.waves[i].position, Vector.mult(this.waves[i].unit1, this.waves[i].radius))
@@ -4018,23 +4113,25 @@ const b = {
for (let j = 0; j < hits.length; j++) { for (let j = 0; j < hits.length; j++) {
const who = hits[j].body const who = hits[j].body
//make them shake around //make them shake around
who.force.x += 0.01 * (Math.random() - 0.5) * who.mass if (!who.isBadTarget) {
who.force.y += 0.01 * (Math.random() - 0.5) * who.mass who.force.x += 0.01 * (Math.random() - 0.5) * who.mass
Matter.Body.setVelocity(who, { //friction who.force.y += 0.01 * (Math.random() - 0.5) * who.mass
x: who.velocity.x * 0.95, }
y: who.velocity.y * 0.95 if (!who.isShielded) {
}); Matter.Body.setVelocity(who, { //friction
x: who.velocity.x * 0.95,
let vertices = who.vertices; y: who.velocity.y * 0.95
const vibe = 50 + who.radius * 0.15 });
ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); let vertices = who.vertices;
for (let j = 1; j < vertices.length; j++) { const vibe = 50 + who.radius * 0.15
ctx.lineTo(vertices[j].x + vibe * (Math.random() - 0.5), vertices[j].y + vibe * (Math.random() - 0.5)); ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
for (let j = 1; j < vertices.length; j++) {
ctx.lineTo(vertices[j].x + vibe * (Math.random() - 0.5), vertices[j].y + vibe * (Math.random() - 0.5));
}
ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
who.locatePlayer();
who.damage(damage / Math.sqrt(who.radius));
} }
ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
const damage = 1.9 * b.dmgScale * tech.waveBeamDamage * tech.wavePacketDamage / Math.sqrt(who.radius) //damage is lower for large radius mobs, since they feel the waves longer
who.locatePlayer();
who.damage(damage);
} }
hits = Matter.Query.ray(body, v1, v2, 50) //Matter.Query.ray(bodies, startPoint, endPoint, [rayWidth]) hits = Matter.Query.ray(body, v1, v2, 50) //Matter.Query.ray(bodies, startPoint, endPoint, [rayWidth])
@@ -4052,11 +4149,19 @@ const b = {
} }
ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
} }
ctx.stroke(); //draw vibes // ctx.stroke(); //draw vibes
this.waves[i].radius += tech.waveBeamSpeed * 2 //expand / move this.waves[i].radius += tech.waveBeamSpeed * 2 * this.waves[i].expanding //expand / move
}
if (this.waves[i].radius > end) {
this.waves[i].expanding = -1
this.waves[i].reflection--
if (this.waves[i].reflection < 1) this.waves.splice(i, 1) //end
} else if (this.waves[i].radius < 25) {
this.waves[i].expanding = 1
this.waves[i].reflection--
if (this.waves[i].reflection < 1) this.waves.splice(i, 1) //end
} }
if (this.waves[i].radius > 1800 * tech.isBulletsLastLonger) this.waves.splice(i, 1) //end
} }
ctx.stroke(); ctx.stroke();
}, },
@@ -4072,7 +4177,9 @@ const b = {
unit1: { x: Math.cos(m.angle - halfArc), y: Math.sin(m.angle - halfArc) }, //used for collision unit1: { x: Math.cos(m.angle - halfArc), y: Math.sin(m.angle - halfArc) }, //used for collision
unit2: { x: Math.cos(m.angle + halfArc), y: Math.sin(m.angle + halfArc) }, //used for collision unit2: { x: Math.cos(m.angle + halfArc), y: Math.sin(m.angle + halfArc) }, //used for collision
arc: halfArc * 2, arc: halfArc * 2,
radius: 25 radius: 25,
reflection: tech.waveReflections,
expanding: 1
}) })
}, },
doTransverse() { doTransverse() {
@@ -4082,7 +4189,7 @@ const b = {
} }
}, },
fireTransverse() { fireTransverse() {
totalCycles = Math.floor(4.3 * tech.wavePacketLength * tech.waveReflections * tech.isBulletsLastLonger) totalCycles = Math.floor(4.3 * 35 * tech.waveReflections * tech.isBulletsLastLonger / Math.sqrt(tech.waveReflections * 0.5))
const me = bullet.length; const me = bullet.length;
bullet[me] = Bodies.polygon(m.pos.x + 25 * Math.cos(m.angle), m.pos.y + 25 * Math.sin(m.angle), 5, 4, { bullet[me] = Bodies.polygon(m.pos.x + 25 * Math.cos(m.angle), m.pos.y + 25 * Math.sin(m.angle), 5, 4, {
angle: m.angle, angle: m.angle,
@@ -4091,7 +4198,7 @@ const b = {
inertia: Infinity, inertia: Infinity,
frictionAir: 0, frictionAir: 0,
slow: 0, slow: 0,
amplitude: (m.crouch ? 5 : 10) * ((this.wavePacketCycle % 2) ? -1 : 1) * Math.sin((this.wavePacketCycle + 1) * tech.wavePacketFrequency), // amplitude: (m.crouch ? 5 : 10) * ((this.wavePacketCycle % 2) ? -1 : 1) * Math.sin((this.wavePacketCycle + 1) * 0.088), //0.0968 //0.1012 //0.11 //0.088 //shorten wave packet
minDmgSpeed: 0, minDmgSpeed: 0,
dmg: b.dmgScale * tech.waveBeamDamage * tech.wavePacketDamage, //also control damage when you divide by mob.mass dmg: b.dmgScale * tech.waveBeamDamage * tech.wavePacketDamage, //also control damage when you divide by mob.mass
classType: "bullet", classType: "bullet",
@@ -4176,7 +4283,7 @@ const b = {
const transverse = Vector.normalise(Vector.perp(bullet[me].velocity)) const transverse = Vector.normalise(Vector.perp(bullet[me].velocity))
//fire a packet of bullets then delay for a while //fire a packet of bullets then delay for a while
this.wavePacketCycle++ this.wavePacketCycle++
if (this.wavePacketCycle > tech.wavePacketLength) { if (this.wavePacketCycle > 35) {
m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCDscale); // cool down m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCDscale); // cool down
this.wavePacketCycle = 0; this.wavePacketCycle = 0;
} }

View File

@@ -176,6 +176,7 @@ function collisionChecks(event) {
if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) { if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) {
obj.beforeDmg(mob[k]); //some bullets do actions when they hits things, like despawn //forces don't seem to work here obj.beforeDmg(mob[k]); //some bullets do actions when they hits things, like despawn //forces don't seem to work here
let dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity))) let dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)))
console.log(dmg)
if (tech.isCrit && mob[k].isStunned) dmg *= 4 if (tech.isCrit && mob[k].isStunned) dmg *= 4
mob[k].foundPlayer(); mob[k].foundPlayer();
mob[k].damage(dmg); mob[k].damage(dmg);

View File

@@ -257,7 +257,7 @@ const build = {
} }
} }
//show in game console with scroll bar?
// text +=`` // text +=``
@@ -434,7 +434,6 @@ const build = {
for (let i = 0, len = b.guns.length; i < len; i++) { for (let i = 0, len = b.guns.length; i < len; i++) {
text += `<div id = "gun-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'gun')"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[i].name}</div> ${b.guns[i].description}</div>` text += `<div id = "gun-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'gun')"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${b.guns[i].name}</div> ${b.guns[i].description}</div>`
} }
for (let i = 0, len = tech.tech.length; i < len; i++) { for (let i = 0, len = tech.tech.length; i < len; i++) {
if (!tech.tech[i].isExperimentHide && (!tech.tech[i].isNonRefundable || tech.tech[i].isExperimentalMode)) { if (!tech.tech[i].isExperimentHide && (!tech.tech[i].isNonRefundable || tech.tech[i].isExperimentalMode)) {
if (tech.tech[i].allowed()) { // || tech.tech[i].name === "+1 cardinality") { //|| tech.tech[i].name === "leveraged investment" if (tech.tech[i].allowed()) { // || tech.tech[i].name === "+1 cardinality") { //|| tech.tech[i].name === "leveraged investment"
@@ -457,7 +456,6 @@ const build = {
document.getElementById("difficulty-select").value = document.getElementById("difficulty-select-experiment").value document.getElementById("difficulty-select").value = document.getElementById("difficulty-select-experiment").value
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
}); });
//add tooltips //add tooltips
for (let i = 0, len = tech.tech.length; i < len; i++) { for (let i = 0, len = tech.tech.length; i < len; i++) {
if (document.getElementById(`tech-${i}`)) { if (document.getElementById(`tech-${i}`)) {
@@ -470,9 +468,7 @@ const build = {
simulation.startGame(true); //starts game, but pauses it simulation.startGame(true); //starts game, but pauses it
build.isExperimentSelection = true; build.isExperimentSelection = true;
simulation.paused = true; simulation.paused = true;
m.setField(0) m.setField(0)
b.inventory = []; //removes guns and ammo b.inventory = []; //removes guns and ammo
for (let i = 0, len = b.guns.length; i < len; ++i) { for (let i = 0, len = b.guns.length; i < len; ++i) {
b.guns[i].count = 0; b.guns[i].count = 0;
@@ -481,7 +477,6 @@ const build = {
} }
b.activeGun = null; b.activeGun = null;
simulation.makeGunHUD(); simulation.makeGunHUD();
tech.setupAllTech(); tech.setupAllTech();
build.populateGrid(); build.populateGrid();
document.getElementById("field-0").classList.add("build-field-selected"); document.getElementById("field-0").classList.add("build-field-selected");
@@ -490,14 +485,12 @@ const build = {
shareURL(isCustom = false) { shareURL(isCustom = false) {
let url = "https://landgreen.github.io/sidescroller/index.html?" let url = "https://landgreen.github.io/sidescroller/index.html?"
let count = 0; let count = 0;
for (let i = 0; i < b.inventory.length; i++) { for (let i = 0; i < b.inventory.length; i++) {
if (b.guns[b.inventory[i]].have) { if (b.guns[b.inventory[i]].have) {
url += `&gun${count}=${encodeURIComponent(b.guns[b.inventory[i]].name.trim())}` url += `&gun${count}=${encodeURIComponent(b.guns[b.inventory[i]].name.trim())}`
count++ count++
} }
} }
count = 0; count = 0;
for (let i = 0; i < tech.tech.length; i++) { for (let i = 0; i < tech.tech.length; i++) {
for (let j = 0; j < tech.tech[i].count; j++) { for (let j = 0; j < tech.tech[i].count; j++) {
@@ -516,7 +509,6 @@ const build = {
} }
console.log('n-gon build URL copied to clipboard.\nPaste into browser address bar.') console.log('n-gon build URL copied to clipboard.\nPaste into browser address bar.')
console.log(url) console.log(url)
navigator.clipboard.writeText(url).then(function() { navigator.clipboard.writeText(url).then(function() {
/* clipboard successfully set */ /* clipboard successfully set */
if (isCustom) { if (isCustom) {

View File

@@ -15,13 +15,15 @@ const level = {
// level.difficultyIncrease(30) // level.difficultyIncrease(30)
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// m.setField("wormhole") // m.setField("wormhole")
// b.giveGuns("shotgun") // b.giveGuns("drones")
// tech.isShotgunRecoil = true // tech.giveTech("torque bursts")
// tech.isShotgunReversed = true // b.giveGuns("wave beam")
// tech.giveTech("supertemporal") // tech.giveTech("phonon")
// tech.giveTech("free-electron laser") // tech.giveTech("bound state")
// tech.giveTech("bound state")
// tech.giveTech("bound state")
// tech.giveTech("isotropic radiator")
// for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics") // for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics")
// tech.giveTech("decoherence")
// for (let i = 0; i < 3; i++) tech.giveTech("packet length") // for (let i = 0; i < 3; i++) tech.giveTech("packet length")
level.intro(); //starting level level.intro(); //starting level
@@ -2252,14 +2254,14 @@ const level = {
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
// spawn.starter(1900, -500, 200) //big boy // spawn.starter(1900, -500, 200) //big boy
// spawn.pulseShooter(1900, -500) // spawn.pulsarBoss(1900, -500)
spawn.shieldingBoss(1900, -500) // spawn.shieldingBoss(1900, -500)
// spawn.grenadierBoss(1900, -500) // spawn.grenadierBoss(1900, -500)
// spawn.shieldingBoss(1900, -500) // spawn.shieldingBoss(1900, -500)
// spawn.historyBoss(1200, -500) // spawn.historyBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400) // spawn.laserTargetingBoss(1600, -400)
// spawn.hopper(1600, -500) // spawn.focuser(1600, -500)
// spawn.laserTargetingBoss(1700, -120) // spawn.laserTargetingBoss(1700, -120)
// spawn.bomberBoss(1400, -500) // spawn.bomberBoss(1400, -500)
// spawn.hopBoss(1800, -120) // spawn.hopBoss(1800, -120)
@@ -2267,7 +2269,7 @@ const level = {
// spawn.orbitalBoss(1600, -500) // spawn.orbitalBoss(1600, -500)
// spawn.cellBossCulture(1600, -500) // spawn.cellBossCulture(1600, -500)
// spawn.shieldingBoss(1600, -500) // spawn.shieldingBoss(1600, -500)
// spawn.laser(1200, -500) spawn.grenadier(1200, -500)
// spawn.shield(mob[mob.length - 1], 1800, -120, 1); // spawn.shield(mob[mob.length - 1], 1800, -120, 1);
// spawn.nodeGroup(1200, -500, "grenadier") // spawn.nodeGroup(1200, -500, "grenadier")
@@ -2621,7 +2623,7 @@ const level = {
// localSettings.levelsClearedLastGame = 20 // localSettings.levelsClearedLastGame = 20
if (level.levelsCleared === 0) { if (level.levelsCleared === 0) {
powerUps.spawn(2500, -50, "research", false); // powerUps.spawn(2500, -50, "research", false);
powerUps.spawn(1900, -50, "heal", false); powerUps.spawn(1900, -50, "heal", false);
powerUps.spawn(2050, -50, "heal", false); powerUps.spawn(2050, -50, "heal", false);
if (localSettings.levelsClearedLastGame < 6) { if (localSettings.levelsClearedLastGame < 6) {

View File

@@ -1830,7 +1830,7 @@ const m = {
m.energy -= 0.04; m.energy -= 0.04;
b.iceIX(1) b.iceIX(1)
} else if (tech.isDroneRadioactive) { } else if (tech.isDroneRadioactive) {
m.energy -= 1.5; //almost 5x drain of normal drones m.energy -= 0.9;
b.droneRadioactive({ 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) }, 25) b.droneRadioactive({ 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) }, 25)
} else { } else {
m.energy -= 0.45 * tech.droneEnergyReduction; m.energy -= 0.45 * tech.droneEnergyReduction;

View File

@@ -262,12 +262,14 @@ const powerUps = {
} }
} }
}, },
currentRerollCount: 0,
use(type) { //runs when you actually research a list of selections, type can be field, gun, or tech use(type) { //runs when you actually research a list of selections, type can be field, gun, or tech
if (tech.isJunkResearch) { if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
tech.addJunkTechToPool(tech.junkResearchNumber) tech.addJunkTechToPool(tech.junkResearchNumber)
} else { } else {
powerUps.research.changeRerolls(-1) powerUps.research.changeRerolls(-1)
} }
powerUps.research.currentRerollCount++
// simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span> // simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span>
// <br>${powerUps.research.count}`) // <br>${powerUps.research.count}`)
if (tech.isBanish && type === 'tech') { // banish researched tech if (tech.isBanish && type === 'tech') { // banish researched tech
@@ -447,8 +449,8 @@ const powerUps = {
powerUps.field.choiceLog.push(choice2) powerUps.field.choiceLog.push(choice2)
powerUps.field.choiceLog.push(choice3) powerUps.field.choiceLog.push(choice3)
if (tech.isJunkResearch) { if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
tech.junkResearchNumber = Math.floor(5 * Math.random()) tech.junkResearchNumber = Math.floor(4 * Math.random())
text += `<div class="choose-grid-module" onclick="powerUps.research.use('field')"><div class="grid-title"> <span style="position:relative;">` text += `<div class="choose-grid-module" onclick="powerUps.research.use('field')"><div class="grid-title"> <span style="position:relative;">`
for (let i = 0; i < tech.junkResearchNumber; i++) text += `<div class="circle-grid junk" style="position:absolute; top:0; left:${15*i}px ;opacity:0.8; border: 1px #fff solid;"></div>` for (let i = 0; i < tech.junkResearchNumber; i++) text += `<div class="circle-grid junk" style="position:absolute; top:0; left:${15*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
text += `</span>&nbsp; <span class='research-select'>pseudoscience</span></div></div>` text += `</span>&nbsp; <span class='research-select'>pseudoscience</span></div></div>`
@@ -461,8 +463,6 @@ const powerUps = {
// text += `<div style = 'color:#fff'>${simulation.SVGrightMouse} activate the shield with the right mouse<br>fields shield you from damage <br>and let you pick up and throw blocks</div>` // text += `<div style = 'color:#fff'>${simulation.SVGrightMouse} activate the shield with the right mouse<br>fields shield you from damage <br>and let you pick up and throw blocks</div>`
document.getElementById("choose-grid").innerHTML = text document.getElementById("choose-grid").innerHTML = text
powerUps.showDraft(); powerUps.showDraft();
} else {
powerUps.giveRandomAmmo()
} }
} }
}, },
@@ -566,7 +566,7 @@ const powerUps = {
powerUps.tech.choiceLog.push(choice3) powerUps.tech.choiceLog.push(choice3)
// if (powerUps.research.count) text += `<div class="choose-grid-module" onclick="powerUps.research.use('tech')"><div class="grid-title"><div class="circle-grid research"></div> &nbsp; research <span class="research-select">${powerUps.research.count}</span></div></div>` // if (powerUps.research.count) text += `<div class="choose-grid-module" onclick="powerUps.research.use('tech')"><div class="grid-title"><div class="circle-grid research"></div> &nbsp; research <span class="research-select">${powerUps.research.count}</span></div></div>`
if (tech.isJunkResearch) { if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
tech.junkResearchNumber = Math.floor(5 * Math.random()) tech.junkResearchNumber = Math.floor(5 * Math.random())
text += `<div class="choose-grid-module" onclick="powerUps.research.use('tech')"><div class="grid-title"> <span style="position:relative;">` text += `<div class="choose-grid-module" onclick="powerUps.research.use('tech')"><div class="grid-title"> <span style="position:relative;">`
for (let i = 0; i < tech.junkResearchNumber; i++) text += `<div class="circle-grid junk" style="position:absolute; top:0; left:${15*i}px ;opacity:0.8; border: 1px #fff solid;"></div>` for (let i = 0; i < tech.junkResearchNumber; i++) text += `<div class="circle-grid junk" style="position:absolute; top:0; left:${15*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
@@ -579,19 +579,16 @@ const powerUps = {
document.getElementById("choose-grid").innerHTML = text document.getElementById("choose-grid").innerHTML = text
powerUps.showDraft(); powerUps.showDraft();
} else { } else if (tech.isBanish) {
if (tech.isBanish) { for (let i = 0, len = tech.tech.length; i < len; i++) {
for (let i = 0, len = tech.tech.length; i < len; i++) { if (tech.tech[i].name === "decoherence") powerUps.ejectTech(i)
if (tech.tech[i].name === "decoherence") powerUps.ejectTech(i)
}
// simulation.makeTextLog(`No <strong class='color-m'>tech</strong> left<br>erased <strong class='color-m'>tech</strong> have been recovered`)
simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - powerUps.tech.banishLog.length)}`)
// powerUps.spawn(m.pos.x, m.pos.y, "tech");
powerUps.endDraft("tech");
} else {
powerUps.giveRandomAmmo()
} }
// simulation.makeTextLog(`No <strong class='color-m'>tech</strong> left<br>erased <strong class='color-m'>tech</strong> have been recovered`)
simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - powerUps.tech.banishLog.length)}`)
// powerUps.spawn(m.pos.x, m.pos.y, "tech");
powerUps.endDraft("tech");
} }
} }
} }
}, },
@@ -658,7 +655,7 @@ const powerUps = {
powerUps.gun.choiceLog.push(choice3) powerUps.gun.choiceLog.push(choice3)
// if (powerUps.research.count) text += `<div class="choose-grid-module" onclick="powerUps.research.use('gun')"><div class="grid-title"><div class="circle-grid research"></div> &nbsp; research <span class="research-select">${powerUps.research.count}</span></div></div>` // if (powerUps.research.count) text += `<div class="choose-grid-module" onclick="powerUps.research.use('gun')"><div class="grid-title"><div class="circle-grid research"></div> &nbsp; research <span class="research-select">${powerUps.research.count}</span></div></div>`
if (tech.isJunkResearch) { if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
tech.junkResearchNumber = Math.floor(5 * Math.random()) tech.junkResearchNumber = Math.floor(5 * Math.random())
text += `<div class="choose-grid-module" onclick="powerUps.research.use('gun')"><div class="grid-title"> <span style="position:relative;">` text += `<div class="choose-grid-module" onclick="powerUps.research.use('gun')"><div class="grid-title"> <span style="position:relative;">`
for (let i = 0; i < tech.junkResearchNumber; i++) text += `<div class="circle-grid junk" style="position:absolute; top:0; left:${15*i}px ;opacity:0.8; border: 1px #fff solid;"></div>` for (let i = 0; i < tech.junkResearchNumber; i++) text += `<div class="circle-grid junk" style="position:absolute; top:0; left:${15*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
@@ -673,12 +670,11 @@ const powerUps = {
if (tech.isOneGun && b.inventory.length > 0) text += `<div style = "color: #f24">replaces your current gun</div>` if (tech.isOneGun && b.inventory.length > 0) text += `<div style = "color: #f24">replaces your current gun</div>`
document.getElementById("choose-grid").innerHTML = text document.getElementById("choose-grid").innerHTML = text
powerUps.showDraft(); powerUps.showDraft();
} else {
powerUps.giveRandomAmmo()
} }
} }
}, },
onPickUp(who) { onPickUp(who) {
powerUps.research.currentRerollCount = 0
if (tech.isTechDamage && who.name === "tech") m.damage(0.11) if (tech.isTechDamage && who.name === "tech") m.damage(0.11)
if (tech.isMassEnergy) m.energy += 2; if (tech.isMassEnergy) m.energy += 2;
if (tech.isMineDrop) { if (tech.isMineDrop) {
@@ -700,15 +696,15 @@ const powerUps = {
} }
} }
}, },
giveRandomAmmo() { // giveRandomAmmo() {
const ammoTarget = Math.floor(Math.random() * (b.guns.length)); // const ammoTarget = Math.floor(Math.random() * (b.guns.length));
const ammo = Math.ceil(b.guns[ammoTarget].ammoPack * 6); // const ammo = Math.ceil(b.guns[ammoTarget].ammoPack * 6);
if (ammo !== Infinity) { // if (ammo !== Infinity) {
b.guns[ammoTarget].ammo += ammo; // b.guns[ammoTarget].ammo += ammo;
simulation.updateGunHUD(); // simulation.updateGunHUD();
simulation.makeTextLog(`${b.guns[ammoTarget].name}.<span class='color-gun'>ammo</span> <span class='color-symbol'>+=</span> ${ammo}`); // simulation.makeTextLog(`${b.guns[ammoTarget].name}.<span class='color-gun'>ammo</span> <span class='color-symbol'>+=</span> ${ammo}`);
} // }
}, // },
spawnRandomPowerUp(x, y) { //mostly used after mob dies, doesn't always return a power up spawnRandomPowerUp(x, y) { //mostly used after mob dies, doesn't always return a power up
if ((Math.random() * Math.random() - 0.3 > Math.sqrt(m.health) && !tech.isEnergyHealth) || Math.random() < 0.04) { //spawn heal chance is higher at low health if ((Math.random() * Math.random() - 0.3 > Math.sqrt(m.health) && !tech.isEnergyHealth) || Math.random() < 0.04) { //spawn heal chance is higher at low health
powerUps.spawn(x, y, "heal"); powerUps.spawn(x, y, "heal");

View File

@@ -332,14 +332,14 @@ const simulation = {
} }
}, },
nextGun() { nextGun() {
if (b.inventory.length > 0 && !tech.isGunCycle) { if (b.inventory.length > 1 && !tech.isGunCycle) {
b.inventoryGun++; b.inventoryGun++;
if (b.inventoryGun > b.inventory.length - 1) b.inventoryGun = 0; if (b.inventoryGun > b.inventory.length - 1) b.inventoryGun = 0;
simulation.switchGun(); simulation.switchGun();
} }
}, },
previousGun() { previousGun() {
if (b.inventory.length > 0 && !tech.isGunCycle) { if (b.inventory.length > 1 && !tech.isGunCycle) {
b.inventoryGun--; b.inventoryGun--;
if (b.inventoryGun < 0) b.inventoryGun = b.inventory.length - 1; if (b.inventoryGun < 0) b.inventoryGun = b.inventory.length - 1;
simulation.switchGun(); simulation.switchGun();

View File

@@ -306,16 +306,16 @@ const spawn = {
function loop() { function loop() {
if (!simulation.paused) { if (!simulation.paused) {
count++ count++
if (count < 600) { if (count < 660) {
if (count === 1) simulation.makeTextLog(`<em>//enter testing mode to set level.levels.length to <strong>Infinite</strong></em>`); 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)}`); if (!(count % 60)) simulation.makeTextLog(`simulation.analysis <span class='color-symbol'>=</span> ${((count/60- Math.random())*0.1 ).toFixed(3)}`);
} else if (count === 600) { } else if (count === 660) {
simulation.makeTextLog(`simulation.analysis <span class='color-symbol'>=</span> 1 <em>//analysis complete</em>`); simulation.makeTextLog(`simulation.analysis <span class='color-symbol'>=</span> 1 <em>//analysis complete</em>`);
} else if (count === 720) { } else if (count === 780) {
simulation.makeTextLog(`<span class="lore-text">undefined</span> <span class='color-symbol'>=</span> ${lore.techCount}/${lore.techGoal}`) simulation.makeTextLog(`<span class="lore-text">undefined</span> <span class='color-symbol'>=</span> ${lore.techCount}/${lore.techGoal}`)
} else if (count === 900) { } else if (count === 1020) {
simulation.makeTextLog(`World.clear(engine.world) <em>//simulation successful</em>`); simulation.makeTextLog(`World.clear(engine.world) <em>//simulation successful</em>`);
} else if (count === 1140) { } else if (count === 1260) {
// tech.isImmortal = false; // tech.isImmortal = false;
// m.death() // m.death()
// m.alive = false; // m.alive = false;
@@ -1709,7 +1709,7 @@ const spawn = {
if (targetDist < r + 16) { if (targetDist < r + 16) {
targetDist = r + 10; targetDist = r + 10;
//charge at player //charge at player
const forceMag = this.accelMag * 30 * this.mass; const forceMag = this.accelMag * 40 * this.mass;
const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x); const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
this.force.x += forceMag * Math.cos(angle); this.force.x += forceMag * Math.cos(angle);
this.force.y += forceMag * Math.sin(angle); this.force.y += forceMag * Math.sin(angle);
@@ -1906,7 +1906,7 @@ const spawn = {
me.fireCycle = 0 me.fireCycle = 0
me.fireTarget = { x: 0, y: 0 } me.fireTarget = { x: 0, y: 0 }
me.pulseRadius = Math.min(500, 230 + simulation.difficulty * 3) me.pulseRadius = Math.min(500, 230 + simulation.difficulty * 3)
me.fireDelay = Math.max(60, 140 - simulation.difficulty * 2) me.fireDelay = Math.max(60, 150 - simulation.difficulty * 2)
me.isFiring = false me.isFiring = false
Matter.Body.setDensity(me, 0.01); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.01); //extra dense //normal is 0.001 //makes effective life much larger
me.isBoss = true; me.isBoss = true;
@@ -2999,20 +2999,21 @@ const spawn = {
}; };
}, },
grenadierBoss(x, y, radius = 95) { grenadierBoss(x, y, radius = 95) {
mobs.spawn(x, y, 6, radius, "rgb(255,50,160)"); mobs.spawn(x, y, 6, radius, "rgb(215,80,190)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.accelMag = 0.00008 * simulation.accelScale; me.accelMag = 0.0001 * simulation.accelScale;
me.fireFreq = Math.floor(360 * simulation.CDScale) me.fireFreq = Math.floor(360 * simulation.CDScale)
me.frictionStatic = 0; me.frictionStatic = 0;
me.friction = 0; me.friction = 0;
me.frictionAir = 0.02; me.frictionAir = 0.035;
me.memory = 420; me.memory = 420;
me.repulsionRange = 1200000; //squared me.repulsionRange = 1200000; //squared
spawn.shield(me, x, y, 1); // spawn.shield(me, x, y, 1);
spawn.spawnOrbitals(me, radius + 25, 1); spawn.spawnOrbitals(me, radius + 50, 1);
spawn.spawnOrbitals(me, radius + 75, 1); spawn.spawnOrbitals(me, radius + 125, 1);
Matter.Body.setDensity(me, 0.002 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger spawn.spawnOrbitals(me, radius + 200, 1);
Matter.Body.setDensity(me, 0.004 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.onDeath = function() { //helps collisions functions work better after vertex have been changed me.onDeath = function() { //helps collisions functions work better after vertex have been changed
for (let i = 0; i < 6; i++) { for (let i = 0; i < 6; i++) {
spawn.grenade(this.position.x, this.position.y, 2, 4, 75 * simulation.CDScale); spawn.grenade(this.position.x, this.position.y, 2, 4, 75 * simulation.CDScale);
@@ -3050,110 +3051,8 @@ const spawn = {
this.attraction(); this.attraction();
}; };
}, },
// grenadierBoss(x, y, radius = 110) {
// mobs.spawn(x, y, 3, radius, "rgb(255,50,160)"); //rgb(255,100,200)
// let me = mob[mob.length - 1];
// me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
// me.isVerticesChange = true
// me.isBoss = true;
// me.frictionStatic = 0;
// me.friction = 0;
// me.memory = 180 //140;
// me.fireFreq = 0.02;
// me.noseLength = 0;
// me.fireAngle = 0;
// me.accelMag = 0.005 * simulation.accelScale;
// me.frictionAir = 0.05;
// me.lookTorque = 0.000006 * (Math.random() > 0.5 ? -1 : 1);
// me.fireDir = {
// x: 0,
// y: 0
// };
// Matter.Body.setDensity(me, 0.008 + 0.0003 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
// setTimeout(() => {
// spawn.spawnOrbitals(me, radius + 25, 1);
// spawn.spawnOrbitals(me, radius + 75, 1);
// }, 100); //have to wait a sec so the tether constraint doesn't attach to an orbital
// me.onDeath = function() { //helps collisions functions work better after vertex have been changed
// for (let i = 0; i < 6; i++) {
// spawn.grenade(this.position.x, this.position.y, 2, 4, 75 * simulation.CDScale);
// const who = mob[mob.length - 1]
// who.collisionFilter.category = 0
// who.collisionFilter.mask = 0
// const speed = 4 * simulation.accelScale;
// const angle = 2 * Math.PI * i / 6
// Matter.Body.setVelocity(who, {
// x: this.velocity.x + speed * Math.cos(angle),
// y: this.velocity.y + speed * Math.sin(angle)
// });
// }
// powerUps.spawnBossPowerUp(this.position.x, this.position.y)
// }
// // me.onDamage = function() {
// // spawn.grenade(this.position.x, this.position.y, 2, 4, 120 * simulation.CDScale);
// // const who = mob[mob.length - 1]
// // who.collisionFilter.category = 0
// // who.collisionFilter.mask = 0
// // const velocity = Vector.mult(Vector.normalise(Vector.sub(player.position, who.position)), 3)
// // Matter.Body.setVelocity(who, {
// // x: this.velocity.x + velocity.x,
// // y: this.velocity.y + velocity.y
// // });
// // };
// me.do = function() {
// this.seePlayerByLookingAt();
// this.checkStatus();
// if (!m.isBodiesAsleep) {
// const setNoseShape = () => {
// const mag = this.radius + this.radius * this.noseLength;
// this.vertices[1].x = this.position.x + Math.cos(this.angle) * mag;
// this.vertices[1].y = this.position.y + Math.sin(this.angle) * mag;
// };
// //throw a mob/bullet at player
// if (this.seePlayer.recall) {
// //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) / 1600; //gives the bullet an arc
// }
// //rotate towards fireAngle
// const angle = this.angle + Math.PI / 2;
// // c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
// //rotate towards fireAngle
// const dot = Vector.dot({
// x: Math.cos(angle),
// y: Math.sin(angle)
// }, this.fireDir)
// const threshold = 0.03;
// if (dot > threshold) {
// this.torque += 0.000004 * this.inertia;
// } else if (dot < -threshold) {
// this.torque -= 0.000004 * this.inertia;
// } else if (this.noseLength > 1.5 && dot > -0.2 && dot < 0.2) {
// //fire
// spawn.grenade(this.vertices[1].x, this.vertices[1].y);
// const v = 7 * simulation.accelScale;
// Matter.Body.setVelocity(mob[mob.length - 1], {
// x: this.velocity.x + this.fireDir.x * v + Math.random(),
// y: this.velocity.y + this.fireDir.y * v + Math.random()
// });
// this.noseLength = 0;
// // recoil
// this.force.x -= 0.002 * this.fireDir.x * this.mass;
// this.force.y -= 0.002 * this.fireDir.y * this.mass;
// }
// if (this.noseLength < 1.5) this.noseLength += this.fireFreq;
// setNoseShape();
// } else if (this.noseLength > 0.1) {
// this.noseLength -= this.fireFreq / 2;
// setNoseShape();
// }
// }
// };
// },
grenadier(x, y, radius = 35 + Math.ceil(Math.random() * 20)) { grenadier(x, y, radius = 35 + Math.ceil(Math.random() * 20)) {
mobs.spawn(x, y, 3, radius, "rgba(255,50,160,1)"); //rgb(255,100,200) mobs.spawn(x, y, 3, radius, "rgb(215,80,190)"); //rgb(255,100,200)
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
me.isVerticesChange = true me.isVerticesChange = true
@@ -3231,7 +3130,7 @@ const spawn = {
}; };
}, },
grenade(x, y, radius = 2, sides = 4, lifeSpan = 90 + Math.ceil(60 / simulation.accelScale)) { grenade(x, y, radius = 2, sides = 4, lifeSpan = 90 + Math.ceil(60 / simulation.accelScale)) {
mobs.spawn(x, y, sides, radius, "rgb(255,0,0)"); mobs.spawn(x, y, sides, radius, "rgb(215,0,190)"); //rgb(215,80,190)
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.stroke = "transparent"; me.stroke = "transparent";
me.onHit = function() { me.onHit = function() {
@@ -3258,7 +3157,7 @@ const spawn = {
x: this.position.x, x: this.position.x,
y: this.position.y, y: this.position.y,
radius: this.pulseRadius, radius: this.pulseRadius,
color: "rgba(255,0,100,0.6)", color: "rgba(255,0,220,0.3)",
time: simulation.drawTime time: simulation.drawTime
}); });
}; };
@@ -3269,7 +3168,7 @@ const spawn = {
this.timeLimit(); this.timeLimit();
ctx.beginPath(); //draw explosion outline ctx.beginPath(); //draw explosion outline
ctx.arc(this.position.x, this.position.y, this.pulseRadius * (1.01 - this.timeLeft / this.lifeSpan), 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay ctx.arc(this.position.x, this.position.y, this.pulseRadius * (1.01 - this.timeLeft / this.lifeSpan), 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay
ctx.fillStyle = "rgba(255,0,100,0.06)"; ctx.fillStyle = "rgba(255,0,220,0.05)";
ctx.fill(); ctx.fill();
}; };
}, },

View File

@@ -647,7 +647,7 @@
}, },
{ {
name: "microstates", name: "microstates",
description: "increase <strong class='color-d'>damage</strong> by <strong>6%</strong><br>for every <strong>10</strong> active <strong>bullets</strong>", description: "increase <strong class='color-d'>damage</strong> by <strong>6%</strong><br>for every <strong>10</strong> active <strong>projectiles</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
@@ -665,7 +665,7 @@
}, },
{ {
name: "anti-shear topology", name: "anti-shear topology",
description: "some <strong>bullets</strong> last <strong>30% longer</strong><br><em style = 'font-size: 83%'>drones, spores, missiles, foam, wave, neutron</em>", description: "some <strong>projectiles</strong> last <strong>30% longer</strong><br><em style = 'font-size: 83%'>drones, spores, missiles, foam, wave, neutron</em>",
// isGunTech: true, // isGunTech: true,
maxCount: 3, maxCount: 3,
count: 0, count: 0,
@@ -2802,7 +2802,7 @@
}, },
{ {
name: "pseudoscience", name: "pseudoscience",
description: "<strong>rerolling</strong> choices no longer costs <strong class='color-r'>research</strong><br>instead it adds <strong>0-4</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool", description: "<span style = 'font-size:94%;'>when <strong>selecting</strong> a power up, <strong class='color-r'>research</strong> <strong>3</strong> times</span><br>for <strong>free</strong>, but add <strong>0-3</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -3883,28 +3883,9 @@
tech.bulletSize = 1; tech.bulletSize = 1;
} }
}, },
{
name: "bound state",
description: "instead of dissipating normally<br>wave packets <strong>reflect</strong> backwards <strong>2</strong> times",
isGunTech: true,
maxCount: 3,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("wave beam") && !tech.isLongitudinal
},
requires: "wave beam",
effect() {
tech.waveReflections += 2
},
remove() {
tech.waveReflections = 1
}
},
{ {
name: "phase velocity", name: "phase velocity",
description: "wave beam <strong>propagates</strong> faster through solids<br>up by <strong>3000%</strong> in the map and <strong>760%</strong> in <strong class='color-block'>blocks</strong>", description: "wave beam <strong>propagates</strong> faster through <strong>solids</strong><br>up by <strong>3000%</strong> in the map and <strong>760%</strong> in <strong class='color-block'>blocks</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -3913,7 +3894,7 @@
allowed() { allowed() {
return tech.haveGunCheck("wave beam") && !tech.isLongitudinal return tech.haveGunCheck("wave beam") && !tech.isLongitudinal
}, },
requires: "wave beam", requires: "wave beam, not phonon",
effect() { effect() {
tech.isPhaseVelocity = true; tech.isPhaseVelocity = true;
}, },
@@ -3922,27 +3903,22 @@
} }
}, },
{ {
name: "packet length", name: "bound state",
description: "wave packet <strong>length</strong> and <strong>duration</strong><br>is increased by <strong>50%</strong>", // description: "holding fire allows the <strong>wave beam</strong> to emits a second <strong>packet</strong><br>at zero ammo cost", description: "wave packets <strong>reflect</strong> backwards <strong>2</strong> times<br><strong>range</strong> is reduced by <strong>25%</strong>",
isGunTech: true, isGunTech: true,
maxCount: 3, maxCount: 9,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("wave beam") && !tech.isLongitudinal return tech.haveGunCheck("wave beam")
}, },
requires: "wave beam", requires: "wave beam",
effect() { effect() {
const scale = 1.5 - 0.025 * this.count tech.waveReflections += 2
tech.wavePacketLength *= scale
tech.wavePacketFrequency /= scale
tech.waveLengthRange *= Math.sqrt(scale)
}, },
remove() { remove() {
tech.wavePacketFrequency = 0.088 //0.0968 //0.1012 //0.11 //0.088 //shorten wave packet tech.waveReflections = 1
tech.wavePacketLength = 35 //32.7 //31.3 //28.8 //36 //how many wave packets are released // double this to emit 2 packets
tech.waveLengthRange = 130;
} }
}, },
{ {
@@ -3968,7 +3944,7 @@
}, },
{ {
name: "propagation", name: "propagation",
description: "wave packet propagation <strong>speed</strong> is <strong>25%</strong> slower<br>wave <strong class='color-d'>damage</strong> is increased by <strong>50%</strong>", description: "wave packet propagation <strong>speed</strong> is <strong>20%</strong> slower<br>wave <strong class='color-d'>damage</strong> is increased by <strong>50%</strong>",
isGunTech: true, isGunTech: true,
maxCount: 9, maxCount: 9,
count: 0, count: 0,
@@ -3979,26 +3955,26 @@
}, },
requires: "wave beam", requires: "wave beam",
effect() { effect() {
tech.waveBeamSpeed *= 0.75; tech.waveBeamSpeed *= 0.8;
tech.waveBeamDamage += 1.3 * 0.5 tech.waveBeamDamage += 1.5 * 0.5 //this sets base wave beam damage, not used by arcs or circles
}, },
remove() { remove() {
tech.waveBeamSpeed = 10; tech.waveBeamSpeed = 10;
tech.waveBeamDamage = 1.5 //this sets base wave beam damage tech.waveBeamDamage = 1.5 //this sets base wave beam damage, not used by arcs or circles
} }
}, },
{ {
name: "pressure wave", //longitudinal //gravitational wave? name: "phonon", //longitudinal //gravitational wave?
description: "wave beam emits low <strong>frequency</strong>, high <strong class='color-d'>damage</strong><br><strong>expanding arcs</strong> that propagate through solids", description: "wave beam emits low <strong>frequency</strong>, high <strong class='color-d'>damage</strong><br><strong>expanding arcs</strong> that propagate through <strong>solids</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 4, frequency: 4,
frequencyDefault: 4, frequencyDefault: 4,
allowed() { allowed() {
return tech.haveGunCheck("wave beam") && !tech.isPhaseVelocity && tech.waveLengthRange === 130 && tech.waveReflections === 1 return tech.haveGunCheck("wave beam") && !tech.isPhaseVelocity
}, },
requires: "wave beam, not phase velocity, packet length, bound state", requires: "wave beam, not phase velocity ",
effect() { effect() {
tech.isLongitudinal = true; tech.isLongitudinal = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -4026,6 +4002,37 @@
tech.isLongitudinal = false; tech.isLongitudinal = false;
} }
}, },
{
name: "isotropic radiator",
description: "<strong>wave beam</strong> expands in <strong>all</strong> directions<br><span style = 'font-size:90%;'><strong>range</strong> reduced <strong>40%</strong> and <strong class='color-d'>damage</strong> increased <strong>50%</strong></span>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 4,
frequencyDefault: 4,
allowed() {
return tech.isLongitudinal
},
requires: "phonon",
effect() {
tech.is360Longitudinal = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "wave beam") {
b.guns[i].chooseFireMethod()
break
}
}
},
remove() {
tech.is360Longitudinal = false;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "wave beam") {
b.guns[i].chooseFireMethod()
break
}
}
}
},
{ {
name: "cruise missile", name: "cruise missile",
description: "<strong>missiles</strong> travel <strong>63%</strong> slower,<br>but have a <strong>50%</strong> larger <strong class='color-e'>explosive</strong> payload", description: "<strong>missiles</strong> travel <strong>63%</strong> slower,<br>but have a <strong>50%</strong> larger <strong class='color-e'>explosive</strong> payload",
@@ -4432,24 +4439,42 @@
} }
}, },
{ {
name: "irradiated drones", name: "torque bursts",
description: "<strong class='color-p'>irradiate</strong> the space around your <strong>drones</strong><br>reduce <strong class='color-g'>ammo</strong>/<strong class='color-f'>efficiency</strong> by <strong>80%</strong>", description: "<strong>drones</strong> rapidly <strong>rush</strong> towards their target<br>increase <strong>drone</strong> collision <strong class='color-d'>damage</strong> by <strong>33%</strong>",
//<br>does <strong class='color-d'>damage</strong>, <strong class='color-harm'>harm</strong>, and drains <strong class='color-f'>energy</strong>
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.droneCycleReduction === 1 && !tech.isIncendiary && (tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField))) return tech.haveGunCheck("drones") && !tech.isDroneRadioactive
},
requires: "drone gun",
effect() {
tech.isDroneTeleport = true
},
remove() {
tech.isDroneTeleport = false
}
},
{
name: "irradiated drones",
description: "<strong class='color-p'>irradiate</strong> the space around your <strong>drones</strong><br>reduce <strong class='color-g'>ammo</strong>/<strong class='color-f'>efficiency</strong> by <strong>75%</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.droneCycleReduction === 1 && !tech.isIncendiary && !tech.isDroneTeleport && (tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField)))
}, },
requires: "drone gun, not reduced tolerances or incendiary", requires: "drone gun, not reduced tolerances or incendiary",
effect() { effect() {
tech.isDroneRadioactive = true tech.isDroneRadioactive = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "drones") { if (b.guns[i].name === "drones") {
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * 0.2 b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * 0.25
b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 0.2) b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 0.25)
} }
} }
}, },
@@ -4459,7 +4484,7 @@
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "drones") { if (b.guns[i].name === "drones") {
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack b.guns[i].ammoPack = b.guns[i].defaultAmmoPack
b.guns[i].ammo = b.guns[i].ammo * 5 b.guns[i].ammo = b.guns[i].ammo * 4
} }
} }
} }
@@ -4583,7 +4608,7 @@
}, },
{ {
name: "electrostatic induction", name: "electrostatic induction",
description: "<strong>foam</strong> bullets are electrically charged<br>causing <strong>attraction</strong> to nearby <strong>mobs</strong>", description: "<strong>foam</strong> bubbles are electrically charged<br>causing <strong>attraction</strong> to nearby <strong>mobs</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -5173,7 +5198,7 @@
m.energy = 0.01; m.energy = 0.01;
b.randomBot() b.randomBot()
b.randomBot() b.randomBot()
// b.randomBot() b.randomBot()
}, },
remove() {} remove() {}
}, },
@@ -5726,7 +5751,7 @@
}, },
{ {
name: "traversable geodesics", name: "traversable geodesics",
description: "your <strong>bullets</strong> can traverse <strong class='color-worm'>wormholes</strong><br>spawn 2 <strong class='color-g'>guns</strong> and <strong class='color-g'>ammo</strong>", description: "your <strong>projectiles</strong> can traverse <strong class='color-worm'>wormholes</strong><br>spawn 2 <strong class='color-g'>guns</strong> and <strong class='color-g'>ammo</strong>",
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -6299,13 +6324,16 @@
if ( if (
tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].count < tech.tech[i].maxCount &&
tech.tech[i].allowed() && tech.tech[i].allowed() &&
!tech.tech[i].isJunk !tech.tech[i].isJunk &&
!tech.tech.isLore
) { ) {
for (let j = 0; j < tech.tech[i].frequency; j++) options.push(i); options.push(i);
} }
} }
const index = options[Math.floor(Math.random() * options.length)] if (options.length) {
tech.tech[index].frequency = 100 const index = options[Math.floor(Math.random() * options.length)]
tech.tech[index].frequency = 100
}
}, },
remove() {} remove() {}
}, },
@@ -7445,10 +7473,8 @@
isMobBlockFling: null, isMobBlockFling: null,
blockingIce: null, blockingIce: null,
isPhaseVelocity: null, isPhaseVelocity: null,
wavePacketLength: null,
waveBeamSpeed: null, waveBeamSpeed: null,
wavePacketAmplitude: null, wavePacketAmplitude: null,
waveLengthRange: null,
isCollisionRealitySwitch: null, isCollisionRealitySwitch: null,
iceIXOnDeath: null, iceIXOnDeath: null,
wimpCount: null, wimpCount: null,
@@ -7473,10 +7499,12 @@
laserColor: null, laserColor: null,
laserColorAlpha: null, laserColorAlpha: null,
isLongitudinal: null, isLongitudinal: null,
is360Longitudinal: null,
isShotgunReversed: null, isShotgunReversed: null,
wormDuplicate: null, wormDuplicate: null,
isCloakingDamage: null, isCloakingDamage: null,
harmonicEnergy: null, harmonicEnergy: null,
isFieldHarmReduction: null, isFieldHarmReduction: null,
isFastTime: null isFastTime: null,
isDroneTeleport: null
} }

View File

@@ -1,29 +1,30 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** NEXT PATCH ********************************************************
shieldingBoss stops re-shielding after taking damage "pressure wave" renamed "phonon"
25% more health tech packet length removed
re-shielding Cooldown is 25% shorter most wave beam tech is now compatible with phonon
you can pick up ammo with laser again wave beam tech: isotropic radiator - phonon has shorter range but expands in every direction
it was too annoying to switch guns
you have 1/2 second harm immunity after leaving a portal drone tech: torque bursts - teleport towards targets and do 30% more collision damage
lore conversations are better at recovering from speech API freezes irradiated drones do 33% more damage, 33% less collisions damage
(if the speech API doesn't work after 10 seconds it switches to pure text) 5% more ammo, 30% less range, don't lose duration on collisions
pseudoscience only gets 3 free rerolls per tech
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
so JUNK tech in experiment mode? give drones or spores some mobs abilities
striker: teleport towards target
new wave tech - reduce range, but make bullets circles, not arcs drone tech: snakes
I haven't thought about this much, but I don't know make them look like snakes...
scrolling console history in pause menu? scrolling console history in pause menu?
also make tech, guns scrolling? also make tech, guns scrolling?
in testing mode console log the body you click on
consider executables: pause should at least show the last in game console message
press F to do things
ideas:
make the player get a buff after using wormhole make the player get a buff after using wormhole
while energy lasts: drain energy and give damage buff while energy lasts: drain energy and give damage buff
@@ -33,8 +34,6 @@ tech: quantized shields - harmonic standing wave field can only lose 33 energy p
the blocked value only scales up to 2x or 4x (33 energy) blocked the blocked value only scales up to 2x or 4x (33 energy) blocked
doesn't stack with spherical tech doesn't stack with spherical tech
in testing mode console log the body you click on
make a tech that improves all charge guns make a tech that improves all charge guns
for: pulse, foam, rail gun for: pulse, foam, rail gun
effect: effect:
@@ -58,8 +57,10 @@ tech: use the ability for power ups to have custom code
attracted to other power ups attracted to other power ups
explode if they touch? explode if they touch?
pause should show the last in game console message consider executables:
press F to do things
ideas:
nail-gun, or .... nail-gun, or ....
1s after being fired your bullets turn: 1s after being fired your bullets turn:
towards the nearest mob towards the nearest mob
@@ -352,6 +353,8 @@ possible names for tech
Laplace's demon was a notable published articulation of causal determinism on a scientific basis by Pierre-Simon Laplace in 1814.[1] According to determinism, if someone (the demon) knows the precise location and momentum of every atom in the universe, their past and future values for any given time are entailed; they can be calculated from the laws of classical mechanics. Laplace's demon was a notable published articulation of causal determinism on a scientific basis by Pierre-Simon Laplace in 1814.[1] According to determinism, if someone (the demon) knows the precise location and momentum of every atom in the universe, their past and future values for any given time are entailed; they can be calculated from the laws of classical mechanics.
evolutionary cosmology evolutionary cosmology
eternal inflation eternal inflation
hypergraph
gnarl
a tutorial / lore intro a tutorial / lore intro
needs to be optional so it doesn't slow experienced players needs to be optional so it doesn't slow experienced players