drone rework, reroll mods
anthropic principle - now consumes 1 rerolls, and heals player to 50% health instead of letting them die many worlds - 66% chance for rerolls quantum immortality - also gives 3 rerolls mod drones - Brushless Motor: drones move faster mod drones - redundant systems: removed choices in power up selection should no longer repeat the previous choices when possible
This commit is contained in:
136
js/bullets.js
136
js/bullets.js
@@ -36,7 +36,7 @@ const b = {
|
||||
modCollisionImmuneCycles: null,
|
||||
modBlockDmg: null,
|
||||
isModPiezo: null,
|
||||
isModDroneCollide: null,
|
||||
isModFastDrones: null,
|
||||
isModFastSpores: null,
|
||||
modSuperBallNumber: null,
|
||||
modOneSuperBall: null,
|
||||
@@ -49,7 +49,6 @@ const b = {
|
||||
isModHealthRecovery: null,
|
||||
isModEnergyLoss: null,
|
||||
isModDeathAvoid: null,
|
||||
isModDeathAvoidOnCD: null,
|
||||
modWaveSpeedMap: null,
|
||||
modWaveSpeedBody: null,
|
||||
isModSporeField: null,
|
||||
@@ -531,7 +530,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
name: "Pauli exclusion",
|
||||
description: `unable to <strong>collide</strong> with mobs for <strong>+2</strong> seconds<br>activates after being <strong>harmed</strong> from a collision`,
|
||||
description: `<strong>immune</strong> to <strong>harm</strong> for <strong>+1</strong> seconds<br>activates after being <strong>harmed</strong> from a collision`,
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -539,8 +538,8 @@ const b = {
|
||||
},
|
||||
requires: "",
|
||||
effect() {
|
||||
b.modCollisionImmuneCycles += 120;
|
||||
mech.collisionImmuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
|
||||
b.modCollisionImmuneCycles += 60;
|
||||
mech.immuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
|
||||
},
|
||||
remove() {
|
||||
b.modCollisionImmuneCycles = 30;
|
||||
@@ -562,40 +561,6 @@ const b = {
|
||||
b.isModSlowFPS = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "quantum immortality",
|
||||
description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br><em>guns, ammo, field, and mods are randomized</em>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
effect() {
|
||||
b.isModImmortal = true;
|
||||
},
|
||||
remove() {
|
||||
b.isModImmortal = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "anthropic principle",
|
||||
description: "<strong>fatal harm</strong> can't happen<br><strong>saves</strong> you up to once every <strong>3</strong> seconds",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
effect() {
|
||||
b.isModDeathAvoid = true;
|
||||
b.isModDeathAvoidOnCD = false;
|
||||
},
|
||||
remove() {
|
||||
b.isModDeathAvoid = false;
|
||||
b.isModDeathAvoidOnCD = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "entanglement",
|
||||
nameInfo: "<span id = 'mod-entanglement'></span>",
|
||||
@@ -780,7 +745,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
name: "Bayesian inference",
|
||||
description: "<strong>33%</strong> chance for double <strong>power ups</strong> to drop<br><strong>remove</strong> all future <strong>ammo</strong> power ups",
|
||||
description: "<strong>37%</strong> chance for double <strong>power ups</strong> to drop<br><strong>remove</strong> all future <strong>ammo</strong> power ups",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -788,7 +753,7 @@ const b = {
|
||||
},
|
||||
requires: "",
|
||||
effect: () => {
|
||||
b.modBayesian = 0.33;
|
||||
b.modBayesian = 0.37;
|
||||
},
|
||||
remove() {
|
||||
b.modBayesian = 0;
|
||||
@@ -828,7 +793,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
name: "determinism",
|
||||
description: "spawn <strong>4</strong> <strong class='color-m'>mods</strong> and 2 <strong class='color-h'>heal</strong> power ups<br>future <strong>power ups</strong> are limited to <strong>one choice</strong>",
|
||||
description: "spawn <strong>5</strong> <strong class='color-m'>mods</strong> and 2 <strong class='color-h'>heal</strong> power ups<br>future <strong>power ups</strong> are limited to <strong>one choice</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -837,7 +802,7 @@ const b = {
|
||||
requires: "not cardinality",
|
||||
effect: () => {
|
||||
b.isModDeterminism = true;
|
||||
for (let i = 0; i < 4; i++) { //if you change the six also change it in Born rule
|
||||
for (let i = 0; i < 5; i++) { //if you change the six also change it in Born rule
|
||||
powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
|
||||
if (Math.random() < b.modBayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
|
||||
}
|
||||
@@ -852,7 +817,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
name: "many worlds",
|
||||
description: "spawn a <strong class='color-r'>reroll</strong> after choosing a power up",
|
||||
description: "after choosing a <strong>gun</strong>, <strong>field</strong>, or <strong class='color-m'>mod</strong><br><strong>66%</strong> chance to spawn a <strong class='color-r'>reroll</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -870,6 +835,45 @@ const b = {
|
||||
b.manyWorlds = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "anthropic principle",
|
||||
nameInfo: "<span id = 'mod-anthropic'></span>",
|
||||
description: "<strong class='color-h'>heal</strong> to <strong>50%</strong> health instead of <strong>dying</strong><br>consumes <strong>1</strong> <strong class='color-r'>reroll</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return powerUps.reroll.rerolls > 0 || build.isCustomSelection
|
||||
},
|
||||
requires: "at least 1 reroll",
|
||||
effect() {
|
||||
b.isModDeathAvoid = true;
|
||||
setTimeout(function () {
|
||||
powerUps.reroll.changeRerolls(0)
|
||||
}, 1000);
|
||||
},
|
||||
remove() {
|
||||
b.isModDeathAvoid = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "quantum immortality",
|
||||
description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br>spawn <strong>3</strong> <strong class='color-r'>rerolls</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
effect() {
|
||||
b.isModImmortal = true;
|
||||
powerUps.spawn(mech.pos.x, mech.pos.y, "reroll", false);
|
||||
powerUps.spawn(mech.pos.x, mech.pos.y, "reroll", false);
|
||||
powerUps.spawn(mech.pos.x, mech.pos.y, "reroll", false);
|
||||
},
|
||||
remove() {
|
||||
b.isModImmortal = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Born rule",
|
||||
description: "<strong>remove</strong> all current <strong class='color-m'>mods</strong><br>spawn new <strong class='color-m'>mods</strong> to replace them",
|
||||
@@ -991,7 +995,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
name: "shotgun spin-statistics",
|
||||
description: "firing the <strong>shotgun</strong> makes you <br><strong>immune</strong> to collisions for <strong>1 second</strong>",
|
||||
description: "firing the <strong>shotgun</strong> makes you <br><strong>immune</strong> to <strong>harm</strong> for <strong>1 second</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -1364,8 +1368,8 @@ const b = {
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "redundant systems",
|
||||
description: "<strong>drone</strong> collisions no longer reduce their <strong>lifespan</strong>",
|
||||
name: "brushless motor",
|
||||
description: "<strong>drones</strong> accelerate <strong>50%</strong> faster",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -1373,10 +1377,10 @@ const b = {
|
||||
},
|
||||
requires: "drones",
|
||||
effect() {
|
||||
b.isModDroneCollide = true
|
||||
b.isModFastDrones = true
|
||||
},
|
||||
remove() {
|
||||
b.isModDroneCollide = true;
|
||||
b.isModFastDrones = false
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2133,7 +2137,7 @@ const b = {
|
||||
let collide = Matter.Query.collides(this, map) //check if collides with map
|
||||
if (collide.length > 0) {
|
||||
for (let i = 0; i < collide.length; i++) {
|
||||
if (collide[i].bodyA.collisionFilter.category === cat.map || collide[i].bodyB.collisionFilter.category === cat.map) {
|
||||
if (collide[i].bodyA.collisionFilter.category === cat.map) { // || collide[i].bodyB.collisionFilter.category === cat.map) {
|
||||
const angle = Matter.Vector.angle(collide[i].normal, {
|
||||
x: 1,
|
||||
y: 0
|
||||
@@ -2141,7 +2145,7 @@ const b = {
|
||||
Matter.Body.setAngle(this, Math.atan2(collide[i].tangent.y, collide[i].tangent.x))
|
||||
//move until touching map again after rotation
|
||||
for (let j = 0; j < 10; j++) {
|
||||
if (Matter.Query.collides(this, map).length > 0) {
|
||||
if (Matter.Query.collides(this, map).length > 0) { //touching map
|
||||
if (angle > -0.2 || angle < -1.5) { //don't stick to level ground
|
||||
Matter.Body.setStatic(this, true) //don't set to static if not touching map
|
||||
} else {
|
||||
@@ -2156,7 +2160,8 @@ const b = {
|
||||
//sometimes the mine can't attach to map and it just needs to be reset
|
||||
const that = this
|
||||
setTimeout(function () {
|
||||
if (Matter.Query.collides(that, map).length === 0) {
|
||||
if (Matter.Query.collides(that, map).length === 0 || Matter.Query.point(map, that.position).length > 0) {
|
||||
console.log(that)
|
||||
that.endCycle = 0 // if not touching map explode
|
||||
that.isArmed = false
|
||||
b.mine(that.position, that.velocity, that.angle)
|
||||
@@ -2366,17 +2371,18 @@ const b = {
|
||||
},
|
||||
drone(speed = 1) {
|
||||
const me = bullet.length;
|
||||
const THRUST = 0.0015
|
||||
const dir = mech.angle + 0.2 * (Math.random() - 0.5);
|
||||
const THRUST = b.isModFastDrones ? 0.0025 : 0.0015
|
||||
const FRICTION = b.isModFastDrones ? 0.008 : 0.0005
|
||||
const dir = mech.angle + 0.4 * (Math.random() - 0.5);
|
||||
const RADIUS = (4.5 + 3 * Math.random())
|
||||
bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 8, RADIUS, {
|
||||
angle: dir,
|
||||
inertia: Infinity,
|
||||
friction: 0.05,
|
||||
frictionAir: 0.0005,
|
||||
frictionAir: FRICTION,
|
||||
restitution: 1,
|
||||
dmg: 0.23, //damage done in addition to the damage from momentum
|
||||
lookFrequency: 107 + Math.floor(47 * Math.random()),
|
||||
lookFrequency: 100 + Math.floor(23 * Math.random()),
|
||||
endCycle: game.cycle + Math.floor((1200 + 420 * Math.random()) * b.isModBulletsLastLonger),
|
||||
classType: "bullet",
|
||||
collisionFilter: {
|
||||
@@ -2396,7 +2402,7 @@ const b = {
|
||||
});
|
||||
|
||||
this.lockedOn = null
|
||||
if (this.endCycle > game.cycle + this.deathCycles && b.isModDroneCollide) {
|
||||
if (this.endCycle > game.cycle + this.deathCycles) {
|
||||
this.endCycle -= 60
|
||||
if (game.cycle + this.deathCycles > this.endCycle) this.endCycle = game.cycle + this.deathCycles
|
||||
}
|
||||
@@ -2966,7 +2972,7 @@ const b = {
|
||||
}
|
||||
player.force.x -= knock * Math.cos(mech.angle)
|
||||
player.force.y -= knock * Math.sin(mech.angle) * 0.3 //reduce knock back in vertical direction to stop super jumps
|
||||
if (b.isModShotgunImmune) mech.collisionImmuneCycle = mech.cycle + 60; //player is immune to collision damage for 30 cycles
|
||||
if (b.isModShotgunImmune) mech.immuneCycle = mech.cycle + 60; //player is immune to collision damage for 30 cycles
|
||||
b.muzzleFlash(35);
|
||||
const side = 19 * b.modBulletSize
|
||||
for (let i = 0; i < 15; i++) {
|
||||
@@ -3687,11 +3693,15 @@ const b = {
|
||||
isStarterGun: false,
|
||||
isEasyToAim: true,
|
||||
fire() {
|
||||
const speed = mech.crouch ? 36 : 22
|
||||
b.mine({
|
||||
const pos = {
|
||||
x: mech.pos.x + 30 * Math.cos(mech.angle),
|
||||
y: mech.pos.y + 30 * Math.sin(mech.angle)
|
||||
}, {
|
||||
}
|
||||
let speed = mech.crouch ? 36 : 22
|
||||
if (Matter.Query.point(map, pos).length > 0) { //don't fire if mine will spawn inside map
|
||||
speed = -2
|
||||
}
|
||||
b.mine(pos, {
|
||||
x: speed * Math.cos(mech.angle),
|
||||
y: speed * Math.sin(mech.angle)
|
||||
}, 0, b.isModMineAmmoBack)
|
||||
@@ -3820,13 +3830,13 @@ const b = {
|
||||
name: "drones",
|
||||
description: "deploy drones that <strong>crash</strong> into mobs<br>collisions reduce their <strong>lifespan</strong> by 1 second",
|
||||
ammo: 0,
|
||||
ammoPack: 14,
|
||||
ammoPack: 15,
|
||||
have: false,
|
||||
isStarterGun: true,
|
||||
isEasyToAim: true,
|
||||
fire() {
|
||||
b.drone(mech.crouch ? 45 : 1)
|
||||
mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 25 : 5) * b.modFireRate); // cool down
|
||||
mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 13 : 5) * b.modFireRate); // cool down
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
30
js/engine.js
30
js/engine.js
@@ -97,8 +97,7 @@ function collisionChecks(event) {
|
||||
|
||||
function collidePlayer(obj) {
|
||||
//player dmg from hitting a body
|
||||
// if ( mech.collisionImmuneCycle < mech.cycle) {
|
||||
if (obj.classType === "body" && obj.speed > 10 && mech.collisionImmuneCycle < mech.cycle) {
|
||||
if (obj.classType === "body" && obj.speed > 10 && mech.immuneCycle < mech.cycle) {
|
||||
const velocityThreshold = 30 //keep this lines up with player.enterLand numbers (130/5 = 26)
|
||||
if (player.position.y > obj.position.y) { //block is above the player look at total momentum difference
|
||||
const velocityDiffMag = Vector.magnitude(Vector.sub(player.velocity, obj.velocity))
|
||||
@@ -109,7 +108,7 @@ function collisionChecks(event) {
|
||||
}
|
||||
|
||||
function hit(dmg) {
|
||||
mech.collisionImmuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
|
||||
mech.immuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
|
||||
dmg = Math.min(Math.max(Math.sqrt(dmg) * obj.mass * 0.01, 0.02), 0.15);
|
||||
mech.damage(dmg);
|
||||
game.drawList.push({ //add dmg to draw queue
|
||||
@@ -123,27 +122,6 @@ function collisionChecks(event) {
|
||||
}
|
||||
}
|
||||
|
||||
// function collidePlayer(obj, speedThreshold = 12, massThreshold = 2) {
|
||||
// //player dmg from hitting a body
|
||||
// if (obj.classType === "body" && mech.collisionImmuneCycle < mech.cycle && obj.speed > speedThreshold && obj.mass > massThreshold) {
|
||||
// const v = Vector.magnitude(Vector.sub(player.velocity, obj.velocity));
|
||||
// if ((Math.abs(obj.velocity.x - player.velocity.x) > speedThreshold) || (player.position.y > obj.position.y && v > speedThreshold)) {
|
||||
// mech.collisionImmuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
|
||||
// let dmg = Math.sqrt((v - speedThreshold + 0.1) * (obj.mass - massThreshold)) * 0.01;
|
||||
// dmg = Math.min(Math.max(dmg, 0.02), 0.15);
|
||||
// mech.damage(dmg);
|
||||
// game.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: game.mobDmgColor,
|
||||
// time: game.drawTime
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
//mob + (player,bullet,body) collisions
|
||||
for (let k = 0; k < mob.length; k++) {
|
||||
if (mob[k].alive && mech.alive) {
|
||||
@@ -157,8 +135,8 @@ function collisionChecks(event) {
|
||||
|
||||
function collideMob(obj) {
|
||||
//player + mob collision
|
||||
if (mech.collisionImmuneCycle < mech.cycle && (obj === playerBody || obj === playerHead)) {
|
||||
mech.collisionImmuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
|
||||
if (mech.immuneCycle < mech.cycle && (obj === playerBody || obj === playerHead)) {
|
||||
mech.immuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
|
||||
mob[k].foundPlayer();
|
||||
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * game.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0
|
||||
if (b.isModPiezo) {
|
||||
|
||||
@@ -17,9 +17,9 @@ const level = {
|
||||
// game.enableConstructMode() //used to build maps in testing mode
|
||||
// level.difficultyIncrease(9)
|
||||
// mech.setField("time dilation field")
|
||||
// b.giveMod("many worlds");
|
||||
// b.giveGuns("neutron bomb")
|
||||
// b.giveGuns("foam")
|
||||
// b.giveMod("brushless motor");
|
||||
// b.giveGuns("drones")
|
||||
// b.giveGuns("mine")
|
||||
// mech.setField("pilot wave")
|
||||
// mech.setField("phase decoherence field")
|
||||
|
||||
@@ -135,7 +135,7 @@ const level = {
|
||||
spawn.mapRect(-250, -700, 1000, 900); // shelf
|
||||
spawn.mapRect(-250, -1200, 1000, 250); // shelf roof
|
||||
powerUps.spawnStartingPowerUps(600, -800);
|
||||
powerUps.spawn(550, -800, "reroll", false); //starting gun
|
||||
powerUps.spawn(550, -800, "reroll", false);
|
||||
|
||||
function blockDoor(x, y, blockSize = 58) {
|
||||
spawn.mapRect(x, y - 290, 40, 60); // door lip
|
||||
|
||||
@@ -373,7 +373,7 @@ const mobs = {
|
||||
ctx.setLineDash([125 * Math.random(), 125 * Math.random()]);
|
||||
// ctx.lineDashOffset = 6*(game.cycle % 215);
|
||||
if (this.distanceToPlayer() < this.laserRange && !mech.isStealth) {
|
||||
if (mech.collisionImmuneCycle < mech.cycle) mech.damage(0.0003 * game.dmgScale);
|
||||
if (mech.immuneCycle < mech.cycle) mech.damage(0.0003 * game.dmgScale);
|
||||
if (mech.energy > 0.1) mech.energy -= 0.003
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(this.position.x, this.position.y);
|
||||
@@ -461,7 +461,8 @@ const mobs = {
|
||||
if (!mech.isStealth) vertexCollision(this.position, look, [player]);
|
||||
// hitting player
|
||||
if (best.who === player) {
|
||||
if (mech.collisionImmuneCycle < mech.cycle) dmg = 0.0012 * game.dmgScale;
|
||||
if (mech.immuneCycle < mech.cycle) {
|
||||
const dmg = 0.0012 * game.dmgScale;
|
||||
mech.damage(dmg);
|
||||
//draw damage
|
||||
ctx.fillStyle = "#f00";
|
||||
@@ -469,6 +470,7 @@ const mobs = {
|
||||
ctx.arc(best.x, best.y, dmg * 2000, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
//draw beam
|
||||
if (best.dist2 === Infinity) {
|
||||
best = look;
|
||||
|
||||
57
js/player.js
57
js/player.js
@@ -215,9 +215,6 @@ const mech = {
|
||||
mech.yOff = mech.yOffWhen.jump;
|
||||
mech.hardLandCD = mech.cycle + Math.min(momentum / 6.5 - 6, 40)
|
||||
|
||||
// if (b.isModStompPauli) {
|
||||
// mech.collisionImmuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
|
||||
// }
|
||||
if (b.isModStomp) {
|
||||
const len = Math.min(25, (momentum - 120) * 0.1)
|
||||
for (let i = 0; i < len; i++) {
|
||||
@@ -363,7 +360,7 @@ const mech = {
|
||||
if (b.isModImmortal) { //if player has the immortality buff, spawn on the same level with randomized stats
|
||||
spawn.setSpawnList(); //new mob types
|
||||
game.clearNow = true; //triggers a map reset
|
||||
powerUps.reroll.rerolls = Math.floor(Math.random() * Math.random() * 8)
|
||||
powerUps.reroll.rerolls = Math.floor(Math.random() * Math.random() * 12)
|
||||
|
||||
//count mods
|
||||
let totalMods = 0;
|
||||
@@ -511,7 +508,7 @@ const mech = {
|
||||
}
|
||||
},
|
||||
defaultFPSCycle: 0, //tracks when to return to normal fps
|
||||
collisionImmuneCycle: 0, //used in engine
|
||||
immuneCycle: 0, //used in engine
|
||||
harmReduction() {
|
||||
let dmg = 1
|
||||
dmg *= mech.fieldDamageResistance
|
||||
@@ -548,24 +545,23 @@ const mech = {
|
||||
if (b.isModEnergyHealth) {
|
||||
mech.energy -= dmg;
|
||||
if (mech.energy < 0 || isNaN(mech.energy)) {
|
||||
if (b.isModDeathAvoid && !b.isModDeathAvoidOnCD) { //&& Math.random() < 0.5
|
||||
b.isModDeathAvoidOnCD = true;
|
||||
mech.energy += dmg //undo the damage
|
||||
if (mech.energy < 0.05) mech.energy = 0.05
|
||||
mech.collisionImmuneCycle = mech.cycle + 30 //disable this.collisionImmuneCycle bonus seconds
|
||||
if (b.isModDeathAvoid && powerUps.reroll.rerolls) { //&& Math.random() < 0.5
|
||||
powerUps.reroll.changeRerolls(-1)
|
||||
|
||||
mech.energy = mech.maxEnergy * 0.5
|
||||
// if (mech.energy < 0.05) mech.energy = 0.05
|
||||
mech.immuneCycle = mech.cycle + 120 //disable this.immuneCycle bonus seconds
|
||||
game.makeTextLog("<span style='font-size:115%;'> <strong>death</strong> avoided<br><strong>1</strong> <strong class='color-r'>reroll</strong> consumed</span>", 300)
|
||||
|
||||
game.wipe = function () { //set wipe to have trails
|
||||
ctx.fillStyle = "rgba(255,255,255,0.02)";
|
||||
ctx.fillStyle = "rgba(255,255,255,0.03)";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
setTimeout(function () {
|
||||
game.wipe = function () { //set wipe to normal
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
// game.replaceTextLog = true;
|
||||
// game.makeTextLog("death avoided", 360);
|
||||
b.isModDeathAvoidOnCD = false;
|
||||
}, 3000);
|
||||
}, 2000);
|
||||
|
||||
return;
|
||||
} else {
|
||||
@@ -578,24 +574,22 @@ const mech = {
|
||||
} else {
|
||||
mech.health -= dmg;
|
||||
if (mech.health < 0 || isNaN(mech.health)) {
|
||||
if (b.isModDeathAvoid && !b.isModDeathAvoidOnCD) { //&& Math.random() < 0.5
|
||||
b.isModDeathAvoidOnCD = true;
|
||||
mech.health += dmg //undo the damage
|
||||
if (mech.health < 0.05) mech.health = 0.05
|
||||
mech.collisionImmuneCycle = mech.cycle + 30 //disable this.collisionImmuneCycle bonus seconds
|
||||
if (b.isModDeathAvoid && powerUps.reroll.rerolls > 0) { //&& Math.random() < 0.5
|
||||
powerUps.reroll.changeRerolls(-1)
|
||||
mech.health = mech.maxHealth * 0.5
|
||||
// if (mech.health < 0.05) mech.health = 0.05
|
||||
mech.immuneCycle = mech.cycle + 120 //disable this.immuneCycle bonus seconds
|
||||
game.makeTextLog("<span style='font-size:115%;'> <strong>death</strong> avoided<br><strong>1</strong> <strong class='color-r'>reroll</strong> consumed</span>", 300)
|
||||
|
||||
game.wipe = function () { //set wipe to have trails
|
||||
ctx.fillStyle = "rgba(255,255,255,0.02)";
|
||||
ctx.fillStyle = "rgba(255,255,255,0.03)";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
setTimeout(function () {
|
||||
game.wipe = function () { //set wipe to normal
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
// game.replaceTextLog = true;
|
||||
// game.makeTextLog("death avoided", 360);
|
||||
b.isModDeathAvoidOnCD = false;
|
||||
}, 3000);
|
||||
}, 2000);
|
||||
} else {
|
||||
mech.health = 0;
|
||||
mech.death();
|
||||
@@ -711,19 +705,12 @@ const mech = {
|
||||
|
||||
// },
|
||||
draw() {
|
||||
// mech.fillColor = (mech.collisionImmuneCycle < mech.cycle) ? "#fff" : "rgba(255,255,255,0.1)" //"#cff"
|
||||
ctx.fillStyle = mech.fillColor;
|
||||
mech.walk_cycle += mech.flipLegs * mech.Vx;
|
||||
|
||||
//draw body
|
||||
ctx.save();
|
||||
// if (mech.collisionImmuneCycle < mech.cycle) {
|
||||
// ctx.globalAlpha = 1
|
||||
// if (mech.collisionImmune) mech.collisionImmune = false;
|
||||
// } else {
|
||||
// ctx.globalAlpha = 0.7
|
||||
// }
|
||||
ctx.globalAlpha = (mech.collisionImmuneCycle < mech.cycle) ? 1 : 0.7
|
||||
ctx.globalAlpha = (mech.immuneCycle < mech.cycle) ? 1 : 0.7
|
||||
ctx.translate(mech.pos.x, mech.pos.y);
|
||||
mech.calcLeg(Math.PI, -3);
|
||||
mech.drawLeg("#4a4a4a");
|
||||
@@ -1672,8 +1659,8 @@ const mech = {
|
||||
const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.01 * Math.min(5, best.who.mass))
|
||||
Matter.Body.applyForce(best.who, path[1], force)
|
||||
Matter.Body.setVelocity(best.who, { //friction
|
||||
x: best.who.velocity.x * 0.6,
|
||||
y: best.who.velocity.y * 0.6
|
||||
x: best.who.velocity.x * 0.7,
|
||||
y: best.who.velocity.y * 0.7
|
||||
});
|
||||
// const angle = Math.atan2(player.position.y - best.who.position.y, player.position.x - best.who.position.x);
|
||||
// const mass = Math.min(Math.sqrt(best.who.mass), 6);
|
||||
|
||||
112
js/powerups.js
112
js/powerups.js
@@ -21,7 +21,7 @@ const powerUps = {
|
||||
powerUps.endDraft();
|
||||
},
|
||||
endDraft() {
|
||||
if (b.manyWorlds) {
|
||||
if (b.manyWorlds && Math.random() < 0.66) {
|
||||
powerUps.spawn(mech.pos.x, mech.pos.y, "reroll");
|
||||
if (Math.random() < b.modBayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "reroll");
|
||||
}
|
||||
@@ -47,9 +47,16 @@ const powerUps = {
|
||||
return 20;
|
||||
},
|
||||
effect() {
|
||||
powerUps.reroll.rerolls++
|
||||
powerUps.reroll.changeRerolls(1)
|
||||
game.makeTextLog("<div class='circle reroll'></div> <span style='font-size:115%;'> <strong>+1 reroll</strong></span>", 300)
|
||||
},
|
||||
changeRerolls(amount) {
|
||||
powerUps.reroll.rerolls += amount
|
||||
if (powerUps.reroll.rerolls < 0) powerUps.reroll.rerolls = 0
|
||||
if (b.isModDeathAvoid && document.getElementById("mod-anthropic")) {
|
||||
document.getElementById("mod-anthropic").innerHTML = `(${powerUps.reroll.rerolls})`
|
||||
}
|
||||
},
|
||||
diceText() {
|
||||
const r = powerUps.reroll.rerolls
|
||||
const fullDice = Math.floor(r / 6)
|
||||
@@ -71,25 +78,8 @@ const powerUps = {
|
||||
}
|
||||
return out
|
||||
},
|
||||
// diceText() {
|
||||
// if (powerUps.reroll.rerolls === 1) {
|
||||
// return '⚀'
|
||||
// } else if (powerUps.reroll.rerolls === 2) {
|
||||
// return '⚁'
|
||||
// } else if (powerUps.reroll.rerolls === 3) {
|
||||
// return '⚂'
|
||||
// } else if (powerUps.reroll.rerolls === 4) {
|
||||
// return '⚃'
|
||||
// } else if (powerUps.reroll.rerolls === 5) {
|
||||
// return '⚄'
|
||||
// } else if (powerUps.reroll.rerolls === 6) {
|
||||
// return '⚅'
|
||||
// } else if (powerUps.reroll.rerolls > 6) {
|
||||
// return '⚅+'
|
||||
// }
|
||||
// },
|
||||
use(type) {
|
||||
powerUps.reroll.rerolls--;
|
||||
powerUps.reroll.changeRerolls(-1)
|
||||
powerUps[type].effect();
|
||||
},
|
||||
},
|
||||
@@ -153,13 +143,30 @@ const powerUps = {
|
||||
size() {
|
||||
return 45;
|
||||
},
|
||||
choiceLog: [], //records all previous choice options
|
||||
effect() {
|
||||
function pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) {
|
||||
let options = [];
|
||||
for (let i = 1; i < who.length; i++) {
|
||||
if (i !== mech.fieldMode && (!game.isEasyToAimMode || mech.fieldUpgrades[i].isEasyToAim) && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) options.push(i);
|
||||
}
|
||||
if (options.length > 0) return options[Math.floor(Math.random() * options.length)]
|
||||
//remove repeats from last selection
|
||||
const totalChoices = b.isModDeterminism ? 1 : 3 + b.isModExtraChoice * 2
|
||||
if (powerUps.field.choiceLog.length > totalChoices || powerUps.field.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove
|
||||
for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection
|
||||
if (options.length > totalChoices) {
|
||||
for (let j = 0, len = options.length; j < len; j++) {
|
||||
if (powerUps.field.choiceLog[powerUps.field.choiceLog.length - 1 - i] === options[j]) {
|
||||
options.splice(j, 1) //remove previous choice from option pool
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (options.length > 0) {
|
||||
return options[Math.floor(Math.random() * options.length)]
|
||||
}
|
||||
}
|
||||
|
||||
let choice1 = pick(mech.fieldUpgrades)
|
||||
@@ -179,7 +186,13 @@ const powerUps = {
|
||||
if (choice4 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice4})"><div class="grid-title"><div class="circle-grid field"></div> ${mech.fieldUpgrades[choice4].name}</div> ${mech.fieldUpgrades[choice4].description}</div>`
|
||||
let choice5 = pick(mech.fieldUpgrades, choice1, choice2, choice3, choice4)
|
||||
if (choice5 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice5})"><div class="grid-title"><div class="circle-grid field"></div> ${mech.fieldUpgrades[choice5].name}</div> ${mech.fieldUpgrades[choice5].description}</div>`
|
||||
powerUps.field.choiceLog.push(choice4)
|
||||
powerUps.field.choiceLog.push(choice5)
|
||||
}
|
||||
powerUps.field.choiceLog.push(choice1)
|
||||
powerUps.field.choiceLog.push(choice2)
|
||||
powerUps.field.choiceLog.push(choice3)
|
||||
|
||||
if (powerUps.reroll.rerolls) text += `<div class="choose-grid-module" onclick="powerUps.reroll.use('field')"><div class="grid-title"><div class="circle-grid reroll"></div> reroll <span class='dice'>${powerUps.reroll.diceText()}</span></div></div>`
|
||||
|
||||
// text += `<div style = 'color:#fff'>${game.SVGrightMouse} activate the shield with the right mouse<br>fields shield you from damage <br>and let you pick up and throw blocks</div>`
|
||||
@@ -196,6 +209,7 @@ const powerUps = {
|
||||
size() {
|
||||
return 42;
|
||||
},
|
||||
choiceLog: [], //records all previous choice options
|
||||
effect() {
|
||||
function pick(skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) {
|
||||
let options = [];
|
||||
@@ -204,7 +218,23 @@ const powerUps = {
|
||||
options.push(i);
|
||||
}
|
||||
}
|
||||
if (options.length > 0) return options[Math.floor(Math.random() * options.length)]
|
||||
//remove repeats from last selection
|
||||
const totalChoices = b.isModDeterminism ? 1 : 3 + b.isModExtraChoice * 2
|
||||
if (powerUps.mod.choiceLog.length > totalChoices || powerUps.mod.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove
|
||||
for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection
|
||||
if (options.length > totalChoices) {
|
||||
for (let j = 0, len = options.length; j < len; j++) {
|
||||
if (powerUps.mod.choiceLog[powerUps.mod.choiceLog.length - 1 - i] === options[j]) {
|
||||
options.splice(j, 1) //remove previous choice from option pool
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (options.length > 0) {
|
||||
return options[Math.floor(Math.random() * options.length)]
|
||||
}
|
||||
}
|
||||
|
||||
let choice1 = pick()
|
||||
@@ -224,7 +254,12 @@ const powerUps = {
|
||||
if (choice4 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice4})"><div class="grid-title"><div class="circle-grid mod"></div> ${b.mods[choice4].name}</div> ${b.mods[choice4].description}</div>`
|
||||
let choice5 = pick(choice1, choice2, choice3, choice4)
|
||||
if (choice5 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice5})"><div class="grid-title"><div class="circle-grid mod"></div> ${b.mods[choice5].name}</div> ${b.mods[choice5].description}</div>`
|
||||
powerUps.mod.choiceLog.push(choice4)
|
||||
powerUps.mod.choiceLog.push(choice5)
|
||||
}
|
||||
powerUps.mod.choiceLog.push(choice1)
|
||||
powerUps.mod.choiceLog.push(choice2)
|
||||
powerUps.mod.choiceLog.push(choice3)
|
||||
if (powerUps.reroll.rerolls) text += `<div class="choose-grid-module" onclick="powerUps.reroll.use('mod')"><div class="grid-title"><div class="circle-grid reroll"></div> reroll <span class='dice'>${powerUps.reroll.diceText()}</span></div></div>`
|
||||
|
||||
document.getElementById("choose-grid").innerHTML = text
|
||||
@@ -240,13 +275,33 @@ const powerUps = {
|
||||
size() {
|
||||
return 35;
|
||||
},
|
||||
choiceLog: [], //records all previous choice options
|
||||
effect() {
|
||||
function pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) {
|
||||
let options = [];
|
||||
for (let i = 0; i < who.length; i++) {
|
||||
if (!who[i].have && (!game.isEasyToAimMode || b.guns[i].isEasyToAim) && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) options.push(i);
|
||||
if (!who[i].have && (!game.isEasyToAimMode || b.guns[i].isEasyToAim) && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) {
|
||||
options.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
//remove repeats from last selection
|
||||
const totalChoices = b.isModDeterminism ? 1 : 3 + b.isModExtraChoice * 2
|
||||
if (powerUps.gun.choiceLog.length > totalChoices || powerUps.gun.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove
|
||||
for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection
|
||||
if (options.length > totalChoices) {
|
||||
for (let j = 0, len = options.length; j < len; j++) {
|
||||
if (powerUps.gun.choiceLog[powerUps.gun.choiceLog.length - 1 - i] === options[j]) {
|
||||
options.splice(j, 1) //remove previous choice from option pool
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (options.length > 0) {
|
||||
return options[Math.floor(Math.random() * options.length)]
|
||||
}
|
||||
if (options.length > 0) return options[Math.floor(Math.random() * options.length)]
|
||||
}
|
||||
|
||||
let choice1 = pick(b.guns)
|
||||
@@ -267,10 +322,17 @@ const powerUps = {
|
||||
let choice5 = pick(b.guns, choice1, choice2, choice3, choice4)
|
||||
if (choice5 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('gun',${choice5})">
|
||||
<div class="grid-title"><div class="circle-grid gun"></div> ${b.guns[choice5].name}</div> ${b.guns[choice5].description}</div>`
|
||||
powerUps.gun.choiceLog.push(choice4)
|
||||
powerUps.gun.choiceLog.push(choice5)
|
||||
}
|
||||
|
||||
powerUps.gun.choiceLog.push(choice1)
|
||||
powerUps.gun.choiceLog.push(choice2)
|
||||
powerUps.gun.choiceLog.push(choice3)
|
||||
if (powerUps.reroll.rerolls) text += `<div class="choose-grid-module" onclick="powerUps.reroll.use('gun')"><div class="grid-title"><div class="circle-grid reroll"></div> reroll <span class='dice'>${powerUps.reroll.diceText()}</span></div></div>`
|
||||
|
||||
// console.log(powerUps.gun.choiceLog)
|
||||
// console.log(choice1, choice2, choice3)
|
||||
|
||||
document.getElementById("choose-grid").innerHTML = text
|
||||
powerUps.showDraft();
|
||||
} else {
|
||||
|
||||
@@ -1019,8 +1019,8 @@ const spawn = {
|
||||
vertexCollision(where, look, map);
|
||||
vertexCollision(where, look, body);
|
||||
if (!mech.isStealth) vertexCollision(where, look, [player]);
|
||||
if (best.who && best.who === player && mech.collisionImmuneCycle < mech.cycle) {
|
||||
mech.collisionImmuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
|
||||
if (best.who && best.who === player && mech.immuneCycle < mech.cycle) {
|
||||
mech.immuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
|
||||
const dmg = 0.14 * game.dmgScale;
|
||||
mech.damage(dmg);
|
||||
game.drawList.push({ //add dmg to draw queue
|
||||
@@ -1445,7 +1445,7 @@ const spawn = {
|
||||
// Matter.Body.rotate(me, Math.PI)
|
||||
|
||||
me.memory = 120;
|
||||
me.fireFreq = 0.006 + Math.random() * 0.003;
|
||||
me.fireFreq = 0.007 + Math.random() * 0.003;
|
||||
me.noseLength = 0;
|
||||
me.fireAngle = 0;
|
||||
me.accelMag = 0.0005 * game.accelScale;
|
||||
|
||||
20
todo.txt
20
todo.txt
@@ -1,20 +1,24 @@
|
||||
mod - many worlds: spawn a reroll after choosing (or canceling) a power up
|
||||
new mob type - launcher: similar to the shooter, but fires bullets that chase you
|
||||
plasma torch - reduces harm to player by 1/3 and has more reliable stopping power against charging mobs
|
||||
explosions and neutron bomb do 50% less damage through walls
|
||||
drone bullets bounce off mobs more predictably
|
||||
anthropic principle - now consumes 1 rerolls, and heals player to 50% health instead of letting them die
|
||||
many worlds - 66% chance for rerolls
|
||||
quantum immortality - also gives 3 rerolls
|
||||
mod drones - Brushless Motor: drones move faster
|
||||
mod drones - redundant systems: removed
|
||||
choices in power up selection should no longer repeat the previous choices when possible
|
||||
|
||||
************** TODO - n-gon **************
|
||||
|
||||
what about a neutron bomb mod, that cause the bomb to activate right after you fire and slowly move forward with no gravity
|
||||
bug - mines spawn extra mines when fired at thin map wall while jumping
|
||||
|
||||
Drop a reroll when the player exits the selection screen without picking one of the choices
|
||||
mod - negative mass field move faster
|
||||
less friction, more like flying?
|
||||
|
||||
what about a neutron bomb mod, that causes the bomb to activate right after you fire and slowly move forward with no gravity
|
||||
|
||||
redblobgames.com/articles/visibility
|
||||
https://github.com/Silverwolf90/2d-visibility/tree/master/src
|
||||
could apply to explosions, neutron bomb, player LOS
|
||||
|
||||
sticking bullets don't always gain the correct speed from mobs after they die
|
||||
bug - sticking bullets don't always gain the correct speed from mobs after they die
|
||||
|
||||
possible names for mods
|
||||
Hypergolic - A hypergolic propellant combination used in a rocket engine is one whose components spontaneously ignite when they come into contact with each other.
|
||||
|
||||
Reference in New Issue
Block a user