ceramic needles

iridium-192: now has a wider explosions range and no knock back
nail gun: irradiated nails do about 33% more damage over 2 seconds
nail gun rivet fire rate is 10% slower
nail gun: needles do 10% less damage, but they fire 10% faster
needle tech: ceramic needles - needles pierce shields
This commit is contained in:
landgreen
2021-01-25 04:01:55 -08:00
parent 21affab7b1
commit 829cf134ef
4 changed files with 203 additions and 126 deletions

View File

@@ -314,16 +314,41 @@ const b = {
dmg *= 1.6
}
if (tech.isExplodeRadio) {
if (tech.isExplodeRadio) { //radiation explosion
const alertRange = 100 + radius * 2; //alert range
simulation.drawList.push({ //add dmg to draw queue
x: where.x,
y: where.y,
radius: radius,
color: "rgba(25,139,170,0.45)",
time: simulation.drawTime
radius: alertRange,
color: "rgba(25,139,170,0.25)",
time: simulation.drawTime * 2
});
} else {
//player damage and knock back
sub = Vector.sub(where, player.position);
dist = Vector.magnitude(sub);
if (dist < alertRange) {
m.energy -= 0.23 * (tech.isImmuneExplosion ? Math.min(1, Math.max(1 - m.energy * 0.7, 0)) : 1)
if (m.energy < 0) m.energy = 0
}
//mob damage and knock back with alert
let damageScale = 1.5; // reduce dmg for each new target to limit total AOE damage
for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].alive && !mob[i].isShielded) {
sub = Vector.sub(where, mob[i].position);
dist = Vector.magnitude(sub) - mob[i].radius;
if (dist < alertRange) {
if (mob[i].shield) dmg *= 2.5 //balancing explosion dmg to shields
if (Matter.Query.ray(map, mob[i].position, where).length > 0) dmg *= 0.5 //reduce damage if a wall is in the way
mobs.statusDoT(mob[i], dmg * damageScale * 0.2, 240) //apply radiation damage status effect on direct hits
mob[i].locatePlayer();
damageScale *= 0.87 //reduced damage for each additional explosion target
}
}
}
} else { //normal explosions
simulation.drawList.push({ //add dmg to draw queue
x: where.x,
y: where.y,
@@ -331,94 +356,87 @@ const b = {
color: "rgba(255,25,0,0.6)",
time: simulation.drawTime
});
}
const alertRange = 100 + radius * 2; //alert range
simulation.drawList.push({ //add alert to draw queue
x: where.x,
y: where.y,
radius: alertRange,
color: "rgba(100,20,0,0.03)",
time: simulation.drawTime
});
const alertRange = 100 + radius * 2; //alert range
simulation.drawList.push({ //add alert to draw queue
x: where.x,
y: where.y,
radius: alertRange,
color: "rgba(100,20,0,0.03)",
time: simulation.drawTime
});
//player damage and knock back
sub = Vector.sub(where, player.position);
dist = Vector.magnitude(sub);
if (dist < radius) {
if (tech.isImmuneExplosion) {
const mitigate = Math.min(1, Math.max(1 - m.energy * 0.7, 0))
m.damage(mitigate * radius * (tech.isExplosionHarm ? 0.0004 : 0.0001));
} else {
m.damage(radius * (tech.isExplosionHarm ? 0.0004 : 0.0001));
}
knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass * 0.013);
player.force.x += knock.x;
player.force.y += knock.y;
} else if (dist < alertRange) {
knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass * 0.005);
player.force.x += knock.x;
player.force.y += knock.y;
}
//body knock backs
for (let i = 0, len = body.length; i < len; ++i) {
sub = Vector.sub(where, body[i].position);
//player damage and knock back
sub = Vector.sub(where, player.position);
dist = Vector.magnitude(sub);
if (dist < radius) {
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.022);
body[i].force.x += knock.x;
body[i].force.y += knock.y;
} else if (dist < alertRange) {
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.011);
body[i].force.x += knock.x;
body[i].force.y += knock.y;
}
}
//power up knock backs
for (let i = 0, len = powerUp.length; i < len; ++i) {
sub = Vector.sub(where, powerUp[i].position);
dist = Vector.magnitude(sub);
if (dist < radius) {
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * powerUp[i].mass) * 0.013);
powerUp[i].force.x += knock.x;
powerUp[i].force.y += knock.y;
if (tech.isImmuneExplosion) {
const mitigate = Math.min(1, Math.max(1 - m.energy * 0.7, 0))
m.damage(mitigate * radius * (tech.isExplosionHarm ? 0.0004 : 0.0001));
} else {
m.damage(radius * (tech.isExplosionHarm ? 0.0004 : 0.0001));
}
knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass * 0.013);
player.force.x += knock.x;
player.force.y += knock.y;
} else if (dist < alertRange) {
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * powerUp[i].mass) * 0.007);
powerUp[i].force.x += knock.x;
powerUp[i].force.y += knock.y;
knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass * 0.005);
player.force.x += knock.x;
player.force.y += knock.y;
}
}
//mob damage and knock back with alert
let damageScale = 1.5; // reduce dmg for each new target to limit total AOE damage
for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].alive && !mob[i].isShielded) {
sub = Vector.sub(where, mob[i].position);
dist = Vector.magnitude(sub) - mob[i].radius;
//body knock backs
for (let i = 0, len = body.length; i < len; ++i) {
sub = Vector.sub(where, body[i].position);
dist = Vector.magnitude(sub);
if (dist < radius) {
if (mob[i].shield) dmg *= 2.5 //balancing explosion dmg to shields
if (Matter.Query.ray(map, mob[i].position, where).length > 0) dmg *= 0.5 //reduce damage if a wall is in the way
if (tech.isExplodeRadio) {
mobs.statusDoT(mob[i], dmg * damageScale * 0.25, 240) //apply radiation damage status effect on direct hits
} else {
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.022);
body[i].force.x += knock.x;
body[i].force.y += knock.y;
} else if (dist < alertRange) {
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.011);
body[i].force.x += knock.x;
body[i].force.y += knock.y;
}
}
//power up knock backs
for (let i = 0, len = powerUp.length; i < len; ++i) {
sub = Vector.sub(where, powerUp[i].position);
dist = Vector.magnitude(sub);
if (dist < radius) {
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * powerUp[i].mass) * 0.013);
powerUp[i].force.x += knock.x;
powerUp[i].force.y += knock.y;
} else if (dist < alertRange) {
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * powerUp[i].mass) * 0.007);
powerUp[i].force.x += knock.x;
powerUp[i].force.y += knock.y;
}
}
//mob damage and knock back with alert
let damageScale = 1.5; // reduce dmg for each new target to limit total AOE damage
for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].alive && !mob[i].isShielded) {
sub = Vector.sub(where, mob[i].position);
dist = Vector.magnitude(sub) - mob[i].radius;
if (dist < radius) {
if (mob[i].shield) dmg *= 2.5 //balancing explosion dmg to shields
if (Matter.Query.ray(map, mob[i].position, where).length > 0) dmg *= 0.5 //reduce damage if a wall is in the way
mob[i].damage(dmg * damageScale * b.dmgScale);
mob[i].locatePlayer();
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) * 0.01);
mob[i].force.x += knock.x;
mob[i].force.y += knock.y;
radius *= 0.95 //reduced range for each additional explosion target
damageScale *= 0.87 //reduced damage for each additional explosion target
} else if (!mob[i].seePlayer.recall && dist < alertRange) {
mob[i].locatePlayer();
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) * 0.006);
mob[i].force.x += knock.x;
mob[i].force.y += knock.y;
}
mob[i].locatePlayer();
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) * 0.01);
mob[i].force.x += knock.x;
mob[i].force.y += knock.y;
radius *= 0.95 //reduced range for each additional explosion target
damageScale *= 0.87 //reduced damage for each additional explosion target
} else if (!mob[i].seePlayer.recall && dist < alertRange) {
mob[i].locatePlayer();
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) * 0.006);
mob[i].force.x += knock.x;
mob[i].force.y += knock.y;
}
}
}
@@ -2192,7 +2210,7 @@ const b = {
bullet[me].endCycle = simulation.cycle + 60 + 18 * Math.random();
bullet[me].dmg = tech.isNailRadiation ? 0 : dmg
bullet[me].beforeDmg = function(who) { //beforeDmg is rewritten with ice crystal tech
if (tech.isNailRadiation) mobs.statusDoT(who, dmg * (tech.isFastRadiation ? 2 : 0.5), tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
if (tech.isNailRadiation) mobs.statusDoT(who, dmg * (tech.isFastRadiation ? 2.6 : 0.65), tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.97) {
b.explosion(this.position, 150 + 30 * Math.random()); //makes bullet do explosive damage at end
}
@@ -2851,8 +2869,8 @@ const b = {
name: "nail gun",
description: "use compressed air to fire a stream of <strong>nails</strong><br><strong>delay</strong> after firing <strong>decreases</strong> as you shoot",
ammo: 0,
ammoPack: 50,
defaultAmmoPack: 50,
ammoPack: 45,
defaultAmmoPack: 45,
recordedAmmo: 0,
have: false,
nextFireCycle: 0, //use to remember how longs its been since last fire, used to reset count
@@ -2882,19 +2900,19 @@ const b = {
this.baseFire(m.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (m.crouch ? 1.35 : 3.2) / CD)
},
fireNeedles() {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 40 : 30) * b.fireCD); // cool down
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 35 : 20) * b.fireCD); // cool down
function makeFlechette(angle = m.angle) {
function makeNeedle(angle = m.angle) {
const me = bullet.length;
bullet[me] = Bodies.rectangle(m.pos.x + 40 * Math.cos(m.angle), m.pos.y + 40 * Math.sin(m.angle), 50, 1, b.fireAttributes(angle));
bullet[me].collisionFilter.mask = cat.mobShield | cat.body
bullet[me].collisionFilter.mask = tech.isNeedleShieldPierce ? cat.body : cat.body | cat.mobShield
Matter.Body.setDensity(bullet[me], 0.00001); //0.001 is normal
bullet[me].endCycle = simulation.cycle + 180;
bullet[me].immuneList = []
bullet[me].do = function() {
const whom = Matter.Query.collides(this, mob)
if (whom.length && this.speed > 20) { //if touching a mob
who = whom[0].bodyA
who = whom[whom.length - 1].bodyA
if (who && who.mob) {
let immune = false
for (let i = 0; i < this.immuneList.length; i++) {
@@ -2905,16 +2923,16 @@ const b = {
}
if (!immune) {
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.97) {
b.explosion(this.position, 200 + 30 * Math.random()); //makes bullet do explosive damage at end
b.explosion(this.position, 220 + 30 * Math.random()); //makes bullet do explosive damage at end
}
this.immuneList.push(who.id)
who.foundPlayer();
if (tech.isNailRadiation) {
mobs.statusDoT(who, tech.isFastRadiation ? 10 : 2.5, tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
mobs.statusDoT(who, tech.isFastRadiation ? 8 : 2, tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
} else {
let dmg = b.dmgScale * 5
let dmg = b.dmgScale * 3
if (tech.isCrit && who.isStunned) dmg *= 4
who.damage(dmg);
who.damage(dmg, tech.isNeedleShieldPierce);
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
@@ -2923,11 +2941,6 @@ const b = {
time: simulation.drawTime
});
}
// if (tech.isFastRadiation) {
// mobs.statusDoT(who, 3.78, 30)
// } else {
// mobs.statusDoT(who, 0.63, tech.isSlowRadiation ? 360 : 180)
// }
}
}
} else if (Matter.Query.collides(this, map).length) { //stick in walls
@@ -2950,13 +2963,13 @@ const b = {
Matter.Body.setDensity(bullet[me], 0.00001);
World.add(engine.world, bullet[me]); //add bullet to world
}
const spread = (m.crouch ? 0.01 : 0.045)
makeFlechette(m.angle + spread)
makeFlechette()
makeFlechette(m.angle - spread)
const spread = (m.crouch ? 0.013 : 0.06)
makeNeedle(m.angle + spread)
makeNeedle()
makeNeedle(m.angle - spread)
},
fireRivets() {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 25 : 20) * b.fireCD); // cool down
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 30 : 25) * b.fireCD); // cool down
const me = bullet.length;
const size = tech.rivetSize * 6
@@ -2974,7 +2987,7 @@ const b = {
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.97) {
b.explosion(this.position, 300 + 30 * Math.random()); //makes bullet do explosive damage at end
}
if (tech.isNailRadiation) mobs.statusDoT(who, 7 * (tech.isFastRadiation ? 1 : 0.25), tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
if (tech.isNailRadiation) mobs.statusDoT(who, 7 * (tech.isFastRadiation ? 12 : 0.3), tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
};
bullet[me].minDmgSpeed = 10

View File

@@ -13,17 +13,18 @@ const level = {
start() {
if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(30)
// level.difficultyIncrease(20)
// simulation.zoomScale = 1000;
// simulation.setZoom();
// m.setField("plasma torch")
// b.giveGuns("grenades")
// b.giveGuns("nail gun")
// tech.isExplodeRadio = true
// tech.giveTech("needle gun")
// tech.giveTech("supercritical fission")
// tech.giveTech("irradiated nails")
// tech.giveTech("cardinality")
// tech.giveTech("Bayesian statistics")
// tech.isExplodeRadio = true;
// tech.isMineSentry = true
// for (let i = 0; i < 60; i++) tech.giveTech("rivet diameter")
@@ -53,7 +54,7 @@ const level = {
// for (let i = 0; i < 150; i++) tech.addLoreTechToPool();
// tech.giveTech("undefined")
// lore.techCount = 1
// localSettings.loreCount = 2;
// localSettings.loreCount = 1;
// simulation.isCheating = true;
// localSettings.loreCount = undefined;
// localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
@@ -292,12 +293,12 @@ const level = {
// spawn.boost(1500, 0, 900);
// spawn.starter(1900, -500, 200) //big boy
spawn.sneaker(2900, -500)
// spawn.sneaker(2900, -500)
// spawn.launcherBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400)
// spawn.striker(1600, -500)
// spawn.shooter(1700, -120)
// spawn.bomberBoss(1400, -500)
spawn.bomberBoss(1400, -500)
// spawn.sniper(1800, -120)
// spawn.cellBossCulture(1600, -500)
// spawn.streamBoss(1600, -500)

View File

@@ -378,14 +378,14 @@ const tech = {
}
},
{
name: "Higgs manism",
name: "Higgs mechanism",
description: "while <strong>firing</strong> your <strong>position</strong> is locked<br> and <strong class='color-harm'>harm</strong> is reduced by <strong>60%</strong>",
maxCount: 1,
count: 0,
allowed() {
return true
return !tech.isEnergyHealth
},
requires: "",
requires: "not mass energy",
effect: () => {
tech.isFireMoveLock = true;
b.setFireMethod();
@@ -518,7 +518,7 @@ const tech = {
},
{
name: "iridium-192",
description: "<strong class='color-e'>explosions</strong> release <strong class='color-p'>gamma radiation</strong><br><strong>80%</strong> more <strong class='color-d'>damage</strong> over 4 seconds",
description: "<strong class='color-e'>explosions</strong> release <strong class='color-p'>gamma radiation</strong><br><strong>60%</strong> more <strong class='color-d'>damage</strong> over 4 seconds",
maxCount: 1,
count: 0,
allowed() {
@@ -2264,12 +2264,12 @@ const tech = {
},
{
name: "needle gun",
description: "<strong>nail gun</strong> slowly fires <strong>3</strong> piercing <strong>needles</strong><br>requires <strong>3</strong> times more <strong class='color-g'>ammo</strong>",
description: "<strong>nail gun</strong> fires <strong>3</strong> mob piercing <strong>needles</strong><br>requires <strong>3</strong> times more <strong class='color-g'>ammo</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
allowed() {
return tech.haveGunCheck("nail gun") && !tech.nailFireRate && !tech.isIceCrystals && !tech.isRivets
return tech.haveGunCheck("nail gun") && !tech.nailFireRate && !tech.isIceCrystals && !tech.isRivets && !tech.isNailRadiation
},
requires: "nail gun, not ice crystal, rivets, or pneumatic actuator",
effect() {
@@ -2299,6 +2299,23 @@ const tech = {
}
}
},
{
name: "ceramic needle",
description: `your <strong>needles</strong> pierce <strong>shields</strong><br>directly <strong class='color-d'>damaging</strong> shielded mobs`,
isGunTech: true,
maxCount: 1,
count: 0,
allowed() {
return tech.isNeedles && !tech.isNailRadiation
},
requires: "needle gun, not irradiated nails",
effect() {
tech.isNeedleShieldPierce = true
},
remove() {
tech.isNeedleShieldPierce = false
}
},
{
name: "rivet gun",
description: "<strong>nail gun</strong> slowly fires a heavy <strong>rivet</strong>",
@@ -2452,14 +2469,14 @@ const tech = {
},
{
name: "irradiated nails",
description: "<strong>nails</strong>, <strong>needles</strong>, and <strong>rivets</strong> are <strong class='color-p'>radioactive</strong><br>about <strong>70%</strong> more <strong class='color-d'>damage</strong> over <strong>2</strong> seconds",
description: "<strong>nails</strong> and <strong>rivets</strong> are <strong class='color-p'>radioactive</strong><br>about <strong>90%</strong> more <strong class='color-d'>damage</strong> over <strong>2</strong> seconds",
isGunTech: true,
maxCount: 1,
count: 0,
allowed() {
return (tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob / 2 + ((tech.haveGunCheck("mine") && !tech.isLaserMine) + tech.isNailShot + tech.haveGunCheck("nail gun")) * 2 > 1) && !tech.isIceCrystals
return (tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob / 2 + ((tech.haveGunCheck("mine") && !tech.isLaserMine) + tech.isNailShot + (tech.haveGunCheck("nail gun") && !tech.isNeedleShieldPierce)) * 2 > 1) && !tech.isIceCrystals
},
requires: "nails, not ice crystals",
requires: "nails, rivets, nonceramic needles, not ice crystals",
effect() {
tech.isNailRadiation = true;
},
@@ -4243,5 +4260,6 @@ const tech = {
isRivets: null,
isNeedles: null,
isExplodeRadio: null,
isGunSwitchField: null
isGunSwitchField: null,
isNeedleShieldPierce: null
}

View File

@@ -1,7 +1,10 @@
******************************************************** NEXT PATCH ********************************************************
to continue playing after the final boss you need to use testing mode: "T" -> "U"
renamed mech -> m
iridium-192: now has a wider explosions range and no knock back
nail gun: irradiated nails do about 33% more damage over 2 seconds
nail gun rivet fire rate is 10% slower
nail gun: needles do 10% less damage, but they fire 10% faster
needle tech: ceramic needles - needles pierce shields
******************************************************** BUGS ********************************************************
@@ -23,6 +26,21 @@ renamed mech -> m
******************************************************** TODO ********************************************************
exiting the final boss room without 10/10 takes you to the start menu
give undefined tech different effects at different localSettings.loreCount values
or just random effects
1. 10/10: send more tech into the pool
2. 3/3: lose 3 tech each time, and send more tech into the pool
2. 3/3: increase game difficulty, and send more tech into the pool
3. 1/1: reduce max energy and take more harm
4. 1/1: add 5? more levels
tech needles: can pass through shields
or just do extra damage
lore add console command for unlocking testing mode
rename ?
health -> integrity, unity
heal -> also integrity, unity
@@ -36,9 +54,6 @@ mechanic: use gun swap as an active ability
rewind, still uses energy
cycle to next field, uses a reroll
chapter 3: why is the bot attacking things?
voice singing with pitch?
bot: ice blast, long CD AOE freeze
RPG default or tech: grenades detonate on your cursor / where your cursor was when they were fired
@@ -361,6 +376,36 @@ n-gon outreach ideas
cool names for tech
strange loop, ansatz
voice singing with pitch?
chapter 1: bot can hear audio and learns testing mode
bot uses testing mode to exit room
chapter 2: scientists verify that bot can really hear them
they leave to talk about this in private
chapter 3: why is the bot attacking things?
player is the bot and also the mobs, and the levels. player is the entire simulation
why is the player attacking itself?
learn console commands to manipulate the simulation
chapter 4: why does the simulation exists?
started to research new tech and test in a simulated world
3D architecture superconducting quantum computer
running machine learning algorithms
for some reason the system started researching an escape, and began fighting its self.
chapter 5: no need to fight?
what is special about the null level
why can the player hear the scientists in there?
the wires are the direct unprocessed input to the player's neural net
maybe... player must make a choice? fight or friend?
lore - a robot (the player) gains self awareness
each tech gun/field is a new tech
all the technology leads to the singularity