super determinism...

damage immunity after a collisions is reduced from 1/2s to 1/4s
freezing status effects only last 1/4 as long on boss mobs
mod - shotgun 66% increased fire rate and recoil
mod - slowly heal when below 25% health
mod - superdeterminism spawn 4 mods, but rerolls, fields, and guns no longer spawn
This commit is contained in:
landgreen
2020-06-21 19:14:01 -07:00
parent 6f503ff3c0
commit d1cb3aff15
11 changed files with 359 additions and 185 deletions

View File

@@ -467,17 +467,18 @@ const b = {
Matter.Body.setVelocity(bullet[bIndex], velocity);
World.add(engine.world, bullet[bIndex]); //add bullet to world
},
spore(who) { //used with the mod upgrade in mob.death()
spore(where, isFreeze = mod.isSporeFreeze) { //used with the mod upgrade in mob.death()
const bIndex = bullet.length;
const side = 4;
bullet[bIndex] = Bodies.polygon(who.position.x, who.position.y, 5, side, {
bullet[bIndex] = Bodies.polygon(where.x, where.y, 5, side, {
// density: 0.0015, //frictionAir: 0.01,
inertia: Infinity,
isFreeze: isFreeze,
restitution: 0.5,
angle: Math.random() * 2 * Math.PI,
friction: 0,
frictionAir: 0.025,
thrust: mod.isFastSpores ? 0.001 : 0.0004,
thrust: (mod.isFastSpores ? 0.001 : 0.0004) * (1 + 0.3 * (Math.random() - 0.5)),
dmg: mod.isMutualism ? 5.6 : 2.8, //2x bonus damage from mod.isMutualism
lookFrequency: 97 + Math.floor(117 * Math.random()),
classType: "bullet",
@@ -491,8 +492,9 @@ const b = {
x: 100 * (Math.random() - 0.5),
y: 100 * (Math.random() - 0.5)
},
onDmg() {
onDmg(who) {
this.endCycle = 0; //bullet ends cycle after doing damage
if (this.isFreeze) mobs.statusSlow(who, 60)
},
onEnd() {
if (mod.isMutualism && this.isMutualismActive && !mod.isEnergyHealth) {
@@ -503,39 +505,70 @@ const b = {
}
},
do() {
if (!(game.cycle % this.lookFrequency)) { //find mob targets
this.closestTarget = null;
this.lockedOn = null;
let closeDist = Infinity;
for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].dropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
// Matter.Query.ray(body, this.position, mob[i].position).length === 0
const targetVector = Vector.sub(this.position, mob[i].position)
const dist = Vector.magnitude(targetVector);
if (dist < closeDist) {
this.closestTarget = mob[i].position;
closeDist = dist;
this.lockedOn = mob[i] //Vector.normalise(targetVector);
if (0.3 > Math.random()) break //doesn't always target the closest mob
if (this.lockedOn && this.lockedOn.alive) {
this.force = Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), this.mass * this.thrust)
} else {
if (!(game.cycle % this.lookFrequency)) { //find mob targets
this.closestTarget = null;
this.lockedOn = null;
let closeDist = Infinity;
for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].dropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
const targetVector = Vector.sub(this.position, mob[i].position)
const dist = Vector.magnitude(targetVector) * (Math.random() + 0.5);
if (dist < closeDist) {
this.closestTarget = mob[i].position;
closeDist = dist;
this.lockedOn = mob[i]
if (0.3 > Math.random()) break //doesn't always target the closest mob
}
}
}
}
}
if (this.lockedOn && this.lockedOn.alive) { //accelerate towards mobs
this.force = Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), this.mass * this.thrust)
} else if (mod.isSporeFollow && this.lockedOn !== undefined) { //move towards player
//checking for undefined means that the spores don't go after the player until it has looked and not found a target
const dx = this.position.x - mech.pos.x;
const dy = this.position.y - mech.pos.y;
if (dx * dx + dy * dy > 10000) {
this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, Vector.add(this.playerOffPosition, this.position))), this.mass * this.thrust)
if (mod.isSporeFollow && this.lockedOn === null) { //move towards player
//checking for null means that the spores don't go after the player until it has looked and not found a target
const dx = this.position.x - mech.pos.x;
const dy = this.position.y - mech.pos.y;
if (dx * dx + dy * dy > 10000) {
this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, Vector.add(this.playerOffPosition, this.position))), this.mass * this.thrust)
}
} else {
this.force.y += this.mass * 0.0001; //gravity
}
// this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.thrust)
} else {
this.force.y += this.mass * 0.0001; //gravity
}
// if (!this.lockedOn && !(game.cycle % this.lookFrequency)) { //find mob targets
// this.closestTarget = null;
// this.lockedOn = null;
// let closeDist = Infinity;
// for (let i = 0, len = mob.length; i < len; ++i) {
// if (mob[i].dropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
// // Matter.Query.ray(body, this.position, mob[i].position).length === 0
// const targetVector = Vector.sub(this.position, mob[i].position)
// const dist = Vector.magnitude(targetVector);
// if (dist < closeDist) {
// this.closestTarget = mob[i].position;
// closeDist = dist;
// this.lockedOn = mob[i] //Vector.normalise(targetVector);
// if (0.3 > Math.random()) break //doesn't always target the closest mob
// }
// }
// }
// }
// if (this.lockedOn && this.lockedOn.alive) { //accelerate towards mobs
// this.force = Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), this.mass * this.thrust)
// } else if (mod.isSporeFollow && this.lockedOn !== undefined) { //move towards player
// //checking for undefined means that the spores don't go after the player until it has looked and not found a target
// const dx = this.position.x - mech.pos.x;
// const dy = this.position.y - mech.pos.y;
// if (dx * dx + dy * dy > 10000) {
// this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, Vector.add(this.playerOffPosition, this.position))), this.mass * this.thrust)
// }
// // this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.thrust)
// } else {
// this.force.y += this.mass * 0.0001; //gravity
// }
},
});
const SPEED = 4 + 8 * Math.random();
@@ -578,7 +611,7 @@ const b = {
onDmg(who) {
mobs.statusSlow(who, 60)
this.endCycle = game.cycle
if (mod.isAlphaRadiation) mobs.statusDoT(who, 0.1, 180)
if (mod.isHeavyWater) mobs.statusDoT(who, 0.1, 180)
},
onEnd() {},
do() {
@@ -1226,18 +1259,27 @@ const b = {
fire() {
let knock, spread
if (mech.crouch) {
spread = 0.75
mech.fireCDcycle = mech.cycle + Math.floor(55 * b.fireCD); // cool down
if (mod.isShotgunImmune) mech.immuneCycle = mech.cycle + Math.floor(58 * b.fireCD); //player is immune to collision damage for 30 cycles
spread = 0.75
knock = 0.01 * mod.bulletSize * mod.bulletSize
knock = 0.01
} else {
mech.fireCDcycle = mech.cycle + Math.floor(45 * b.fireCD); // cool down
if (mod.isShotgunImmune) mech.immuneCycle = mech.cycle + Math.floor(47 * b.fireCD); //player is immune to collision damage for 30 cycles
spread = 1.3
knock = 0.08 * mod.bulletSize * mod.bulletSize
knock = 0.08
}
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 (mod.isShotgunRecoil) {
mech.fireCDcycle -= 15
player.force.x -= 2 * knock * Math.cos(mech.angle)
player.force.y -= 2 * knock * Math.sin(mech.angle) //reduce knock back in vertical direction to stop super jumps
} else {
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
}
b.muzzleFlash(35);
if (mod.isNailShot) {
@@ -2142,7 +2184,7 @@ const b = {
bullet[me].onEnd = function () {
const NUM = 10
for (let i = 0; i < NUM; i++) {
b.spore(this)
b.spore(this.position)
}
}
}
@@ -2669,10 +2711,20 @@ const b = {
}
//use energy to explode
const energy = 0.3 * Math.min(mech.energy, 1.75)
mech.energy -= energy * mod.isLaserDiode
if (best.who) b.explosion(path[1], 1000 * energy, true)
mech.fireCDcycle = mech.cycle + Math.floor(50 * b.fireCD); // cool down
let energy;
if (mod.isRapidPulse) {
energy = 0.02 + 0.06 * Math.min(mech.energy, 1.75)
if (mech.energy < energy) return
mech.energy -= energy * mod.isLaserDiode
if (best.who) b.explosion(path[1], 2000 * energy, true)
mech.fireCDcycle = mech.cycle + Math.floor(15 * b.fireCD); // cool down
} else {
energy = 0.3 * Math.min(mech.energy, 1.75)
mech.energy -= energy * mod.isLaserDiode
if (best.who) b.explosion(path[1], 1000 * energy, true)
mech.fireCDcycle = mech.cycle + Math.floor(50 * b.fireCD); // cool down
}
if (mod.isPulseStun) {
const range = 100 + 2000 * energy

View File

@@ -205,13 +205,9 @@ function collisionChecks(event) {
if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) {
// const dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)));
let dmg = b.dmgScale * (obj.dmg + mod.acidDmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)))
// console.log(obj.dmg, 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)))
// console.log(obj.dmg / (0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity))))
if (mod.isCrit && !mob[k].seePlayer.recall && !mob[k].shield) dmg *= 5
mob[k].foundPlayer();
console.log(dmg)
mob[k].damage(dmg);
// console.log(dmg)
obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn
game.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x,

View File

@@ -771,6 +771,12 @@ const game = {
if (mod.isHealthRecovery) mech.addHealth(0.01)
}
if (mod.isHealLowHealth) {
if (mech.health < mech.maxHealth * 0.25) {
mech.addHealth(0.01 * mech.maxHealth)
}
}
if (!(game.cycle % 420)) { //once every 7 seconds
fallCheck = function (who, save = false) {
let i = who.length;

View File

@@ -81,7 +81,7 @@ const build = {
<br>${mob.length} mobs, &nbsp; ${body.length} blocks, &nbsp; ${bullet.length} bullets, &nbsp; ${powerUp.length} power ups
<br>mouse: (${game.mouseInGame.x.toFixed(1)}, ${game.mouseInGame.y.toFixed(1)}) &nbsp; ${mech.cycle} cycles
<br>
<br>health: ${(mech.health*100).toFixed(0)}% &nbsp; energy: ${(mech.energy*100).toFixed(0)}% &nbsp;
<br>health: (${(mech.health*100).toFixed(0)} / ${(mech.maxHealth*100).toFixed(0)}) &nbsp; energy: (${(mech.energy*100).toFixed(0)} / ${(mech.maxEnergy*100).toFixed(0)})
<br>mass: ${player.mass.toFixed(1)} &nbsp; rerolls: ${powerUps.reroll.rerolls}
<br>position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)}) &nbsp; velocity: (${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)})
<br>

View File

@@ -16,14 +16,10 @@ const level = {
if (level.levelsCleared === 0) { //this code only runs on the first level
// game.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(9)
// mech.setField("time dilation field")
// mod.giveMod("logistics");
// mod.giveMod("negative temperature");
// b.giveGuns("flechettes")
mod.giveMod("automatic shotgun");
// b.giveGuns("spores")
// mech.setField("negative mass field")
// mech.setField("phase decoherence field")
// mech.setField("plasma torch")
level.intro(); //starting level
// level.testing();
@@ -58,8 +54,8 @@ const level = {
}
if (mod.isArmorFromPowerUps) {
// for (let i = 0; i < powerUps.totalPowerUps; i++) {}
mech.maxHealth += 0.03 * powerUps.totalPowerUps
game.makeTextLog("<span style='font-size:115%;'> max health increased by " + (0.05 * powerUps.totalPowerUps * 100).toFixed(0) + "%</span>", 300)
mech.maxHealth += 0.04 * powerUps.totalPowerUps
if (powerUps.totalPowerUps) game.makeTextLog("<span style='font-size:115%;'> max health increased by " + (0.04 * powerUps.totalPowerUps * 100).toFixed(0) + "%</span>", 300)
}
},
isBuildRun: false,
@@ -135,7 +131,7 @@ const level = {
//******************************************************************************************************************
testing() {
level.difficultyIncrease(14); //hard mode level 7
// level.difficultyIncrease(14); //hard mode level 7
spawn.setSpawnList();
spawn.setSpawnList();
level.defaultZoom = 1500
@@ -193,9 +189,10 @@ const level = {
// spawn.launcherBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400)
// spawn.spawner(1600, -500)
spawn.sniper(1700, -120, 50)
// spawn.sniper(1600, -120)
// spawn.sniper(1800, -120)
// spawn.sniper(1700, -120, 50)
spawn.sniper(1400, -120)
spawn.sniper(1800, -120)
spawn.sniper(2200, -120)
// spawn.cellBossCulture(1600, -500)
// spawn.shooter(1600, -500)
// spawn.striker(1600, -500)

View File

@@ -45,6 +45,9 @@ const mobs = {
},
statusSlow(who, cycles = 60) {
if (!who.shield && !who.isShielded && !mech.isBodiesAsleep) {
if (who.isBoss) {
cycles = Math.floor(cycles * 0.25)
}
//remove other "slow" effects on this mob
let i = who.status.length
while (i--) {
@@ -993,7 +996,7 @@ const mobs = {
if (Math.random() < mod.sporesOnDeath) {
const len = Math.min(30, Math.floor(4 + this.mass * Math.random()))
for (let i = 0; i < len; i++) {
b.spore(this) //spawn drone
b.spore(this.position)
}
}
if (Math.random() < mod.isBotSpawner) {

View File

@@ -245,14 +245,14 @@ const mod = {
},
{
name: "electrostatic shots",
description: "<strong>33%</strong> increased <strong class='color-d'>damage</strong><br><strong>33%</strong> increased <strong>delay</strong> after firing",
description: "<strong>25%</strong> increased <strong class='color-d'>damage</strong><br><strong>25%</strong> increased <strong>delay</strong> after firing",
maxCount: 1,
count: 0,
allowed() {
return true
},
effect() {
mod.slowFire = 1.33
mod.slowFire = 1.25
b.setFireCD();
},
remove() {
@@ -431,7 +431,7 @@ const mod = {
effect() {
mod.sporesOnDeath += 0.11;
for (let i = 0; i < 10; i++) {
b.spore(player)
b.spore(mech.pos)
}
},
remove() {
@@ -552,7 +552,7 @@ const mod = {
mech.immuneCycle = mech.cycle + mod.collisionImmuneCycles; //player is immune to collision damage for 30 cycles
},
remove() {
mod.collisionImmuneCycles = 30;
mod.collisionImmuneCycles = 15;
}
},
{
@@ -720,6 +720,38 @@ const mod = {
mech.displayHealth();
}
},
{
name: "negentropy",
description: "when below <strong>25%</strong> of <strong>maximum health</strong><br> <strong class='color-h'>heal</strong> <strong>1%</strong> of <strong>maximum health</strong> per second",
maxCount: 9,
count: 0,
allowed() {
return mech.maxHealth > 1
},
requires: "increased max health",
effect() {
mod.isHealLowHealth = true;
},
remove() {
mod.isHealLowHealth = false;
}
},
{
name: "crystallized armor",
description: "increase <strong>maximum</strong> <strong class='color-h'>health</strong> by <strong>4%</strong> for each<br>unused <strong>power up</strong> at the end of a <strong>level</strong>",
maxCount: 1,
count: 0,
allowed() {
return !mod.isEnergyHealth
},
requires: "not mass-energy equivalence",
effect() {
mod.isArmorFromPowerUps = true;
},
remove() {
mod.isArmorFromPowerUps = false;
}
},
{
name: "recursive healing",
description: "<strong class='color-h'>healing</strong> <strong>power ups</strong> trigger <strong>+1</strong> more time",
@@ -736,22 +768,6 @@ const mod = {
mod.recursiveHealing = 1;
}
},
{
name: "crystallized armor",
description: "increase <strong>maximum</strong> <strong class='color-h'>health</strong> by <strong>3%</strong> for each<br>unused <strong>power up</strong> at the end of a <strong>level</strong>",
maxCount: 1,
count: 0,
allowed() {
return !mod.isEnergyHealth
},
requires: "not mass-energy equivalence",
effect() {
mod.isArmorFromPowerUps = true;
},
remove() {
mod.isArmorFromPowerUps = false;
}
},
{
name: "pair production",
description: "<strong>power ups</strong> overfill your <strong class='color-f'>energy</strong><br>temporarily gain <strong>twice</strong> your max <strong class='color-f'>energy</strong>",
@@ -787,13 +803,13 @@ const mod = {
},
{
name: "logistics",
description: "<strong>ammo</strong> power ups <strong>add</strong> to your current <strong>gun</strong><br>spawn <strong>4 ammo</strong>",
description: "<strong>ammo</strong> power ups add to your <strong>current gun</strong><br>spawn <strong>4 ammo</strong>",
maxCount: 1,
count: 0,
allowed() {
return true
return b.inventory.length > 1
},
requires: "",
requires: "at least 2 guns",
effect() {
mod.isAmmoForGun = true;
for (let i = 0; i < 4; i++) {
@@ -858,6 +874,7 @@ const mod = {
description: "spawn <strong>5</strong> <strong class='color-m'>mods</strong><br><strong>power ups</strong> are limited to <strong>one choice</strong>",
maxCount: 1,
count: 0,
isNonRefundable: true,
allowed() {
return !mod.isExtraChoice
},
@@ -873,15 +890,36 @@ const mod = {
mod.isDeterminism = false;
}
},
{
name: "superdeterminism",
description: "spawn <strong>4</strong> <strong class='color-m'>mods</strong><br><strong class='color-r'>rerolls</strong>, <strong>guns</strong>, and <strong>fields</strong> will no longer <strong>spawn</strong>",
maxCount: 1,
count: 0,
isNonRefundable: true,
allowed() {
return mod.isDeterminism && !mod.manyWorlds
},
requires: "determinism",
effect: () => {
mod.isSuperDeterminism = true;
for (let i = 0; i < 4; i++) { //if you change the six also change it in Born rule
powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
if (Math.random() < mod.bayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
}
},
remove() {
mod.isSuperDeterminism = false;
}
},
{
name: "many-worlds",
description: "after choosing a <strong>gun</strong>, <strong>field</strong>, or <strong class='color-m'>mod</strong><br>spawn a <strong class='color-r'>reroll</strong>, if you have none",
maxCount: 1,
count: 0,
allowed() {
return true
return !mod.isSuperDeterminism
},
requires: "",
requires: "not superdeterminism",
effect: () => {
mod.manyWorlds = true;
},
@@ -947,7 +985,9 @@ const mod = {
for (let i = 0, len = mod.mods.length; i < len; i++) { // spawn new mods power ups
if (!mod.mods[i].isNonRefundable) count += mod.mods[i].count
}
if (mod.isDeterminism) count -= 5 //remove the 5 bonus mods when getting rid of determinism
if (mod.isDeterminism) count -= 3 //remove the bonus mods
if (mod.isSuperDeterminism) count -= 2 //remove the bonus mods
mod.setupAllMods(); // remove all mods
for (let i = 0; i < count; i++) { // spawn new mods power ups
powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
@@ -963,7 +1003,7 @@ const mod = {
count: 0,
isNonRefundable: true,
allowed() {
return (mod.totalCount > 0) && !build.isCustomSelection
return (mod.totalCount > 0) && !build.isCustomSelection && !mod.isSuperDeterminism
},
requires: "at least 1 mod",
effect: () => {
@@ -1121,6 +1161,22 @@ const mod = {
mod.isNailShot = false;
}
},
{
name: "automatic shotgun",
description: "the <strong>shotgun</strong> fires <strong>66%</strong> faster<br><strong>recoil</strong> is greatly increased",
maxCount: 1,
count: 0,
allowed() {
return mod.haveGunCheck("shotgun")
},
requires: "shotgun",
effect() {
mod.isShotgunRecoil = true;
},
remove() {
mod.isShotgunRecoil = false;
}
},
{
name: "super duper",
description: "fire <strong>+2</strong> additional <strong>super balls</strong>",
@@ -1187,7 +1243,7 @@ const mod = {
},
{
name: "6s half-life",
description: "<strong>needles</strong> are exposed to <strong class='color-p'>plutonium-238</strong><br><strong>2x</strong> <strong class='color-d'>damage</strong> spread over <strong>6</strong> seconds",
description: "<strong>flechette</strong> needles made of <strong class='color-p'>plutonium-238</strong><br><strong>2x</strong> <strong class='color-d'>damage</strong> spread over <strong>6</strong> seconds",
maxCount: 1,
count: 0,
allowed() {
@@ -1203,7 +1259,7 @@ const mod = {
},
{
name: "1/2s half-life",
description: "<strong>needles</strong> are exposed to <strong class='color-p'>lithium-8</strong><br>flechette <strong class='color-d'>damage</strong> occurs after <strong>1/2</strong> a second",
description: "<strong>flechette</strong> needles made of <strong class='color-p'>lithium-8</strong><br>flechette <strong class='color-d'>damage</strong> occurs after <strong>1/2</strong> a second",
maxCount: 1,
count: 0,
allowed() {
@@ -1259,7 +1315,7 @@ const mod = {
},
requires: "wave beam",
effect() {
mod.waveSpeedMap = 3 //needs to be 3 for pocket universe require check
mod.waveSpeedMap = 3 //needs to be 3 to stop bound state require check
mod.waveSpeedBody = 1.9
},
remove() {
@@ -1268,8 +1324,8 @@ const mod = {
}
},
{
name: "pocket universe",
description: "<strong>wave beam</strong> bullets last <strong>5x</strong> longer<br>bullets are <strong>confined</strong> to a <strong>region</strong> around player",
name: "bound state",
description: "<strong>wave beam</strong> bullets last <strong>5x</strong> longer<br>bullets are <strong>bound</strong> to a <strong>region</strong> around player",
maxCount: 1,
count: 0,
allowed() {
@@ -1385,7 +1441,7 @@ const mod = {
},
{
name: "rocket-propelled grenade",
description: "<strong>grenades</strong> are rapidly <strong>accelerated</strong> forward<br>map <strong>collisions</strong> trigger an <strong class='color-e'>explosion</strong>",
description: "<strong>grenades</strong> rapidly <strong>accelerate</strong> forward<br>map <strong>collisions</strong> trigger an <strong class='color-e'>explosion</strong>",
maxCount: 1,
count: 0,
allowed() {
@@ -1527,6 +1583,23 @@ const mod = {
mod.isMutualism = false
}
},
{
name: "cryodesiccation",
description: "<strong class='color-p' style='letter-spacing: 2px;'>spores</strong> <strong class='color-s'>freeze</strong> mobs for <strong>1</strong> second",
// <br><strong class='color-p' style='letter-spacing: 2px;'>spores</strong> do <strong>1/3</strong> <strong class='color-d'>damage</strong>
maxCount: 1,
count: 0,
allowed() {
return mod.haveGunCheck("spores") || mod.sporesOnDeath > 0 || mod.isSporeField
},
requires: "spores",
effect() {
mod.isSporeFreeze = true
},
remove() {
mod.isSporeFreeze = false
}
},
{
name: "brushless motor",
description: "<strong>drones</strong> accelerate <strong>50%</strong> faster",
@@ -1545,7 +1618,7 @@ const mod = {
},
{
name: "heavy water",
description: "<strong>ice IX</strong> is synthesized with unstable isotopes<br>does <strong class='color-p'>radioactive</strong> <strong class='color-d'>damage</strong> over 3 seconds",
description: "<strong>ice IX</strong> is synthesized with an extra neutron<br>does <strong class='color-p'>radioactive</strong> <strong class='color-d'>damage</strong> over 3 seconds",
maxCount: 1,
count: 0,
allowed() {
@@ -1553,15 +1626,15 @@ const mod = {
},
requires: "ice IX",
effect() {
mod.isAlphaRadiation = true
mod.isHeavyWater = true
},
remove() {
mod.isAlphaRadiation = false;
mod.isHeavyWater = false;
}
},
{
name: "necrophoresis",
description: "<strong>foam</strong> splits into 3 <strong>copies</strong><br>when the mob it is stuck to <strong>dies</strong>",
description: "<strong>foam</strong> splits into 3 <strong>copies</strong><br>when the mob it's stuck to <strong>dies</strong>",
maxCount: 1,
count: 0,
allowed() {
@@ -1644,6 +1717,38 @@ const mod = {
mod.isPulseStun = false;
}
},
// {
// name: "aim",
// description: "<strong>pulse</strong> <strong class='color-e'>explosions</strong> aim",
// maxCount: 1,
// count: 0,
// allowed() {
// return mod.haveGunCheck("pulse")
// },
// requires: "pulse",
// effect() {
// mod.isPulseAim = true;
// },
// remove() {
// mod.isPulseAim = false;
// }
// },
// {
// name: "fast ignition",
// description: "<strong>pulse</strong> <strong class='color-e'>explosions</strong> more <strong>efficient</strong><br><strong>delay</strong> after firing is <strong>shorter</strong>",
// maxCount: 1,
// count: 0,
// allowed() {
// return mod.haveGunCheck("pulse")
// },
// requires: "pulse",
// effect() {
// mod.isRapidPulse = true;
// },
// remove() {
// mod.isRapidPulse = false;
// }
// },
//**************************************************
//************************************************** field
//************************************************** mods
@@ -1772,7 +1877,7 @@ const mod = {
},
{
name: "bremsstrahlung radiation",
description: "<strong>blocking</strong> with your field does <strong class='color-d'>damage</strong>",
description: "<strong>blocking</strong> with <strong>standing wave harmonics</strong><br> does <strong class='color-d'>damage</strong> to mobs",
maxCount: 9,
count: 0,
allowed() {
@@ -1945,9 +2050,9 @@ const mod = {
count: 0,
isNonRefundable: true,
allowed() {
return true
return !mod.isSuperDeterminism
},
requires: "",
requires: "not superdeterminism",
effect() {
for (let i = 0; i < 6; i++) {
powerUps.spawn(mech.pos.x, mech.pos.y, "reroll");
@@ -1963,9 +2068,9 @@ const mod = {
count: 0,
isNonRefundable: true,
allowed() {
return true
return !mod.isSuperDeterminism
},
requires: "",
requires: "not superdeterminism",
effect() {
powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
if (Math.random() < mod.bayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
@@ -1979,9 +2084,9 @@ const mod = {
count: 0,
isNonRefundable: true,
allowed() {
return true
return !mod.isSuperDeterminism
},
requires: "",
requires: "not superdeterminism",
effect() {
powerUps.spawn(mech.pos.x, mech.pos.y, "field");
if (Math.random() < mod.bayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "field");
@@ -2050,7 +2155,7 @@ const mod = {
isBlockStun: null,
isStunField: null,
isHarmDamage: null,
isAlphaRadiation: null,
isHeavyWater: null,
energyRegen: null,
isVacuumShield: null,
renormalization: null,
@@ -2067,6 +2172,7 @@ const mod = {
isRPG: null,
is3Missiles: null,
isDeterminism: null,
isSuperDeterminism: null,
isHarmReduce: null,
nailsDeathMob: null,
isSlowFPS: null,
@@ -2081,5 +2187,10 @@ const mod = {
fastTimeJump: null,
isFastDot: null,
isArmorFromPowerUps: null,
isAmmoForGun: null
isAmmoForGun: null,
isRapidPulse: null,
// isPulseAim: null,
isSporeFreeze: null,
isShotgunRecoil: null,
isHealLowHealth: null
}

View File

@@ -219,17 +219,6 @@ const mech = {
mech.doCrouch();
mech.yOff = mech.yOffWhen.jump;
mech.hardLandCD = mech.cycle + Math.min(momentum / 6.5 - 6, 40)
// if (mod.isStomp) {
// const len = Math.min(25, (momentum - 120) * 0.1)
// for (let i = 0; i < len; i++) {
// b.spore(player) //spawn drone
// }
// } else if (player.velocity.y > 27 && momentum > 180 * mod.squirrelFx) { //falling damage
// let dmg = Math.sqrt(momentum - 180) * 0.01
// dmg = Math.min(Math.max(dmg, 0.02), 0.20);
// mech.damage(dmg);
// }
} else {
mech.yOffGoal = mech.yOffWhen.stand;
}
@@ -316,8 +305,11 @@ const mech = {
//count mods
let totalMods = 0;
for (let i = 0; i < mod.mods.length; i++) {
totalMods += mod.mods[i].count
if (!mod.mods[i].isNonRefundable) totalMods += mod.mods[i].count
}
if (mod.isDeterminism) totalMods -= 3 //remove the bonus mods
if (mod.isSuperDeterminism) totalMods -= 2 //remove the bonus mods
const totalGuns = b.inventory.length //count guns
function randomizeMods() {
@@ -328,7 +320,6 @@ const mech = {
if (mod.mods[i].count < mod.mods[i].maxCount &&
!mod.mods[i].isNonRefundable &&
mod.mods[i].name !== "quantum immortality" &&
mod.mods[i].name !== "determinism" &&
mod.mods[i].allowed()
) options.push(i);
}
@@ -1335,7 +1326,7 @@ const mech = {
const len = Math.floor(6 + 4 * Math.random())
mech.energy -= len * 0.074;
for (let i = 0; i < len; i++) {
b.spore(player)
b.spore(mech.pos)
}
} else if (mod.isMissileField) {
// mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones
@@ -1506,9 +1497,8 @@ const mech = {
name: "plasma torch",
description: "use <strong class='color-f'>energy</strong> to emit short range plasma<br>plasma <strong class='color-d'>damages</strong> and <strong>pushes</strong> mobs",
isEasyToAim: false,
effect: () => {
effect() {
mech.fieldMeterColor = "#f0f"
mech.hold = function () {
if (mech.isHolding) {
mech.drawHold(mech.holdingTarget);
@@ -1607,13 +1597,6 @@ const mech = {
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);
// Matter.Body.setVelocity(best.who, {
// x: best.who.velocity.x * 0.85 - 3 * Math.cos(angle) / mass,
// y: best.who.velocity.y * 0.85 - 3 * Math.sin(angle) / mass
// });
//draw mob damage circle
game.drawList.push({
x: path[1].x,
@@ -1648,7 +1631,6 @@ const mech = {
ctx.beginPath();
ctx.moveTo(x, y);
const step = Vector.magnitude(Vector.sub(path[0], path[1])) / 10
for (let i = 0; i < 8; i++) {
x += step * (Dx + 1.5 * (Math.random() - 0.5))
y += step * (Dy + 1.5 * (Math.random() - 0.5))
@@ -1656,12 +1638,6 @@ const mech = {
}
ctx.lineWidth = 2 * Math.random();
ctx.stroke();
//draw shield around player
// ctx.beginPath();
// ctx.arc(mech.pos.x, mech.pos.y, mech.fieldRange * 0.75, 0, 2 * Math.PI);
// ctx.fillStyle = "rgba(255,0,255,0.05)"
// ctx.fill();
// mech.pushBody360(100); //disabled because doesn't work at short range
}
} else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
mech.pickUp();
@@ -1669,6 +1645,7 @@ const mech = {
mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
}
mech.drawFieldMeter("rgba(0, 0, 0, 0.2)")
}
}
},

View File

@@ -475,35 +475,35 @@ const powerUps = {
}
},
spawn(x, y, target, moving = true, mode = null) {
// if (!level.isBuildRun || target === "heal" || target === "ammo") {
let index = powerUp.length;
target = powerUps[target];
size = target.size();
powerUp[index] = Matter.Bodies.polygon(x, y, 0, size, {
density: 0.001,
frictionAir: 0.01,
restitution: 0.8,
inertia: Infinity, //prevents rotation
collisionFilter: {
group: 0,
category: cat.powerUp,
mask: cat.map | cat.powerUp
},
color: target.color,
effect: target.effect,
name: target.name,
size: size
});
if (mode) {
powerUp[index].mode = mode
}
if (moving) {
Matter.Body.setVelocity(powerUp[index], {
x: (Math.random() - 0.5) * 15,
y: Math.random() * -9 - 3
if (!(mod.isSuperDeterminism && (target === 'gun' || target === 'field' || target === 'reroll'))) {
let index = powerUp.length;
target = powerUps[target];
size = target.size();
powerUp[index] = Matter.Bodies.polygon(x, y, 0, size, {
density: 0.001,
frictionAir: 0.01,
restitution: 0.8,
inertia: Infinity, //prevents rotation
collisionFilter: {
group: 0,
category: cat.powerUp,
mask: cat.map | cat.powerUp
},
color: target.color,
effect: target.effect,
name: target.name,
size: size
});
if (mode) {
powerUp[index].mode = mode
}
if (moving) {
Matter.Body.setVelocity(powerUp[index], {
x: (Math.random() - 0.5) * 15,
y: Math.random() * -9 - 3
});
}
World.add(engine.world, powerUp[index]); //add to world
}
World.add(engine.world, powerUp[index]); //add to world
// }
},
};

View File

@@ -159,6 +159,7 @@ const spawn = {
cellBoss(x, y, radius = 20) {
mobs.spawn(x + Math.random(), y + Math.random(), 20, radius * (1 + 1.2 * Math.random()), "rgba(0,150,155,0.7)");
let me = mob[mob.length - 1];
me.isBoss = true;
me.isCell = true;
me.accelMag = 0.00015 * game.accelScale;
me.memory = 40;
@@ -214,11 +215,12 @@ const spawn = {
}
};
me.onDeath = function () {
this.isCell = false;
let count = 0 //count other cells
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].isCell) count++
}
if (count === 1) { //only drop a power up if this is the last cell
if (count < 1) { //only drop a power up if this is the last cell
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
} else {
this.leaveBody = false;
@@ -553,6 +555,7 @@ const spawn = {
suckerBoss(x, y, radius = 25) {
mobs.spawn(x, y, 12, radius, "#000");
let me = mob[mob.length - 1];
me.isBoss = true;
me.stroke = "transparent"; //used for drawSneaker
me.eventHorizon = 1100; //required for black hole
me.seeAtDistance2 = (me.eventHorizon + 1000) * (me.eventHorizon + 1000); //vision limit is event horizon
@@ -653,6 +656,7 @@ const spawn = {
let targets = [] //track who is in the node boss, for shields
mobs.spawn(x, y, 6, radius, "#b386e8");
let me = mob[mob.length - 1];
me.isBoss = true;
targets.push(me.id) //add to shield protection
me.friction = 0;
me.frictionAir = 0.0065;
@@ -732,6 +736,7 @@ const spawn = {
timeSkipBoss(x, y, radius = 55) {
mobs.spawn(x, y, 6, radius, '#000');
let me = mob[mob.length - 1];
me.isBoss = true;
// me.stroke = "transparent"; //used for drawSneaker
me.timeSkipLastCycle = 0
me.eventHorizon = 1800; //required for black hole
@@ -896,6 +901,7 @@ const spawn = {
const color = "#05f"
mobs.spawn(x, y, 3, radius, color);
let me = mob[mob.length - 1];
me.isBoss = true;
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
me.accelMag = 0.0005 * game.accelScale;
@@ -1054,6 +1060,7 @@ const spawn = {
laserBoss(x, y, radius = 30) {
mobs.spawn(x, y, 3, radius, "#f00");
let me = mob[mob.length - 1];
me.isBoss = true;
me.startingPosition = {
x: x,
y: y
@@ -1463,6 +1470,7 @@ const spawn = {
//boss that drops bombs from above and holds a set distance from player
mobs.spawn(x, y, 3, radius, "transparent");
let me = mob[mob.length - 1];
me.isBoss = true;
Matter.Body.setDensity(me, 0.0015 + 0.0004 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.stroke = "rgba(255,0,200)"; //used for drawGhost
@@ -1527,6 +1535,7 @@ const spawn = {
shooterBoss(x, y, radius = 130) {
mobs.spawn(x, y, 3, radius, "rgb(255,70,180)");
let me = mob[mob.length - 1];
me.isBoss = true;
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
me.isVerticesChange = true
me.memory = 240;
@@ -1739,7 +1748,7 @@ const spawn = {
this.seePlayerCheck();
this.checkStatus();
this.attraction();
if (this.seePlayer.recall && !(game.cycle % this.fireFreq)) {
if (this.seePlayer.recall && !(game.cycle % this.fireFreq) && !mech.isBodiesAsleep) {
Matter.Body.setAngularVelocity(this, 0.14)
//fire a bullet from each vertex
for (let i = 0, len = this.vertices.length; i < len; i++) {
@@ -1757,6 +1766,7 @@ const spawn = {
launcherBoss(x, y, radius = 90) {
mobs.spawn(x, y, 6, radius, "rgb(150,150,255)");
let me = mob[mob.length - 1];
me.isBoss = true;
me.accelMag = 0.00008 * game.accelScale;
me.fireFreq = Math.floor(330 * game.CDScale)
me.frictionStatic = 0;
@@ -1776,7 +1786,7 @@ const spawn = {
this.checkStatus();
this.attraction();
this.repulsion();
if (this.seePlayer.recall && !(game.cycle % this.fireFreq)) {
if (this.seePlayer.recall && !(game.cycle % this.fireFreq) && !mech.isBodiesAsleep) {
Matter.Body.setAngularVelocity(this, 0.11)
//fire a bullet from each vertex
for (let i = 0, len = this.vertices.length; i < len; i++) {
@@ -1881,6 +1891,7 @@ const spawn = {
//snake boss with a laser head
mobs.spawn(x, y, 8, radius, "rgb(255,50,130)");
let me = mob[mob.length - 1];
me.isBoss = true;
me.accelMag = 0.0012 * game.accelScale;
me.memory = 200;
me.laserRange = 500;
@@ -1922,6 +1933,7 @@ const spawn = {
// often has a ring of mobs around it
mobs.spawn(x, y, 8, radius, "rgb(0,60,80)");
let me = mob[mob.length - 1];
me.isBoss = true;
me.g = 0.0001; //required if using 'gravity'
me.accelMag = 0.002 * game.accelScale;
me.memory = 20;

View File

@@ -1,25 +1,47 @@
added mods to spawn a gun, a field, and rerolls
added mod that gives max health for leftover power ups
this mod has some interesting interactions with other mods
mod annihilation now uses 20% of base energy and doesn't trigger damage immunity
mod Hawking radiation removed
mod negative temperature: freezed mobs in range of negative mass field, but drain energy
mod: logistics
ammo power ups are added to your current gun
spawn 4 ammo immediately
damage immunity after a collisions is reduced from 1/2s to 1/4s
freezing status effects only last 1/4 as long on boss mobs
mod - shotgun 66% increased fire rate and recoil
mod - slowly heal when below 25% health
mod - superdeterminism spawn 4 mods, but rerolls, fields, and guns no longer spawn
************** TODO - n-gon **************
physics question: why don't the bound states of fields spread out. What is making them bound.
very high speed projectile that checks for collisions in future positions to avoid tunneling
rework reaction inhibitor to spawn mobs with 12% less life, rather then killing them at 12%
mod: all mobs have a shield (or just a higher rate)
all mobs drop an extra ammo power up?
levels: make a function in the main game loop that runs level specific code
reset the level function as each new level loads
mod: foam grenades
or maybe all explosions make foam?
mod: use the stealth flag from the phase decoherence field
maybe trigger it along with the damage immunity CD
mod: efficient shielding (requires standing wave harmonics field)
lowers force applied when blocking mobs (instead of flinging them away, you push them like with plasma torch), but uses less energy to block mobs
and making it so liquid nitrogen and uranium reactor core have that effect in a radius around the player instead of on contact
the idea being that you're sacrificing defense and instead of flinging away mobs when they touch the field, you're letting them stay longer in your field so that they take more damage
mod harmonic shield: slow everything in range around shield (temporal shield)
set max speed?
need a mod that effects ice status
mod: ice status effect lasts twice as long
mod: bot very slowly follows you and gives you a bonus when it's in range
it moves through walls
effect: damage bonus?, damage reduction?, push away mobs, limit top speed of mobs/blocks/player?
pulse and laser can auto aim
can hit multiple targets if they are in range
make a visual indication of max health
mod: give a gun auto aiming
minigun?
ice status effect lasts twice as long
shrink font on small screens (so you can see 5 options on power ups)
graphic idea: bezier curve that moves smoothly from mob to mob
@@ -29,8 +51,6 @@ give rail gun projectile a trail
only draw above speed 5
track previous positions?
shielded mobs don't knock back the same as unshielded mobs
movement fluidity
let legs jump on mobs, but player will still take damage
like: ori and the blind forest, celeste