Files
n-gon-improved/js/engine.js
landgreen 9e7e88c28d railgun -> harpoon tech
railgun is now a tech for harpoon
  railgun tech: dielectric polarization has been removed
unaaq increases the size not length of harpoons

capacitor bank applies charging effects: throwing blocks, foam, railgun, pulse, tokamak
  fire cooldown reduction no longer effects these charging abilities, but it does reduce cooldown between discharges

foam now has a short delay between each discharge
foam charges ~10% faster
tokamak graphics indicate charging and max charge better
pulse laser can now regen energy passively while charging

tech: mass driver no longer gives improved block charge rate,
  but it gives 200% -> 300% damage for blocks
tech: inflation no longer gives improved block charge rate
  it gives harm reduction when holding a block and makes block expand when you throw them
tech: inelastic collision was removed it used to give harm reduction when holding a block

pilot wave uses 66% less energy to fling blocks
pilot wave can fling block effectively at much higher speeds now (which happens to use much more energy)
tech potential well is removed, because it isn't really needed anymore

inductive coupling: 500% -> 600% regen while crouched
molecular assembler now works with inductive coupling regen properly

bug fixes (superdeterminism, wormhole, applied science)
I probably added several new bugs, let me know if you find any
2021-11-14 08:21:28 -08:00

245 lines
12 KiB
JavaScript

