depolarization
community map - arena by Richard0820 skin tech: depolarization - gain +300 damage or -50% damage if a mobs has died in last 5 seconds CPT triggers if you have above 90->85 energy CPT skin graphically indicates when CPT is active mass-energy defense reduction is 66->50% new level load display animation draws the outline of the new map only on reactor and final levels choose MINIMAL HUD in settings to disable (or enter testing mode) enthalpy spawns heals on mobs death with a 5% chance this is roughly an 80% increase in spawn rate mass production spawns a few ammo and heals when you first get it paradigm shift 6->4 health removed incendiary ammunition drone and shotgun explosions are 30% bigger Zectron super balls do 75->90% more damage and drain 25->20 energy on hitting player fixed bug with optical amplifier and cloaking field plasma ball can pick up power ups when out of energy, like other fields fixed bug with not hiding mouse
This commit is contained in:
13
js/bullet.js
13
js/bullet.js
@@ -3545,7 +3545,7 @@ const b = {
|
||||
} else {
|
||||
if (tech.isIncendiary && simulation.cycle + this.deathCycles < this.endCycle && !tech.isForeverDrones) {
|
||||
const max = Math.max(Math.min(this.endCycle - simulation.cycle - this.deathCycles, 1500), 0)
|
||||
b.explosion(this.position, max * 0.1 + this.isImproved * 110 + 60 * Math.random()); //makes bullet do explosive damage at end
|
||||
b.explosion(this.position, max * 0.14 + this.isImproved * 110 + 60 * Math.random()); //makes bullet do explosive damage at end
|
||||
if (tech.isForeverDrones) {
|
||||
this.endCycle = 0
|
||||
b.drone({ x: m.pos.x + 30 * (Math.random() - 0.5), y: m.pos.y + 30 * (Math.random() - 0.5) }, 5)
|
||||
@@ -4028,7 +4028,7 @@ const b = {
|
||||
bullet[me] = Bodies.polygon(where.x, where.y, 12, radius, b.fireAttributes(dir, false));
|
||||
Composite.add(engine.world, bullet[me]); //add bullet to world
|
||||
Matter.Body.setVelocity(bullet[me], velocity);
|
||||
bullet[me].calcDensity = function () { return 0.0007 + 0.00055 * tech.isSuperHarm + 0.0004 * tech.isBulletTeleport }
|
||||
bullet[me].calcDensity = function () { return 0.0007 + 0.00065 * tech.isSuperHarm + 0.0004 * tech.isBulletTeleport }
|
||||
Matter.Body.setDensity(bullet[me], bullet[me].calcDensity());
|
||||
bullet[me].endCycle = simulation.cycle + Math.floor(270 + 90 * Math.random());
|
||||
bullet[me].minDmgSpeed = 0;
|
||||
@@ -4041,7 +4041,7 @@ const b = {
|
||||
this.force.y += this.mass * 0.001;
|
||||
if (Matter.Query.collides(this, [player]).length) {
|
||||
this.endCycle = 0
|
||||
m.energy -= m.energy * 0.25
|
||||
m.energy -= m.energy * 0.2
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: this.position.x,
|
||||
y: this.position.y,
|
||||
@@ -6583,7 +6583,7 @@ const b = {
|
||||
if (tech.isIncendiary) {
|
||||
bullet[me].endCycle = simulation.cycle + 60
|
||||
bullet[me].onEnd = function () {
|
||||
b.explosion(this.position, 360 + (Math.random() - 0.5) * 60); //makes bullet do explosive damage at end
|
||||
b.explosion(this.position, 400 + (Math.random() - 0.5) * 60); //makes bullet do explosive damage at end
|
||||
}
|
||||
bullet[me].beforeDmg = function () {
|
||||
this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion
|
||||
@@ -6642,7 +6642,7 @@ const b = {
|
||||
y: speed * Math.sin(dirOff)
|
||||
});
|
||||
bullet[me].onEnd = function () {
|
||||
b.explosion(this.position, 150 * (tech.isShotgunReversed ? 1.4 : 1) + (Math.random() - 0.5) * 30); //makes bullet do explosive damage at end
|
||||
b.explosion(this.position, 180 * (tech.isShotgunReversed ? 1.4 : 1) + (Math.random() - 0.5) * 30); //makes bullet do explosive damage at end
|
||||
}
|
||||
bullet[me].beforeDmg = function () {
|
||||
this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion
|
||||
@@ -8164,10 +8164,11 @@ const b = {
|
||||
if (tech.isStuckOn) {
|
||||
if (this.isStuckOn) {
|
||||
if (!input.fire) this.fire();
|
||||
if (m.energy < tech.laserDrain) this.isStuckOn = false
|
||||
if (m.energy < tech.laserDrain + 0.06) this.isStuckOn = false
|
||||
} else if (input.fire) {
|
||||
this.isStuckOn = true
|
||||
}
|
||||
// console.log(this.isStuckOn)
|
||||
}
|
||||
},
|
||||
do() { },
|
||||
|
||||
@@ -109,7 +109,7 @@ function collisionChecks(event) {
|
||||
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0
|
||||
// if (m.isCloak) dmg *= 0.5
|
||||
mob[k].foundPlayer();
|
||||
if (tech.isRewindAvoidDeath && (m.energy + 0.05) > Math.min(0.95, m.maxEnergy) && dmg > 0.01) { //CPT reversal runs in m.damage, but it stops the rest of the collision code here too
|
||||
if (tech.isRewindAvoidDeath && m.energy > 0.85 * Math.min(1, m.maxEnergy) && dmg > 0.01) { //CPT reversal runs in m.damage, but it stops the rest of the collision code here too
|
||||
m.damage(dmg);
|
||||
return
|
||||
}
|
||||
|
||||
@@ -408,6 +408,7 @@ ${botText}
|
||||
${junkCount ? `<br><strong class='color-junk'>JUNK</strong>: ${(junkCount / totalCount * 100).toFixed(1)}% ` : ""}
|
||||
<br>
|
||||
<br>level: ${level.levelsCleared} ${level.levels[level.onLevel]} (${level.difficultyText()})
|
||||
<br>mobs: ${spawn.pickList[0]}, ${spawn.pickList[0]}
|
||||
<br>seed: ${Math.initialSeed} ${m.cycle} cycles
|
||||
<br>mobs: ${mob.length} blocks: ${body.length} bullets: ${bullet.length} power ups: ${powerUp.length}
|
||||
${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
|
||||
|
||||
691
js/level.js
691
js/level.js
@@ -11,7 +11,7 @@ const level = {
|
||||
// playableLevels: ["pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion"],
|
||||
//see level.populateLevels: (initial, ... , reservoir or factory, reactor, ... , subway, final) added later
|
||||
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock"],
|
||||
communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass", "cantilever", "tlinat", "ruins", "ace", "crimsonTowers", "LaunchSite", "shipwreck", "unchartedCave", "dojo"],
|
||||
communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass", "cantilever", "tlinat", "ruins", "ace", "crimsonTowers", "LaunchSite", "shipwreck", "unchartedCave", "dojo", 'arena'],
|
||||
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"],
|
||||
levels: [],
|
||||
start() {
|
||||
@@ -28,29 +28,30 @@ const level = {
|
||||
// tech.tech[297].frequency = 100
|
||||
// m.couplingChange(10)
|
||||
// m.setField("metamaterial cloaking") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook
|
||||
// m.energy = 0
|
||||
// tech.isHookWire = true
|
||||
// m.energy = 0
|
||||
// simulation.molecularMode = 2
|
||||
// m.damage(0.1);
|
||||
// b.giveGuns("super balls") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
|
||||
// b.giveGuns("harpoon") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
|
||||
// b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
|
||||
// b.guns[8].ammo = 100000000
|
||||
// requestAnimationFrame(() => { tech.giveTech("Higgs mechanism") });
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("martingale")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("paradigm shift")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("bubble fusion")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("optical amplifier")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("depolarization")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("mass production")
|
||||
// requestAnimationFrame(() => { for (let i = 0; i < 10; i++) tech.giveTech("orbital-bot") });
|
||||
// requestAnimationFrame(() => { for (let i = 0; i < 10; i++) b.orbitBot(m.pos, false) });
|
||||
// m.skin.hexagon();
|
||||
|
||||
|
||||
// for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("quenching")
|
||||
// for (let i = 0; i < 3; ++i) tech.giveTech("adiabatic healing")
|
||||
// m.lastKillCycle = m.cycle
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("depolarization")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("CPT symmetry")
|
||||
// for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech");
|
||||
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research");
|
||||
// for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling");
|
||||
// level.testing();
|
||||
// level.arena();
|
||||
|
||||
// for (let i = 0; i < 4; ++i) spawn.hopMother(1900, -500)
|
||||
// for (let i = 0; i < 4; ++i) spawn.stinger(1900, -500)
|
||||
@@ -287,8 +288,9 @@ const level = {
|
||||
tech.isDeathAvoidedThisLevel = false;
|
||||
simulation.updateTechHUD();
|
||||
simulation.clearNow = true; //triggers in simulation.clearMap to remove all physics bodies and setup for new map
|
||||
|
||||
//pop up new level info screen for a few seconds
|
||||
if (!simulation.isChoosing && m.alive && (level.levels[level.onLevel] === "final" || level.levels[level.onLevel] === "reactor")) { //level.levels[level.onLevel] === "subway" ||
|
||||
if (!localSettings.isHideHUD && !simulation.isChoosing && !simulation.isCheating && m.alive && (level.levels[level.onLevel] === "final" || level.levels[level.onLevel] === "reactor" || level.levels[level.onLevel] === "subway")) {
|
||||
//pause
|
||||
if (!simulation.paused) {
|
||||
simulation.paused = true;
|
||||
@@ -296,6 +298,7 @@ const level = {
|
||||
}
|
||||
//build level info
|
||||
document.getElementById("choose-grid").style.gridTemplateColumns = "250px"
|
||||
//onclick="level.unPause()"
|
||||
let text = `<div><div class="card-background" style="height:auto; border: none; background-color: transparent; line-height: 160%; background-color: var(--card-color); font-size: 1.15em;"> <div class="card-text">`
|
||||
for (let i = 0; i < level.levels.length; i++) {
|
||||
if (i < level.levelsCleared) {
|
||||
@@ -322,7 +325,7 @@ const level = {
|
||||
simulation.draw.cons();
|
||||
simulation.draw.body();
|
||||
level.customTopLayer();
|
||||
let count = simulation.testing ? 0 : 240
|
||||
let count = countMax = simulation.testing ? 0 : 180
|
||||
let newLevelDraw = () => {
|
||||
count--
|
||||
if (count > 0) {
|
||||
@@ -354,7 +357,16 @@ const level = {
|
||||
// mobs.draw();
|
||||
// } else
|
||||
// if (count < 240) {
|
||||
|
||||
// ctx.lineDashOffset = 900 * Math.random()
|
||||
// ctx.setLineDash([3, -8 + 0.5 * count]);
|
||||
|
||||
const scale = 10
|
||||
ctx.setLineDash([scale * (countMax - count), scale * count]);
|
||||
simulation.draw.wireFrame();
|
||||
ctx.setLineDash([]);
|
||||
|
||||
|
||||
// }
|
||||
// else if (count === 91) { //hide text boss
|
||||
// document.getElementById("choose-grid").style.opacity = "0"
|
||||
@@ -591,6 +603,7 @@ const level = {
|
||||
document.getElementById("choose-grid").style.visibility = "visible"
|
||||
document.getElementById("choose-training").addEventListener("click", () => {
|
||||
level.unPause()
|
||||
document.body.style.cursor = "none";
|
||||
simulation.isTraining = true
|
||||
level.levelsCleared--;
|
||||
level.onLevel--
|
||||
@@ -608,6 +621,7 @@ const level = {
|
||||
});
|
||||
document.getElementById("choose-unPause").addEventListener("click", () => {
|
||||
level.unPause()
|
||||
document.body.style.cursor = "none";
|
||||
level.nextLevel()
|
||||
//reset hide image style
|
||||
if (localSettings.isHideImages) {
|
||||
@@ -31120,6 +31134,661 @@ const level = {
|
||||
boss.showHealthBar = true;
|
||||
powerUps.addResearchToLevel() //needs to run after mobs are spawned
|
||||
},
|
||||
arena() {
|
||||
simulation.makeTextLog(`<strong>arena</strong> by <span class='color-var'>Richard0820</span>`)
|
||||
let isUsingSwordMod = false;
|
||||
for (let i = 0; i < tech.tech.length; i++) {
|
||||
if (tech.tech[i].name === 'size-weight illusion') { //to detect if the player is using the sword mod so that it won't mess up their mod. The sword mod adds this tech so if it is detected then the sword won't be removed from the gun array //Landgreen, don't add a tech with the same name
|
||||
isUsingSwordMod = true;
|
||||
}
|
||||
}
|
||||
if (!isUsingSwordMod) {
|
||||
(function () {
|
||||
const e = {
|
||||
name: "sword",
|
||||
descriptionFunction() { return `swing a <b>sword</b> that <b style="color: indigo;">lifesteals</b> <strong class='color-h'>health</strong><br>drains <strong class='color-h'>health</strong> instead of ammunition<br>doesn't use <b>ammo</b>` },
|
||||
ammo: Infinity,
|
||||
ammoPack: Infinity,
|
||||
defaultAmmoPack: Infinity,
|
||||
have: false,
|
||||
cycle: 0,
|
||||
sword: undefined,
|
||||
bladeSegments: undefined,
|
||||
bladeTrails: [],
|
||||
angle: 0,
|
||||
constraint: undefined,
|
||||
do() {
|
||||
if (input.fire && m.fireCDcycle > m.cycle) {
|
||||
if (tech.isEnergyHealth) {
|
||||
m.energy -= 0.004;
|
||||
} else {
|
||||
m.health -= 0.001;
|
||||
m.displayHealth();
|
||||
}
|
||||
}
|
||||
if (b.activeGun !== null && input.fire && (tech.isEnergyHealth ? m.energy >= 0.11 : m.health >= 0.11)) {
|
||||
if (!this.sword && b.guns[b.activeGun].name === 'sword') {
|
||||
Matter.Body.setMass(player, 1000);
|
||||
({ sword: this.sword, bladeSegments: this.bladeSegments } = this.createAndSwingSword());
|
||||
this.angle = m.angle;
|
||||
}
|
||||
}
|
||||
if (this.sword && !input.fire) {
|
||||
this.cycle = 0;
|
||||
Matter.Body.setAngularVelocity(this.sword, 0);
|
||||
Matter.Body.setMass(player, 5)
|
||||
Composite.remove(engine.world, this.sword);
|
||||
this.sword.parts.forEach(part => {
|
||||
Composite.remove(engine.world, part);
|
||||
const index = bullet.indexOf(part);
|
||||
if (index !== -1) {
|
||||
bullet.splice(index, 1);
|
||||
}
|
||||
});
|
||||
this.sword = undefined;
|
||||
if (this.constraint) {
|
||||
Composite.remove(engine.world, this.constraint);
|
||||
this.constraint = undefined;
|
||||
}
|
||||
this.bladeTrails = [];
|
||||
m.fireCDcycle = m.cycle + 10;
|
||||
} else {
|
||||
if (this.sword && (tech.isEnergyHealth ? m.energy >= 0.11 : m.health >= 0.11)) {
|
||||
let handle;
|
||||
for (let i = 0; i < bullet.length; i++) {
|
||||
if (bullet[i].customName == "handle") {
|
||||
handle = bullet[i];
|
||||
}
|
||||
}
|
||||
if (!(this.angle > -Math.PI / 2 && this.angle < Math.PI / 2)) {
|
||||
Matter.Body.setAngularVelocity(this.sword, -Math.PI * 0.1);
|
||||
} else {
|
||||
Matter.Body.setAngularVelocity(this.sword, Math.PI * 0.1);
|
||||
}
|
||||
if (!this.constraint && (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) {
|
||||
this.constraint = Constraint.create({
|
||||
bodyA: player,
|
||||
bodyB: this.sword,
|
||||
pointB: { x: -9, y: ((handle.position.y - this.sword.position.y)) },
|
||||
stiffness: 0.1,
|
||||
damping: 0.0001815,
|
||||
length: 0,
|
||||
|
||||
});
|
||||
Composite.add(engine.world, this.constraint);
|
||||
} else if (!this.constraint) {
|
||||
this.constraint = Constraint.create({
|
||||
bodyA: player,
|
||||
bodyB: this.sword,
|
||||
pointB: { x: 9, y: ((handle.position.y - this.sword.position.y)) },
|
||||
stiffness: 0.1,
|
||||
damping: 0.0001815,
|
||||
length: 0,
|
||||
});
|
||||
Composite.add(engine.world, this.constraint);
|
||||
}
|
||||
} else if (this.sword) {
|
||||
if (tech.isEnergyHealth) {
|
||||
m.energy = 0.01;
|
||||
m.immuneCycle = m.cycle + 30;
|
||||
}
|
||||
this.cycle = 0;
|
||||
Matter.Body.setAngularVelocity(this.sword, 0);
|
||||
Matter.Body.setMass(player, 5)
|
||||
Composite.remove(engine.world, this.sword);
|
||||
this.sword.parts.forEach(part => {
|
||||
Composite.remove(engine.world, part);
|
||||
const index = bullet.indexOf(part);
|
||||
if (index !== -1) {
|
||||
bullet.splice(index, 1);
|
||||
}
|
||||
});
|
||||
this.sword = undefined;
|
||||
if (this.constraint) {
|
||||
Composite.remove(engine.world, this.constraint);
|
||||
this.constraint = undefined;
|
||||
}
|
||||
this.bladeTrails = [];
|
||||
m.fireCDcycle = 0;
|
||||
}
|
||||
}
|
||||
if (this.sword) {
|
||||
for (let i = 0; i < this.bladeSegments.length; i++) {
|
||||
const blade = this.bladeSegments[i];
|
||||
const trail = this.bladeTrails[i] || [];
|
||||
const vertices = blade.vertices.map(vertex => ({ x: vertex.x, y: vertex.y }));
|
||||
trail.push(vertices);
|
||||
if (trail.length > 10) {
|
||||
trail.shift();
|
||||
}
|
||||
this.bladeTrails[i] = trail;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.bladeTrails.length; i++) {
|
||||
const trail = this.bladeTrails[i];
|
||||
|
||||
const alphaStep = 1 / trail.length;
|
||||
let alpha = 0;
|
||||
|
||||
for (let j = 0; j < trail.length; j++) {
|
||||
const vertices = trail[j];
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||
|
||||
for (let k = 1; k < vertices.length; k++) {
|
||||
ctx.lineTo(vertices[k].x, vertices[k].y);
|
||||
};
|
||||
|
||||
alpha += alphaStep;
|
||||
ctx.closePath();
|
||||
if (tech.isEnergyHealth) {
|
||||
const eyeColor = m.fieldMeterColor;
|
||||
const r = eyeColor[1];
|
||||
const g = eyeColor[2];
|
||||
const b = eyeColor[3];
|
||||
const color = `#${r}${r}${g}${g}${b}${b}${Math.round(alpha * 255).toString(16).padStart(2, '0')}`;
|
||||
ctx.fillStyle = color;
|
||||
} else {
|
||||
ctx.fillStyle = `rgba(220, 20, 60, ${alpha})`;
|
||||
}
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < this.bladeSegments.length; i++) {
|
||||
ctx.beginPath();
|
||||
ctx.lineJoin = "miter";
|
||||
ctx.miterLimit = 100;
|
||||
ctx.strokeStyle = tech.isEnergyHealth ? m.fieldMeterColor : tech.isAmmoSword ? "#c0c0c0" : "crimson";
|
||||
ctx.lineWidth = 5;
|
||||
ctx.fillStyle = "black";
|
||||
ctx.moveTo(this.bladeSegments[i].vertices[0].x, this.bladeSegments[i].vertices[0].y);
|
||||
for (let j = 0; j < this.bladeSegments[i].vertices.length; j++) {
|
||||
ctx.lineTo(this.bladeSegments[i].vertices[j].x, this.bladeSegments[i].vertices[j].y)
|
||||
};
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
ctx.fill();
|
||||
ctx.lineJoin = "round";
|
||||
ctx.miterLimit = 10;
|
||||
}
|
||||
}
|
||||
if (this.sword) {
|
||||
for (let i = 0; i < mob.length; i++) {
|
||||
if (Matter.Query.collides(this.sword, [mob[i]]).length > 0) {
|
||||
const dmg = m.dmgScale * 6 * Math.sqrt(this.sword.speed);
|
||||
if (m.health < 0.9) {
|
||||
if (tech.isEnergyHealth) {
|
||||
m.energy += 0.04;
|
||||
} else {
|
||||
m.health += 0.001 * (dmg - mob[i].health);
|
||||
m.displayHealth();
|
||||
}
|
||||
} else {
|
||||
if (tech.isEnergyHealth) {
|
||||
m.energy += 0.04;
|
||||
} else {
|
||||
m.health = m.maxHealth;
|
||||
m.displayHealth();
|
||||
}
|
||||
}
|
||||
mob[i].damage(dmg, true);
|
||||
simulation.drawList.push({
|
||||
x: mob[i].position.x,
|
||||
y: mob[i].position.y,
|
||||
radius: Math.sqrt(dmg / this.sword.speed) * 50,
|
||||
color: simulation.mobDmgColor,
|
||||
time: simulation.drawTime
|
||||
});
|
||||
const angle = Math.atan2(mob[i].position.y - this.sword.position.y, mob[i].position.x - this.sword.position.x);
|
||||
this.sword.force.x -= Math.cos(angle) * 5;
|
||||
this.sword.force.y -= Math.sin(angle) * 5;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
createAndSwingSword(x = player.position.x, y = player.position.y, angle = m.angle) {
|
||||
if (this.cycle < m.cycle) {
|
||||
this.cycle = Infinity;
|
||||
m.fireCDcycle = Infinity;
|
||||
const handleWidth = 20;
|
||||
const handleHeight = 150;
|
||||
const handle = Bodies.rectangle(x, y, handleWidth, handleHeight, spawn.propsIsNotHoldable);
|
||||
bullet[bullet.length] = handle;
|
||||
handle.customName = "handle";
|
||||
bullet[bullet.length - 1].do = () => { };
|
||||
const bladeWidth = 100;
|
||||
const bladeHeight = 20;
|
||||
const numBlades = 15;
|
||||
const extensionFactor = 5;
|
||||
const bladeSegments = [];
|
||||
if ((angle > -Math.PI / 2 && angle < Math.PI / 2)) {
|
||||
for (let i = 0; i < numBlades; i++) {
|
||||
const extensionFactorFraction = (i / (numBlades - 1)) * extensionFactor;
|
||||
const bladeX = x + i * (bladeWidth / 20);
|
||||
const bladeY = y - handleHeight / 2 - i * (bladeHeight / 4.5) * extensionFactor;
|
||||
|
||||
const vertices = [
|
||||
{ x: bladeX, y: bladeY - bladeHeight / 2 },
|
||||
{ x: bladeX + bladeWidth / 2, y: bladeY + bladeHeight / 2 },
|
||||
{ x: bladeX - bladeWidth / 2, y: bladeY + bladeHeight / 2 },
|
||||
{ x: bladeX, y: bladeY - bladeHeight / 2 + 10 },
|
||||
];
|
||||
|
||||
const blade = Bodies.fromVertices(bladeX, bladeY, vertices, spawn.propsIsNotHoldable);
|
||||
bullet[bullet.length] = blade;
|
||||
bullet[bullet.length - 1].do = () => { };
|
||||
Matter.Body.rotate(blade, -Math.sin(i * (Math.PI / 270) * 15));
|
||||
bladeSegments.push(blade);
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < numBlades; i++) {
|
||||
const extensionFactorFraction = (i / (numBlades - 1)) * extensionFactor;
|
||||
const mirroredBladeX = x - i * (bladeWidth / 20);
|
||||
const mirroredBladeY = y - handleHeight / 2 - i * (bladeHeight / 4.5) * extensionFactor;
|
||||
const mirroredVertices = [
|
||||
{ x: mirroredBladeX, y: mirroredBladeY - bladeHeight / 2 },
|
||||
{ x: mirroredBladeX + bladeWidth / 2, y: mirroredBladeY + bladeHeight / 2 },
|
||||
{ x: mirroredBladeX - bladeWidth / 2, y: mirroredBladeY + bladeHeight / 2 },
|
||||
{ x: mirroredBladeX, y: mirroredBladeY - bladeHeight / 2 + 10 },
|
||||
];
|
||||
const mirroredBlade = Bodies.fromVertices(mirroredBladeX, mirroredBladeY, mirroredVertices, spawn.propsIsNotHoldable);
|
||||
bullet[bullet.length] = mirroredBlade;
|
||||
bullet[bullet.length - 1].do = () => { };
|
||||
Matter.Body.rotate(mirroredBlade, Math.sin(i * (Math.PI / 270) * 15));
|
||||
bladeSegments.push(mirroredBlade);
|
||||
}
|
||||
}
|
||||
const sword = Body.create({
|
||||
parts: [handle, ...bladeSegments],
|
||||
});
|
||||
|
||||
Composite.add(engine.world, sword);
|
||||
Matter.Body.setPosition(sword, { x, y });
|
||||
|
||||
sword.collisionFilter.category = cat.bullet;
|
||||
sword.collisionFilter.mask = cat.mobBullet | cat.mob;
|
||||
Body.scale(sword, -1, 1, { x, y });
|
||||
// sword.frictionAir -= 0.01;
|
||||
|
||||
return { sword, bladeSegments };
|
||||
}
|
||||
},
|
||||
fire() { }
|
||||
};
|
||||
b.guns.push(e);
|
||||
const gunArray = b.guns.filter(
|
||||
(obj, index, self) =>
|
||||
index === self.findIndex((item) => item.name === obj.name)
|
||||
);
|
||||
b.guns = gunArray;
|
||||
})();
|
||||
}
|
||||
simulation.makeTextLog(`<strong>arena</strong> by <span class='color-var'>Richard0820</span>`);
|
||||
let index = 0;
|
||||
let index2 = 0;
|
||||
let { sword: sword, bladeSegments: bladeSegments } = createSword();
|
||||
const door = level.door(-950, -3000, 400, 4000, 2000, 10);
|
||||
const door2 = level.door(550, -3000, 400, 4000, 2000, 10);
|
||||
level.setPosToSpawn(-7900, -2550); //normal spawn
|
||||
level.exit.x = 7875;
|
||||
level.exit.y = -2530;
|
||||
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance
|
||||
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit
|
||||
level.defaultZoom = 8000
|
||||
simulation.zoomTransition(level.defaultZoom)
|
||||
document.body.style.backgroundColor = "#987654";
|
||||
color.map = "#765432" //custom map color
|
||||
color.block = "#876543";
|
||||
door.isClosing = true;
|
||||
door2.isClosing = true;
|
||||
spawnStuff(1000, -3100, 4450, 3125, 50 / simulation.difficultyMode);
|
||||
spawnStuff(5400, -2425, 200, 2250, 5 / simulation.difficultyMode);
|
||||
spawnStuff(5625, -2425, 2000, 275, 5 / simulation.difficultyMode);
|
||||
spawnStuff(5625, -2125, 850, 1125, 5 / simulation.difficultyMode);
|
||||
spawnStuff(6500, -2150, 475, 650, 5 / simulation.difficultyMode);
|
||||
spawnStuff(7000, -2125, 325, 275, 5 / simulation.difficultyMode);
|
||||
spawnStuff(5650, -950, 300, 450, 5 / simulation.difficultyMode);
|
||||
spawn.randomLevelBoss(4225, -575);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
powerUps.spawn(-6075, -2000, "heal");
|
||||
}
|
||||
let bladeTrails = [];
|
||||
let isOwned = false;
|
||||
class Particle {
|
||||
constructor() {
|
||||
this.x = player.position.x + Math.random() * 10000 - 5000;
|
||||
this.y = player.position.y + Math.random() * 10000 - 5000;
|
||||
this.vx = 0;
|
||||
this.vy = 0;
|
||||
this.accelX = 0;
|
||||
this.accelY = 0;
|
||||
this.life = 2000;
|
||||
this.alpha = 1;
|
||||
this.size = 8;
|
||||
}
|
||||
|
||||
update() {
|
||||
this.vx += this.accelX;
|
||||
this.vy += this.accelY;
|
||||
this.x += this.vx;
|
||||
this.y += this.vy;
|
||||
|
||||
if (this.x < player.position.x - 5000 || this.x > player.position.x + 5000 ||
|
||||
this.y < player.position.y - 5000 || this.y > player.position.y + 5000) {
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.x = player.position.x + Math.random() * 10000 - 5000;
|
||||
this.y = player.position.y + Math.random() * 10000 - 5000;
|
||||
this.vx = 0;
|
||||
this.vy = 0;
|
||||
this.life = Math.random() * 1000 + 1000;
|
||||
this.maxLife = this.life;
|
||||
}
|
||||
|
||||
draw(ctx) {
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = `rgba(255, 255, 255, ${this.alpha})`;
|
||||
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
ctx.closePath();
|
||||
}
|
||||
|
||||
isAlive() {
|
||||
return this.life >= 0;
|
||||
}
|
||||
}
|
||||
class ParticleSystem {
|
||||
constructor() {
|
||||
this.particles = [];
|
||||
this.updateHandler = undefined;
|
||||
}
|
||||
|
||||
addParticle(particle) {
|
||||
this.particles.push(particle);
|
||||
}
|
||||
|
||||
update(deltaTime = 0) {
|
||||
this.particles.forEach(particle => {
|
||||
particle.update(deltaTime);
|
||||
this.updateHandler && this.updateHandler(particle);
|
||||
});
|
||||
}
|
||||
|
||||
onUpdate(fn) {
|
||||
this.updateHandler = fn;
|
||||
}
|
||||
}
|
||||
let system = new ParticleSystem();
|
||||
for (let i = 0; i < 200; i++) {
|
||||
let particle = new Particle();
|
||||
system.addParticle(particle);
|
||||
}
|
||||
system.onUpdate((particle) => {
|
||||
if (!particle.isAlive()) {
|
||||
particle.reset();
|
||||
}
|
||||
|
||||
particle.life -= 10;
|
||||
particle.accelX = (Math.random() - 0.5) * 0.02;
|
||||
particle.accelY = (Math.random() - 0.5) * 0.02;
|
||||
|
||||
if (particle.life >= particle.maxLife / 2) {
|
||||
particle.alpha = 1 - (particle.life / particle.maxLife);
|
||||
} else {
|
||||
particle.alpha = particle.life / particle.maxLife;
|
||||
}
|
||||
|
||||
particle.update();
|
||||
});
|
||||
function update() {
|
||||
system.update();
|
||||
}
|
||||
function draw() {
|
||||
system.particles.forEach(particle => particle.draw(ctx));
|
||||
}
|
||||
level.custom = () => {
|
||||
update();
|
||||
draw();
|
||||
for (let i = 0, len = b.guns.length; i < len; i++) {
|
||||
if (b.guns[i].name === "sword" && b.guns[i].have) {
|
||||
isOwned = true;
|
||||
}
|
||||
}
|
||||
Matter.Body.setPosition(sword, { x: -3950, y: -275 - (Math.sin(simulation.cycle / 100) * 50) });
|
||||
Matter.Body.setAngularVelocity(sword, 0);
|
||||
door.openClose();
|
||||
door2.openClose();
|
||||
if (Matter.Collision.collides(sword, player) && index <= 0 || isOwned) {
|
||||
bladeTrails = [];
|
||||
bladeSegments = [];
|
||||
Composite.remove(engine.world, sword);
|
||||
sword.parts.forEach(part => {
|
||||
Composite.remove(engine.world, part);
|
||||
const index = bullet.indexOf(part);
|
||||
if (index !== -1) {
|
||||
bullet.splice(index, 1);
|
||||
}
|
||||
});
|
||||
b.giveGuns("sword");
|
||||
door.isClosing = false;
|
||||
door2.isClosing = false;
|
||||
index++;
|
||||
}
|
||||
|
||||
level.exit.drawAndCheck();
|
||||
|
||||
level.enter.draw();
|
||||
if (tech.isEnergyHealth) {
|
||||
ctx.beginPath();
|
||||
const gradient = ctx.createRadialGradient(-3950, 0, 5, -3950, 0, 350 + Math.sin(simulation.cycle * 0.15) * 0.1);
|
||||
gradient.addColorStop(0, m.fieldMeterColor);
|
||||
gradient.addColorStop(0.9, "transparent");
|
||||
// gradient.addColorStop(1, "darkgray");
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.strokeStyle = "transparent";
|
||||
ctx.fillRect(-4000, -350, 100, 350);
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
} else {
|
||||
ctx.beginPath();
|
||||
const gradient = ctx.createLinearGradient(-3500, 0, -3500, -350 + Math.sin(simulation.cycle * 0.15) * 0.1);
|
||||
gradient.addColorStop(0, "crimson");
|
||||
gradient.addColorStop(0.9, "transparent");
|
||||
// gradient.addColorStop(1, "darkgray");
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.strokeStyle = "transparent";
|
||||
ctx.fillRect(-4000, -350, 100, 350);
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
}
|
||||
if (player.position.x > -4000 && player.position.x < -3900 && player.position.y > -350 && player.position.y < 0) {
|
||||
player.force.y -= 0.03;
|
||||
}
|
||||
|
||||
if (player.position.x > level.exit.x && player.position.x < level.exit.x + 100 && player.position.y > level.exit.y - 150 && player.position.y < level.exit.y - 0 && player.velocity.y < .15 && index2 == 0 && !isUsingSwordMod) {
|
||||
b.removeGun("sword"); //completely removing the stuff (if you leave properly through the door)
|
||||
for (let i = 0, len = b.guns.length; i < len; i++) {
|
||||
if (b.guns[i].name === "sword") {
|
||||
b.guns.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
index2++;
|
||||
simulation.makeTextLog(`If you want to keep this sword, visit <a href="https://github.com/Whyisthisnotavalable/n-scythe">https://github.com/Whyisthisnotavalable/n-scythe</a>. The sword is there.`)
|
||||
}
|
||||
for (let i = 0; i < bladeSegments.length; i++) {
|
||||
const blade = bladeSegments[i];
|
||||
const trail = bladeTrails[i] || [];
|
||||
const vertices = blade.vertices.map(vertex => ({ x: vertex.x, y: vertex.y }));
|
||||
trail.push(vertices);
|
||||
if (trail.length > 10) {
|
||||
trail.shift();
|
||||
}
|
||||
bladeTrails[i] = trail;
|
||||
}
|
||||
|
||||
for (let i = 0; i < bladeTrails.length; i++) {
|
||||
const trail = bladeTrails[i];
|
||||
|
||||
const alphaStep = 1 / trail.length;
|
||||
let alpha = 0;
|
||||
|
||||
for (let j = 0; j < trail.length; j++) {
|
||||
const vertices = trail[j];
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||
|
||||
for (let k = 1; k < vertices.length; k++) {
|
||||
ctx.lineTo(vertices[k].x, vertices[k].y);
|
||||
};
|
||||
|
||||
alpha += alphaStep;
|
||||
ctx.closePath();
|
||||
if (tech.isEnergyHealth) {
|
||||
const eyeColor = m.fieldMeterColor;
|
||||
const r = eyeColor[1];
|
||||
const g = eyeColor[2];
|
||||
const b = eyeColor[3];
|
||||
const color = `#${r}${r}${g}${g}${b}${b}${Math.round(alpha * 255).toString(16).padStart(2, '0')}`;
|
||||
ctx.fillStyle = color;
|
||||
} else {
|
||||
ctx.fillStyle = `rgba(220, 20, 60, ${alpha})`;
|
||||
}
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < bladeSegments.length; i++) {
|
||||
ctx.beginPath();
|
||||
ctx.lineJoin = "miter";
|
||||
ctx.miterLimit = 100;
|
||||
ctx.strokeStyle = tech.isEnergyHealth ? m.fieldMeterColor : tech.isAmmoSword ? "#c0c0c0" : "crimson";
|
||||
ctx.lineWidth = 5;
|
||||
ctx.fillStyle = "black";
|
||||
ctx.moveTo(bladeSegments[i].vertices[0].x, bladeSegments[i].vertices[0].y);
|
||||
for (let j = 0; j < bladeSegments[i].vertices.length; j++) {
|
||||
ctx.lineTo(bladeSegments[i].vertices[j].x, bladeSegments[i].vertices[j].y)
|
||||
};
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
ctx.fill();
|
||||
ctx.lineJoin = "round";
|
||||
ctx.miterLimit = 10;
|
||||
}
|
||||
if (bladeSegments.length) {
|
||||
ctx.beginPath();
|
||||
ctx.lineJoin = "miter";
|
||||
ctx.miterLimit = 100;
|
||||
ctx.strokeStyle = tech.isEnergyHealth ? m.fieldMeterColor : tech.isAmmoSword ? "#c0c0c0" : "crimson";
|
||||
ctx.lineWidth = 5;
|
||||
ctx.fillStyle = "black";
|
||||
ctx.moveTo(sword.parts[1].vertices[0].x, sword.parts[1].vertices[0].y);
|
||||
for (let j = 0; j < sword.parts[1].vertices.length; j++) {
|
||||
ctx.lineTo(sword.parts[1].vertices[j].x, sword.parts[1].vertices[j].y)
|
||||
};
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
ctx.lineJoin = "round";
|
||||
ctx.miterLimit = 10;
|
||||
}
|
||||
};
|
||||
level.customTopLayer = () => { };
|
||||
|
||||
spawn.mapRect(-10000, 0, 20000, 2000);
|
||||
spawn.mapRect(-10000, -10000, 2000, 10000);
|
||||
spawn.mapRect(8000, -10000, 2000, 10000);
|
||||
spawn.mapRect(-10000, -10000, 20000, 2000);
|
||||
spawn.spawnStairs(8000, 0, 15, 2500, 2500, true);
|
||||
spawn.spawnStairs(-8000, 0, 15, 2500, 2500, false);
|
||||
|
||||
spawn.mapRect(-4000, -10, 100, 20);
|
||||
spawn.mapRect(4000, -10, 100, 20);
|
||||
|
||||
spawn.mapRect(-1000, -10000, 2000, 8000);
|
||||
spawn.mapRect(-500, -10000, 1000, 9700);
|
||||
function createSword(x = 0, y = 0, angle = 0) { //sword asthetic
|
||||
const handleWidth = 20;
|
||||
const handleHeight = 150;
|
||||
const handle = Bodies.rectangle(x, y, handleWidth, handleHeight, spawn.propsIsNotHoldable);
|
||||
bullet[bullet.length] = handle;
|
||||
handle.customName = "handle";
|
||||
bullet[bullet.length - 1].do = () => { };
|
||||
const bladeWidth = 100;
|
||||
const bladeHeight = 20;
|
||||
const numBlades = 15;
|
||||
const extensionFactor = 5;
|
||||
const bladeSegments = [];
|
||||
if ((angle > -Math.PI / 2 && angle < Math.PI / 2)) {
|
||||
for (let i = 0; i < numBlades; i++) {
|
||||
const extensionFactorFraction = (i / (numBlades - 1)) * extensionFactor;
|
||||
const bladeX = x + i * (bladeWidth / 20);
|
||||
const bladeY = y - handleHeight / 2 - i * (bladeHeight / 4.5) * extensionFactor;
|
||||
|
||||
const vertices = [
|
||||
{ x: bladeX, y: bladeY - bladeHeight / 2 },
|
||||
{ x: bladeX + bladeWidth / 2, y: bladeY + bladeHeight / 2 },
|
||||
{ x: bladeX - bladeWidth / 2, y: bladeY + bladeHeight / 2 },
|
||||
{ x: bladeX, y: bladeY - bladeHeight / 2 + 10 },
|
||||
];
|
||||
|
||||
const blade = Bodies.fromVertices(bladeX, bladeY, vertices, spawn.propsIsNotHoldable);
|
||||
bullet[bullet.length] = blade;
|
||||
bullet[bullet.length - 1].do = () => { };
|
||||
Matter.Body.rotate(blade, -Math.sin(i * (Math.PI / 270) * 15));
|
||||
bladeSegments.push(blade);
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < numBlades; i++) {
|
||||
const extensionFactorFraction = (i / (numBlades - 1)) * extensionFactor;
|
||||
const mirroredBladeX = x - i * (bladeWidth / 20);
|
||||
const mirroredBladeY = y - handleHeight / 2 - i * (bladeHeight / 4.5) * extensionFactor;
|
||||
const mirroredVertices = [
|
||||
{ x: mirroredBladeX, y: mirroredBladeY - bladeHeight / 2 },
|
||||
{ x: mirroredBladeX + bladeWidth / 2, y: mirroredBladeY + bladeHeight / 2 },
|
||||
{ x: mirroredBladeX - bladeWidth / 2, y: mirroredBladeY + bladeHeight / 2 },
|
||||
{ x: mirroredBladeX, y: mirroredBladeY - bladeHeight / 2 + 10 },
|
||||
];
|
||||
const mirroredBlade = Bodies.fromVertices(mirroredBladeX, mirroredBladeY, mirroredVertices, spawn.propsIsNotHoldable);
|
||||
bullet[bullet.length] = mirroredBlade;
|
||||
bullet[bullet.length - 1].do = () => { };
|
||||
Matter.Body.rotate(mirroredBlade, Math.sin(i * (Math.PI / 270) * 15));
|
||||
bladeSegments.push(mirroredBlade);
|
||||
}
|
||||
}
|
||||
const sword = Body.create({
|
||||
parts: [handle, ...bladeSegments],
|
||||
});
|
||||
|
||||
Composite.add(engine.world, sword);
|
||||
Matter.Body.setPosition(sword, { x, y });
|
||||
|
||||
sword.collisionFilter.category = cat.bullet;
|
||||
sword.collisionFilter.mask = cat.bullet;
|
||||
Body.scale(sword, -1, 1, { x, y });
|
||||
Body.rotate(sword, Math.PI / 1.05)
|
||||
sword.frictionAir = -0.01;
|
||||
|
||||
return { sword, bladeSegments };
|
||||
}
|
||||
function spawnStuff(x, y, width, height, num) {
|
||||
for (let i = 0; i < num; i++) {
|
||||
randomMob(x + width * Math.random(), y + height * Math.random(), Infinity)
|
||||
}
|
||||
}
|
||||
function randomMob(x, y, chance = 1) {
|
||||
if (spawn.spawnChance(chance) || chance === Infinity) {
|
||||
const pick = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)];
|
||||
spawn[pick](x, y);
|
||||
}
|
||||
if (tech.isDuplicateMobs && Math.random() < tech.duplicationChance()) {
|
||||
const pick = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)];
|
||||
spawn[pick](x, y);
|
||||
}
|
||||
}
|
||||
},
|
||||
// ********************************************************************************************************
|
||||
// ********************************************************************************************************
|
||||
// ***************************************** training levels **********************************************
|
||||
|
||||
27
js/mob.js
27
js/mob.js
@@ -1217,9 +1217,6 @@ const mobs = {
|
||||
dmg *= this.damageReduction
|
||||
//energy and heal drain should be calculated after damage boosts
|
||||
if (tech.energySiphon && dmg !== Infinity && this.isDropPowerUp && m.immuneCycle < m.cycle) m.energy += Math.min(this.health, dmg) * tech.energySiphon
|
||||
if (tech.healthDrain && dmg !== Infinity && this.isDropPowerUp && Math.random() < tech.healthDrain * Math.min(this.health, dmg)) {
|
||||
powerUps.spawn(m.pos.x + 20 * (Math.random() - 0.5), m.pos.y + 20 * (Math.random() - 0.5), "heal");
|
||||
}
|
||||
dmg /= Math.sqrt(this.mass)
|
||||
}
|
||||
|
||||
@@ -1307,6 +1304,30 @@ const mobs = {
|
||||
});
|
||||
}
|
||||
}
|
||||
if (tech.healSpawn && Math.random() < tech.healSpawn) {
|
||||
powerUps.spawn(this.position.x + 20 * (Math.random() - 0.5), this.position.y + 20 * (Math.random() - 0.5), "heal");
|
||||
simulation.drawList.push({
|
||||
x: this.position.x,
|
||||
y: this.position.y,
|
||||
radius: 50,
|
||||
color: "#0eb",
|
||||
time: 12
|
||||
});
|
||||
simulation.drawList.push({
|
||||
x: this.position.x,
|
||||
y: this.position.y,
|
||||
radius: 100,
|
||||
color: "#0eb",
|
||||
time: 6
|
||||
});
|
||||
simulation.drawList.push({
|
||||
x: this.position.x,
|
||||
y: this.position.y,
|
||||
radius: 200,
|
||||
color: "#0eb",
|
||||
time: 3
|
||||
});
|
||||
}
|
||||
|
||||
if (tech.deathSkipTime && !m.isBodiesAsleep) {
|
||||
requestAnimationFrame(() => {
|
||||
|
||||
243
js/player.js
243
js/player.js
@@ -563,7 +563,6 @@ const m = {
|
||||
if (tech.isHarmMACHO) dmg *= 0.4
|
||||
if (tech.isImmortal) dmg *= 0.7
|
||||
if (tech.energyRegen === 0) dmg *= 0.34
|
||||
// if (tech.healthDrain) dmg *= 1 + 3.33 * tech.healthDrain //tech.healthDrain = 0.03 at one stack //cause more damage
|
||||
if (m.fieldMode === 0 || m.fieldMode === 3) dmg *= 0.973 ** m.coupling
|
||||
if (tech.isLowHealthDefense) dmg *= 1 - Math.max(0, 1 - m.health) * 0.8
|
||||
if (tech.isHarmReduceNoKill && m.lastKillCycle + 300 < m.cycle) dmg *= 0.26
|
||||
@@ -577,11 +576,7 @@ const m = {
|
||||
if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.27
|
||||
if (tech.isTurret && m.crouch) dmg *= 0.34;
|
||||
if (tech.isFirstDer && b.inventory[0] === b.activeGun) dmg *= 0.85 ** b.inventory.length
|
||||
if (tech.isEnergyHealth) {
|
||||
return Math.pow(dmg, 0.33) //defense has less effect
|
||||
} else {
|
||||
return dmg
|
||||
}
|
||||
return tech.isEnergyHealth ? Math.pow(dmg, 0.5) : dmg //defense has less effect
|
||||
},
|
||||
rewind(steps) { // m.rewind(Math.floor(Math.min(599, 137 * m.energy)))
|
||||
if (tech.isRewindGrenade) {
|
||||
@@ -1071,6 +1066,111 @@ const m = {
|
||||
ctx.restore();
|
||||
}
|
||||
},
|
||||
polar() {
|
||||
m.isAltSkin = true
|
||||
m.color = {
|
||||
hue: 0,
|
||||
sat: 0,
|
||||
light: 100,
|
||||
}
|
||||
// m.setFillColors();
|
||||
m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)`
|
||||
m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 35}%)`
|
||||
let grd = ctx.createLinearGradient(-30, 0, 30, 0);
|
||||
grd.addColorStop(0, m.fillColorDark);
|
||||
grd.addColorStop(0.7, m.fillColor);
|
||||
// grd.addColorStop(1, m.fillColor);
|
||||
m.bodyGradient = grd
|
||||
|
||||
m.draw = function () {
|
||||
ctx.fillStyle = m.fillColor;
|
||||
m.walk_cycle += m.flipLegs * m.Vx;
|
||||
ctx.save();
|
||||
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
|
||||
ctx.translate(m.pos.x, m.pos.y);
|
||||
m.calcLeg(Math.PI, -3);
|
||||
|
||||
|
||||
const diff = (m.lastKillCycle - m.cycle + 240) / 240
|
||||
const color = diff < 0 ? "#fff" : "#aaa"
|
||||
const hue = 220 + 20 * Math.sin(0.01 * m.cycle)
|
||||
const colorInverse = diff < 0 ? `hsl(${hue}, 80%, 40%)` : "#fff"
|
||||
// const colorInverseFade = diff < 0 ? "#ccc" : "#fff"
|
||||
m.drawLeg(color, colorInverse);
|
||||
m.calcLeg(0, 0);
|
||||
m.drawLeg(color, colorInverse);
|
||||
|
||||
ctx.rotate(m.angle);
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = color
|
||||
ctx.fill();
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(15, 0)
|
||||
ctx.lineTo(28, 0)
|
||||
// ctx.arc(15, 0, 4, 0, 2 * Math.PI);
|
||||
ctx.strokeStyle = colorInverse;
|
||||
ctx.lineWidth = 4;
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
|
||||
|
||||
// const scale = diff>0.3
|
||||
// console.log(diff.toFixed(3), scale.toFixed(3))
|
||||
ctx.beginPath();
|
||||
ctx.ellipse(m.pos.x, m.pos.y, 24, 18, 3.14 * Math.random(), 0, 2 * Math.PI)
|
||||
// `rgba(0,0,${100 + 30 * Math.sin(0.1 * m.cycle)},0.8)`
|
||||
ctx.fillStyle = diff < 0 ? `hsl(${hue}, 80%, 40%)` : `rgba(255,255,255,${Math.min(Math.max(0, diff + 0.3), 1)})`
|
||||
// ctx.fillStyle = colorInverse
|
||||
// ctx.fillStyle = `rgba(0,0,0,${scale})`
|
||||
ctx.fill();
|
||||
|
||||
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
|
||||
powerUps.boost.draw()
|
||||
}
|
||||
m.drawLeg = function (stroke, circles) {
|
||||
// if (simulation.mouseInGame.x > m.pos.x) {
|
||||
if (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2) {
|
||||
m.flipLegs = 1;
|
||||
} else {
|
||||
m.flipLegs = -1;
|
||||
}
|
||||
ctx.save();
|
||||
ctx.scale(m.flipLegs, 1); //leg lines
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(m.hip.x, m.hip.y);
|
||||
ctx.lineTo(m.knee.x, m.knee.y);
|
||||
ctx.lineTo(m.foot.x, m.foot.y);
|
||||
ctx.strokeStyle = stroke;
|
||||
ctx.lineWidth = 6;
|
||||
ctx.stroke();
|
||||
|
||||
//toe lines
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(m.foot.x, m.foot.y);
|
||||
ctx.lineTo(m.foot.x - 15, m.foot.y + 5);
|
||||
ctx.moveTo(m.foot.x, m.foot.y);
|
||||
ctx.lineTo(m.foot.x + 15, m.foot.y + 5);
|
||||
ctx.lineWidth = 3;
|
||||
ctx.stroke();
|
||||
|
||||
//hip joint
|
||||
ctx.beginPath();
|
||||
ctx.arc(m.hip.x, m.hip.y, 11, 0, 2 * Math.PI);
|
||||
//knee joint
|
||||
ctx.moveTo(m.knee.x + 5, m.knee.y);
|
||||
ctx.arc(m.knee.x, m.knee.y, 5, 0, 2 * Math.PI);
|
||||
//foot joint
|
||||
ctx.moveTo(m.foot.x + 5, m.foot.y);
|
||||
ctx.arc(m.foot.x, m.foot.y, 5, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = circles;
|
||||
ctx.fill();
|
||||
// ctx.lineWidth = 2;
|
||||
// ctx.stroke();
|
||||
ctx.restore();
|
||||
}
|
||||
},
|
||||
strokeGap() {
|
||||
m.isAltSkin = true
|
||||
m.yOffWhen.stand = 52
|
||||
@@ -1579,9 +1679,9 @@ const m = {
|
||||
// m.setFillColors();
|
||||
m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)`
|
||||
m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 35}%)`
|
||||
let grd = ctx.createLinearGradient(-30, 0, 30, 0);
|
||||
let grd = ctx.createLinearGradient(-20, 0, 15, 0);
|
||||
grd.addColorStop(0, m.fillColorDark);
|
||||
grd.addColorStop(0.7, m.fillColor);
|
||||
grd.addColorStop(1, m.fillColor);
|
||||
// grd.addColorStop(1, m.fillColor);
|
||||
m.bodyGradient = grd
|
||||
|
||||
@@ -1595,10 +1695,11 @@ const m = {
|
||||
m.drawLeg("#eee");
|
||||
m.calcLeg(0, 0);
|
||||
m.drawLeg("#fff");
|
||||
ctx.rotate(0.017 * simulation.cycle);
|
||||
|
||||
ctx.rotate(0.024 * simulation.cycle);
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = m.bodyGradient
|
||||
ctx.fillStyle = m.energy > 0.85 * Math.min(1, m.maxEnergy) ? m.bodyGradient : "#fff"
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
|
||||
@@ -3654,74 +3755,75 @@ const m = {
|
||||
m.drawHold(m.holdingTarget);
|
||||
m.holding();
|
||||
m.throwBlock();
|
||||
} else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
|
||||
} else if (input.field) { //not hold but field button is pressed
|
||||
if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen
|
||||
m.grabPowerUp();
|
||||
m.lookForPickUp();
|
||||
if (m.fieldCDcycle < m.cycle) {
|
||||
//field is active
|
||||
if (!m.plasmaBall.isAttached) { //return ball to player
|
||||
if (m.plasmaBall.isOn) {
|
||||
m.plasmaBall.isPopping = true
|
||||
} else {
|
||||
m.plasmaBall.isAttached = true
|
||||
m.plasmaBall.isOn = true
|
||||
m.plasmaBall.isPopping = false
|
||||
m.plasmaBall.alpha = 0.7
|
||||
m.plasmaBall.setPositionToNose()
|
||||
// m.plasmaBall.reset()
|
||||
|
||||
//field is active
|
||||
if (!m.plasmaBall.isAttached) { //return ball to player
|
||||
if (m.plasmaBall.isOn) {
|
||||
m.plasmaBall.isPopping = true
|
||||
} else {
|
||||
m.plasmaBall.isAttached = true
|
||||
m.plasmaBall.isOn = true
|
||||
m.plasmaBall.isPopping = false
|
||||
m.plasmaBall.alpha = 0.7
|
||||
}
|
||||
// const scale = 0.7
|
||||
// Matter.Body.scale(m.plasmaBall, scale, scale); //shrink fast
|
||||
// if (m.plasmaBall.circleRadius < m.plasmaBall.radiusLimit) {
|
||||
// m.plasmaBall.isAttached = true
|
||||
// m.plasmaBall.isOn = true
|
||||
// m.plasmaBall.setPositionToNose()
|
||||
// }
|
||||
} else if (m.energy > m.plasmaBall.drain) { //charge up when attached
|
||||
if (tech.isCapacitor) {
|
||||
m.energy -= m.plasmaBall.drain * 2;
|
||||
const scale = 1 + 48 * Math.pow(Math.max(1, m.plasmaBall.circleRadius), -1.8)
|
||||
Matter.Body.scale(m.plasmaBall, scale, scale); //grow
|
||||
} else {
|
||||
m.energy -= m.plasmaBall.drain;
|
||||
const scale = 1 + 16 * Math.pow(Math.max(1, m.plasmaBall.circleRadius), -1.8)
|
||||
Matter.Body.scale(m.plasmaBall, scale, scale); //grow
|
||||
}
|
||||
if (m.energy > m.maxEnergy) {
|
||||
m.energy -= m.plasmaBall.drain * 2;
|
||||
const scale = 1 + 16 * Math.pow(Math.max(1, m.plasmaBall.circleRadius), -1.8)
|
||||
Matter.Body.scale(m.plasmaBall, scale, scale); //grow
|
||||
}
|
||||
m.plasmaBall.setPositionToNose()
|
||||
// m.plasmaBall.reset()
|
||||
|
||||
}
|
||||
// const scale = 0.7
|
||||
// Matter.Body.scale(m.plasmaBall, scale, scale); //shrink fast
|
||||
// if (m.plasmaBall.circleRadius < m.plasmaBall.radiusLimit) {
|
||||
// m.plasmaBall.isAttached = true
|
||||
// m.plasmaBall.isOn = true
|
||||
// m.plasmaBall.setPositionToNose()
|
||||
// }
|
||||
} else if (m.energy > m.plasmaBall.drain) { //charge up when attached
|
||||
if (tech.isCapacitor) {
|
||||
m.energy -= m.plasmaBall.drain * 2;
|
||||
const scale = 1 + 48 * Math.pow(Math.max(1, m.plasmaBall.circleRadius), -1.8)
|
||||
Matter.Body.scale(m.plasmaBall, scale, scale); //grow
|
||||
//add friction for player when holding ball, more friction in vertical
|
||||
// const floatScale = Math.sqrt(m.plasmaBall.circleRadius)
|
||||
// const friction = 0.0002 * floatScale
|
||||
// const slowY = (player.velocity.y > 0) ? Math.max(0.8, 1 - friction * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - friction * Math.abs(player.velocity.y)) //down : up
|
||||
// Matter.Body.setVelocity(player, {
|
||||
// x: Math.max(0.95, 1 - friction * Math.abs(player.velocity.x)) * player.velocity.x,
|
||||
// y: slowY * player.velocity.y
|
||||
// });
|
||||
|
||||
// if (player.velocity.y > 7) player.force.y -= 0.95 * player.mass * simulation.g //less gravity when falling fast
|
||||
// player.force.y -= Math.min(0.95, 0.05 * floatScale) * player.mass * simulation.g; //undo some gravity on up or down
|
||||
|
||||
//float
|
||||
const slowY = (player.velocity.y > 0) ? Math.max(0.8, 1 - 0.002 * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - 0.001 * Math.abs(player.velocity.y)) //down : up
|
||||
Matter.Body.setVelocity(player, {
|
||||
x: Math.max(0.95, 1 - 0.003 * Math.abs(player.velocity.x)) * player.velocity.x,
|
||||
y: slowY * player.velocity.y
|
||||
});
|
||||
if (player.velocity.y > 5) {
|
||||
player.force.y -= 0.9 * player.mass * simulation.g //less gravity when falling fast
|
||||
} else {
|
||||
player.force.y -= 0.5 * player.mass * simulation.g;
|
||||
}
|
||||
} else {
|
||||
m.energy -= m.plasmaBall.drain;
|
||||
const scale = 1 + 16 * Math.pow(Math.max(1, m.plasmaBall.circleRadius), -1.8)
|
||||
Matter.Body.scale(m.plasmaBall, scale, scale); //grow
|
||||
m.fieldCDcycle = m.cycle + 90;
|
||||
m.plasmaBall.fire()
|
||||
}
|
||||
if (m.energy > m.maxEnergy) {
|
||||
m.energy -= m.plasmaBall.drain * 2;
|
||||
const scale = 1 + 16 * Math.pow(Math.max(1, m.plasmaBall.circleRadius), -1.8)
|
||||
Matter.Body.scale(m.plasmaBall, scale, scale); //grow
|
||||
}
|
||||
m.plasmaBall.setPositionToNose()
|
||||
|
||||
//add friction for player when holding ball, more friction in vertical
|
||||
// const floatScale = Math.sqrt(m.plasmaBall.circleRadius)
|
||||
// const friction = 0.0002 * floatScale
|
||||
// const slowY = (player.velocity.y > 0) ? Math.max(0.8, 1 - friction * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - friction * Math.abs(player.velocity.y)) //down : up
|
||||
// Matter.Body.setVelocity(player, {
|
||||
// x: Math.max(0.95, 1 - friction * Math.abs(player.velocity.x)) * player.velocity.x,
|
||||
// y: slowY * player.velocity.y
|
||||
// });
|
||||
|
||||
// if (player.velocity.y > 7) player.force.y -= 0.95 * player.mass * simulation.g //less gravity when falling fast
|
||||
// player.force.y -= Math.min(0.95, 0.05 * floatScale) * player.mass * simulation.g; //undo some gravity on up or down
|
||||
|
||||
//float
|
||||
const slowY = (player.velocity.y > 0) ? Math.max(0.8, 1 - 0.002 * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - 0.001 * Math.abs(player.velocity.y)) //down : up
|
||||
Matter.Body.setVelocity(player, {
|
||||
x: Math.max(0.95, 1 - 0.003 * Math.abs(player.velocity.x)) * player.velocity.x,
|
||||
y: slowY * player.velocity.y
|
||||
});
|
||||
if (player.velocity.y > 5) {
|
||||
player.force.y -= 0.9 * player.mass * simulation.g //less gravity when falling fast
|
||||
} else {
|
||||
player.force.y -= 0.5 * player.mass * simulation.g;
|
||||
}
|
||||
} else {
|
||||
m.fieldCDcycle = m.cycle + 90;
|
||||
m.plasmaBall.fire()
|
||||
}
|
||||
} else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
|
||||
m.pickUp();
|
||||
@@ -4204,6 +4306,7 @@ const m = {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m.isCloak) {
|
||||
m.fieldRange = m.fieldRange * 0.85 + 130
|
||||
m.fieldDrawRadius = m.fieldRange * 1.1 //* 0.88 //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy));
|
||||
|
||||
@@ -687,7 +687,7 @@ const powerUps = {
|
||||
return `<div></div>`
|
||||
} else if (tech.isCancelTech) {
|
||||
return `<div class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 115px;">randomize</div>`
|
||||
} else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted) { //don't show cancel if on initial level and haven't done tutorial
|
||||
} else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted && b.inventory.length === 0) { //don't show cancel if on initial level and haven't done tutorial
|
||||
return `<div class='cancel-card' style="visibility: hidden;"></div>`
|
||||
} else {
|
||||
return `<div class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 85px;">cancel</div>`
|
||||
@@ -745,7 +745,7 @@ const powerUps = {
|
||||
text += `<span class='cancel-card' style="width: 95px;float: right;background-color: #aaa;color:#888;">cancel</span>`
|
||||
} else if (tech.isCancelTech) {
|
||||
text += `<span class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 115px;float: right;font-size:0.9em;padding-top:5px">randomize</span>`
|
||||
} else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted) {
|
||||
} else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted && b.inventory.length === 0) {
|
||||
text += `<span class='cancel-card' style="visibility: hidden;">cancel</span>` //don't show cancel if on initial level and haven't done tutorial
|
||||
} else {
|
||||
text += `<span class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 95px;float: right;">cancel</span>`
|
||||
@@ -1539,7 +1539,7 @@ const powerUps = {
|
||||
tech.removeTech(index)
|
||||
} else {
|
||||
powerUps.ejectTech(index)
|
||||
m.damage(0.06)
|
||||
m.damage(0.04)
|
||||
}
|
||||
document.getElementById(`${index}-pause-tech`).style.textDecoration = "line-through"
|
||||
document.getElementById(`${index}-pause-tech`).style.animation = ""
|
||||
|
||||
93
js/tech.js
93
js/tech.js
@@ -231,6 +231,8 @@ const tech = {
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (tech.isDamageCooldown) dmg *= m.lastKillCycle + 240 > m.cycle ? 0.5 : 4
|
||||
if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 1.93
|
||||
if (tech.isDivisor && b.activeGun !== undefined && b.activeGun !== null && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.77
|
||||
if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.85 : 2
|
||||
if (tech.isDilate) dmg *= 1.5 + 0.6 * Math.sin(m.cycle * 0.0075)
|
||||
@@ -254,7 +256,6 @@ const tech = {
|
||||
if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.007
|
||||
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2.11
|
||||
if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.88, player.speed * 0.0193)
|
||||
if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 1.93
|
||||
if (tech.isAxion && tech.isHarmMACHO) dmg *= 2 - m.defense()
|
||||
if (tech.isHarmDamage && m.lastHarmCycle + 480 > m.cycle) dmg *= 3;
|
||||
if (tech.lastHitDamage && m.lastHit) dmg *= 1 + tech.lastHitDamage * m.lastHit * (2 - m.defense()) // if (!simulation.paused) m.lastHit = 0
|
||||
@@ -365,6 +366,30 @@ const tech = {
|
||||
if (this.count) m.resetSkin();
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "depolarization",
|
||||
descriptionFunction() {
|
||||
// return `<strong>+300%</strong> <strong class='color-d'>damage</strong> or <strong>-50%</strong> <strong class='color-d'>damage</strong><br>if a mob has <strong>died</strong> in the last <strong>5 seconds</strong>`
|
||||
return `<span style = 'font-size:88%;'><strong>+300%</strong> <strong class='color-d'>damage</strong> if <strong>no</strong> mobs <strong>died</strong> in the last <strong>4 seconds</strong><br><strong>-50%</strong> <strong class='color-d'>damage</strong> if a mob <strong>died</strong> in the last <strong>4 seconds</strong></span>`
|
||||
},
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
frequencyDefault: 1,
|
||||
isSkin: true,
|
||||
allowed() {
|
||||
return !m.isAltSkin
|
||||
},
|
||||
requires: "not skinned",
|
||||
effect() {
|
||||
m.skin.polar();
|
||||
tech.isDamageCooldown = true;
|
||||
},
|
||||
remove() {
|
||||
tech.isDamageCooldown = false;
|
||||
if (this.count) m.resetSkin();
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Higgs mechanism",
|
||||
description: "<strong>+77%</strong> <strong><em>fire rate</em></strong><br>while <strong>firing</strong> your <strong>position</strong> is fixed",
|
||||
@@ -462,7 +487,7 @@ const tech = {
|
||||
{
|
||||
name: "mass-energy equivalence",
|
||||
// description: "<strong class='color-f'>energy</strong> protects you instead of <strong class='color-h'>health</strong><br>√ of <strong class='color-defense'>defense</strong> <strong>reduction</strong> reduces max <strong class='color-f'>energy</strong>",
|
||||
description: `<strong class='color-f'>energy</strong> protects you instead of <strong class='color-h'>health</strong><br><strong class='color-defense'>defensive</strong> upgrades <strong>reduced</strong> by <strong>~66%</strong>`,
|
||||
description: `<strong class='color-f'>energy</strong> protects you instead of <strong class='color-h'>health</strong><br><strong class='color-defense'>defensive</strong> upgrades <strong>reduced</strong> by about <strong>50%</strong>`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -535,7 +560,7 @@ const tech = {
|
||||
// description: "<strong>charge</strong>, <strong>parity</strong>, and <strong>time</strong> invert to undo <strong class='color-defense'>defense</strong><br><strong class='color-rewind'>rewind</strong> <strong>(1.5—5)</strong> seconds for <strong>(66—220)</strong> <strong class='color-f'>energy</strong>",
|
||||
// description: "after losing <strong class='color-h'>health</strong>, if you have <strong>full</strong> <strong class='color-f'>energy</strong><br><strong>rewind</strong> time for <strong>44</strong> <strong class='color-f'>energy</strong> per second",
|
||||
descriptionFunction() {
|
||||
return `after losing <strong class='color-h'>health</strong>, if you have <strong>${(100 * Math.min(100, m.maxEnergy)).toFixed(0)}</strong> <strong class='color-f'>energy</strong><br><strong>rewind</strong> time for <strong>20</strong> <strong class='color-f'>energy</strong> per second`
|
||||
return `after losing <strong class='color-h'>health</strong>, if you have above <strong>${(85 * Math.min(100, m.maxEnergy)).toFixed(0)}</strong> <strong class='color-f'>energy</strong><br><strong>rewind</strong> time for <strong>20</strong> <strong class='color-f'>energy</strong> per second`
|
||||
},
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -1346,6 +1371,27 @@ const tech = {
|
||||
tech.isShieldAmmo = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "enthalpy",
|
||||
descriptionFunction() {
|
||||
return `after mobs <strong>die</strong><br>they have a <strong>+8%</strong> chance to spawn ${powerUps.orb.heal(1)}`
|
||||
},
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
frequency: 1000,
|
||||
frequencyDefault: 1000,
|
||||
isHealTech: true,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
effect() {
|
||||
tech.healSpawn += 0.08;
|
||||
},
|
||||
remove() {
|
||||
tech.healSpawn = 0;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "yield stress",
|
||||
description: "<strong>+55%</strong> <strong class='color-d'>damage</strong><br>to <strong>mobs</strong> at maximum <strong>health</strong>",
|
||||
@@ -3233,27 +3279,6 @@ const tech = {
|
||||
tech.isHealLowHealth = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "enthalpy",
|
||||
descriptionFunction() {
|
||||
return `doing <strong class='color-d'>damage</strong> has a small chance to spawn ${powerUps.orb.heal(1)}` //<br><strong>–10%</strong> <strong class='color-defense'>defense</strong>
|
||||
},
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
frequencyDefault: 1,
|
||||
isHealTech: true,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
effect() {
|
||||
tech.healthDrain += 0.023;
|
||||
},
|
||||
remove() {
|
||||
tech.healthDrain = 0;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "maintenance",
|
||||
descriptionFunction() {
|
||||
@@ -3532,9 +3557,9 @@ const tech = {
|
||||
{
|
||||
name: "mass production",
|
||||
descriptionFunction() {
|
||||
return `<strong class='color-m'>tech</strong> always have <strong>+3</strong> choices to spawn<br>options for ${powerUps.orb.ammo(1)} or ${powerUps.orb.heal(1)} or ${powerUps.orb.research(1)}`
|
||||
return `spawn ${powerUps.orb.ammo(3)}${powerUps.orb.heal(3)} ${powerUps.orb.research(2)}<br><strong class='color-m'>tech</strong> have extra choices to spawn ${powerUps.orb.ammo(1)}, ${powerUps.orb.heal(1)}, or ${powerUps.orb.research(1)}`
|
||||
},
|
||||
// description: `<strong class='color-m'>tech</strong> always have <strong>+3</strong> choices to spawn<br>${powerUps.orb.ammo(8)} ${powerUps.orb.heal(8)} or ${powerUps.orb.research(5)}`,
|
||||
// description: `< strong class='color-m' > tech</strong > always have < strong > +3</strong > choices to spawn < br > ${ powerUps.orb.ammo(8) } ${ powerUps.orb.heal(8) } & nbsp;& nbsp; or ${ powerUps.orb.research(5) } `,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -3543,6 +3568,9 @@ const tech = {
|
||||
requires: "",
|
||||
effect() {
|
||||
tech.isMassProduction = true
|
||||
powerUps.spawnDelay("ammo", 4);
|
||||
powerUps.spawnDelay("heal", 4);
|
||||
powerUps.spawnDelay("research", 2);
|
||||
},
|
||||
remove() {
|
||||
tech.isMassProduction = false
|
||||
@@ -3551,7 +3579,7 @@ const tech = {
|
||||
{
|
||||
name: "research",
|
||||
descriptionFunction() {
|
||||
return `spawn ${this.value > 36 ? this.value + powerUps.orb.research(1) : powerUps.orb.research(this.value)}<br>next time this effect is improved by ${powerUps.orb.research(5)}`
|
||||
return `spawn ${this.value > 36 ? this.value + powerUps.orb.research(1) : powerUps.orb.research(this.value)} <br>next time this effect is improved by ${powerUps.orb.research(5)}`
|
||||
},
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
@@ -3610,7 +3638,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "pseudoscience",
|
||||
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>1-3%</strong> <strong class='color-junk'>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>1-3%</strong> <strong class='color-junk'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -3940,7 +3968,7 @@ const tech = {
|
||||
// description: `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <strong>ejects</strong> it<br>with a <strong>20%</strong> chance to remove without <strong>ejecting</strong>`,
|
||||
// description: `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <strong>ejects</strong> it<br>and a <strong>20%</strong> chance to remove without <strong>ejecting</strong>`,
|
||||
descriptionFunction() {
|
||||
return `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <strong>ejects</strong> it<br><strong>–6</strong> ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"} each time and a <strong>3%</strong> chance to fail`
|
||||
return `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <strong>ejects</strong> it<br><strong>–4</strong> ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"} each time and a <strong>3%</strong> chance to fail`
|
||||
},
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -5246,7 +5274,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "Zectron",
|
||||
description: `<strong>+75%</strong> <strong>super ball</strong> density and <strong class='color-d'>damage</strong>, but<br>after colliding with <strong>super balls</strong> <strong>-25%</strong> <strong class='color-f'>energy</strong>`,
|
||||
description: `<strong>+90%</strong> <strong>super ball</strong> density and <strong class='color-d'>damage</strong>, but<br>after colliding with <strong>super balls</strong> <strong>-25%</strong> <strong class='color-f'>energy</strong>`,
|
||||
isGunTech: true,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -11756,7 +11784,7 @@ const tech = {
|
||||
fireRate: null,
|
||||
bulletSize: null,
|
||||
energySiphon: null,
|
||||
healthDrain: null,
|
||||
healSpawn: null,
|
||||
crouchAmmoCount: null,
|
||||
bulletsLastLonger: null,
|
||||
isImmortal: null,
|
||||
@@ -12107,5 +12135,6 @@ const tech = {
|
||||
isHarpoonFullHealth: null,
|
||||
isMobFullHealth: null,
|
||||
isMobFullHealthCloak: null,
|
||||
isMobLowHealth: null
|
||||
isMobLowHealth: null,
|
||||
isDamageCooldown: null,
|
||||
}
|
||||
Reference in New Issue
Block a user