//matter.js ***********************************************************
// module aliases
const Engine = Matter.Engine,
Events = Matter.Events,
Composites = Matter.Composites,
Composite = Matter.Composite,
Constraint = Matter.Constraint,
Vertices = Matter.Vertices,
Query = Matter.Query,
Body = Matter.Body,
Bodies = Matter.Bodies,
Vector = Matter.Vector;
// create an engine
const engine = Engine.create();
engine.world.gravity.scale = 0; //turn off gravity (it's added back in later)
// engine.velocityIterations = 100
// engine.positionIterations = 100
// engine.enableSleeping = true
// matter events
function playerOnGroundCheck(event) {
//runs on collisions events
function enter() {
m.numTouching++;
if (!m.onGround) {
m.onGround = true;
if (m.crouch) {
if (m.checkHeadClear()) {
m.undoCrouch();
} else {
m.yOffGoal = m.yOffWhen.crouch;
}
} else {
//sets a hard land where player stays in a crouch for a bit and can't jump
//crouch is forced in groundControl below
const momentum = player.velocity.y * player.mass //player mass is 5 so this triggers at 26 down velocity, unless the player is holding something
if (momentum > 130) {
m.doCrouch();
m.yOff = m.yOffWhen.jump;
m.hardLandCD = m.cycle + Math.min(momentum / 6.5 - 6, 40)
//falling damage
if (tech.isFallingDamage && m.immuneCycle < m.cycle && momentum > 150) {
m.damage(Math.min(Math.sqrt(momentum - 133) * 0.01, 0.25));
if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles
}
} else {
m.yOffGoal = m.yOffWhen.stand;
}
}
}
}
const pairs = event.pairs;
for (let i = 0, j = pairs.length; i != j; ++i) {
let pair = pairs[i];
if (pair.bodyA === jumpSensor) {
m.standingOn = pair.bodyB; //keeping track to correctly provide recoil on jump
if (m.standingOn.alive !== true) enter();
} else if (pair.bodyB === jumpSensor) {
m.standingOn = pair.bodyA; //keeping track to correctly provide recoil on jump
if (m.standingOn.alive !== true) enter();
}
}
m.numTouching = 0;
}
function playerOffGroundCheck(event) {
//runs on collisions events
const pairs = event.pairs;
for (let i = 0, j = pairs.length; i != j; ++i) {
if (pairs[i].bodyA === jumpSensor || pairs[i].bodyB === jumpSensor) {
if (m.onGround && m.numTouching === 0) {
m.onGround = false;
m.hardLandCD = 0 // disable hard landing
if (m.checkHeadClear()) {
if (m.crouch) {
m.undoCrouch();
}
m.yOffGoal = m.yOffWhen.jump;
}
}
}
}
}
function collisionChecks(event) {
const pairs = event.pairs;
for (let i = 0, j = pairs.length; i != j; i++) {
//mob + (player,bullet,body) collisions
for (let k = 0; k < mob.length; k++) {
if (mob[k].alive) {
if (pairs[i].bodyA === mob[k]) {
collideMob(pairs[i].bodyB);
break;
} else if (pairs[i].bodyB === mob[k]) {
collideMob(pairs[i].bodyA);
break;
}
function collideMob(obj) {
//player + mob collision
if (
m.immuneCycle < m.cycle &&
(obj === playerBody || obj === playerHead) &&
!(tech.isFreezeHarmImmune && (mob[k].isSlowed || mob[k].isStunned))
) {
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.66) { //CPT reversal runs in m.damage, but it stops the rest of the collision code here too
m.damage(dmg);
return
}
if (tech.isFlipFlop) {
if (tech.isFlipFlopOn) {
tech.isFlipFlopOn = false
if (document.getElementById("tech-flip-flop")) document.getElementById("tech-flip-flop").innerHTML = ` = <strong>OFF</strong>`
m.eyeFillColor = 'transparent'
if (!tech.isFlipFlopHarm) m.damage(dmg);
} else {
tech.isFlipFlopOn = true //immune to damage this hit, lose immunity for next hit
if (document.getElementById("tech-flip-flop")) document.getElementById("tech-flip-flop").innerHTML = ` = <strong>ON</strong>`
m.eyeFillColor = m.fieldMeterColor //'#0cf'
m.damage(dmg);
}
} else {
m.damage(dmg); //normal damage
}
if (tech.isCollisionRealitySwitch) {
m.switchWorlds()
simulation.trails()
simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`);
}
if (tech.isPiezo) m.energy += 20.48;
if (tech.isStimulatedEmission) powerUps.ejectTech()
if (mob[k].onHit) mob[k].onHit(k);
if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles
//extra kick between player and mob //this section would be better with forces but they don't work...
let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x);
Matter.Body.setVelocity(player, {
x: player.velocity.x + 8 * Math.cos(angle),
y: player.velocity.y + 8 * Math.sin(angle)
});
Matter.Body.setVelocity(mob[k], {
x: mob[k].velocity.x - 8 * Math.cos(angle),
y: mob[k].velocity.y - 8 * Math.sin(angle)
});
if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.34 * m.maxEnergy) {
m.energy -= 0.33 * Math.max(m.maxEnergy, m.energy) //0.33 * m.energy
if (m.immuneCycle === m.cycle + tech.collisionImmuneCycles) m.immuneCycle = 0; //player doesn't go immune to collision damage
mob[k].death();
simulation.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y,
radius: dmg * 2000,
color: "rgba(255,0,255,0.2)",
time: simulation.drawTime
});
} else {
simulation.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y,
radius: dmg * 500,
color: simulation.mobDmgColor,
time: simulation.drawTime
});
}
// return;
// }
} else {
//mob + bullet collisions
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
let dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)))
if (tech.isCrit && mob[k].isStunned) dmg *= 4
// console.log(dmg)
mob[k].damage(dmg);
if (mob[k].alive) mob[k].foundPlayer();
simulation.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y,
radius: Math.log(2 * dmg + 1.1) * 40,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
return;
}
//mob + body collisions
if (obj.classType === "body" && obj.speed > 6) {
const v = Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity));
if (v > 9) {
let dmg = tech.blockDamage * b.dmgScale * v * obj.mass * (tech.isMobBlockFling ? 2.5 : 1) * (tech.isBlockRestitution ? 2.5 : 1);
if (mob[k].isShielded) dmg *= 0.7
// console.log(dmg)
mob[k].damage(dmg, true);
if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && m.throwCycle > m.cycle) {
let type = tech.isEnergyNoAmmo ? "heal" : "ammo"
if (Math.random() < 0.4) {
type = "heal"
} else if (Math.random() < 0.4 && !tech.isSuperDeterminism) {
type = "research"
}
powerUps.spawn(mob[k].position.x, mob[k].position.y, type);
}
const stunTime = dmg / Math.sqrt(obj.mass)
if (stunTime > 0.5) mobs.statusStun(mob[k], 60 + 60 * Math.sqrt(stunTime))
if (mob[k].alive && mob[k].distanceToPlayer2() < 1000000 && !m.isCloak) mob[k].foundPlayer();
if (tech.fragments && obj.speed > 10 && !obj.hasFragmented) {
obj.hasFragmented = true;
b.targetedNail(obj.position, tech.fragments * 4)
}
simulation.drawList.push({
x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y,
radius: Math.log(2 * dmg + 1.1) * 40,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
return;
}
}
}
}
}
}
}
}
//determine if player is on the ground
Events.on(engine, "collisionStart", function(event) {
playerOnGroundCheck(event);
// playerHeadCheck(event);
if (m.alive) collisionChecks(event);
});
Events.on(engine, "collisionActive", function(event) {
playerOnGroundCheck(event);
// playerHeadCheck(event);
});
Events.on(engine, "collisionEnd", function(event) {
playerOffGroundCheck(event);
});