diff --git a/.DS_Store b/.DS_Store
index babae7a..f787002 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/js/bullet.js b/js/bullet.js
index 9728ed8..05c5a5e 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -1118,7 +1118,7 @@ const b = {
turnRate: isReturn ? 0.1 : 0.03, //0.015
drawStringControlMagnitude: 3000 + 5000 * Math.random(),
drawStringFlip: (Math.round(Math.random()) ? 1 : -1),
- dmg: 6, //damage done in addition to the damage from momentum
+ dmg: 7, //damage done in addition to the damage from momentum
classType: "bullet",
endCycle: simulation.cycle + totalCycles * 2.5 + 15,
collisionFilter: {
@@ -1133,10 +1133,9 @@ const b = {
who.isShielded = false
requestAnimationFrame(() => { who.isShielded = true });
}
+ if (tech.fragments) b.targetedNail(this.vertices[2], tech.fragments * 3)
if (!who.isBadTarget) {
- if (tech.fragments) {
- b.targetedNail(this.vertices[2], tech.fragments * 4)
- } else if (isReturn) {
+ if (isReturn) {
this.do = this.returnToPlayer
} else {
this.frictionAir = 0.01
@@ -1166,7 +1165,7 @@ const b = {
this.caughtPowerUp.effect();
Matter.Composite.remove(engine.world, this.caughtPowerUp);
powerUp.splice(index, 1);
- if (tech.isHarpoonPowerUp) tech.harpoonDensity = 0.006 * 6 //0.006 is normal
+ if (tech.isHarpoonPowerUp) tech.harpoonDensity = 0.008 * 6 //0.006 is normal
} else {
this.dropCaughtPowerUp()
}
@@ -1195,7 +1194,7 @@ const b = {
returnToPlayer() {
if (Vector.magnitude(Vector.sub(this.position, m.pos)) < returnRadius) { //near player
this.endCycle = 0;
- if (m.cycle + 25 * b.fireCDscale < m.fireCDcycle) m.fireCDcycle = m.cycle + 25 * b.fireCDscale //lower cd to 25 if it is above 25
+ if (m.cycle + 25 * b.fireCDscale < m.fireCDcycle) m.fireCDcycle = m.cycle + 35 * b.fireCDscale //lower cd to 25 if it is above 25
//recoil on catching
const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), this.mass * (input.down ? 0.0001 : 0.0002))
player.force.x += momentum.x
@@ -1364,6 +1363,48 @@ const b = {
this.force.y += this.mass * 0.001; //gravity
}
}
+
+ /* todo
+ despawn
+ when player gets far away?
+ set time
+ release mouse?
+
+ */
+ // if (true && input.down) {
+ // Matter.Body.setVelocity(bullet[me], {
+ // x: m.Vx / 2 + 70 * Math.cos(bullet[me].angle),
+ // y: m.Vy / 2 + 70 * Math.sin(bullet[me].angle)
+ // });
+ // bullet[me].frictionAir = 0.0011
+ // bullet[me].endCycle = simulation.cycle + Infinity
+ // bullet[me].do = function() {
+ // if (!m.isBodiesAsleep) {
+ // this.cycle++
+ // if (Matter.Query.collides(this, map).length) {
+ // // this.collisionFilter.mask = 0; //non collide with everything
+ // this.collisionFilter.category = cat.map
+ // this.collisionFilter.mask = cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet;
+
+ // Matter.Body.setPosition(this, Vector.add(this.position, Vector.mult(Vector.normalise(this.lastVelocity), 30))) //move a bit into the wall
+ // Matter.Body.setVelocity(this, { x: 0, y: 0 });
+ // Matter.Body.setStatic(this, true) //don't set to static if not touching map
+
+ // Matter.Body.setAngularVelocity(this, 0)
+ // const unit = Vector.normalise(Vector.sub({ x: this.position.x, y: this.position.y - 150 }, player.position))
+ // const push = Vector.mult(unit, 1)
+ // player.force.x += push.x
+ // player.force.y += push.y
+ // //pull player back in
+ // this.do = () => {
+
+ // }
+ // }
+ // this.lastVelocity = { x: this.velocity.x, y: this.velocity.y }
+ // }
+ // this.drawString()
+ // }
+ // }
Composite.add(engine.world, bullet[me]); //add bullet to world
},
missile(where, angle, speed, size = 1) {
@@ -2794,7 +2835,7 @@ const b = {
inertia: Infinity,
frictionAir: 0.003,
dmg: 0, //damage on impact
- damage: (tech.isFastFoam ? 0.039 : 0.011) * (tech.isBulletTeleport ? 1.43 : 1), //damage done over time
+ damage: (tech.isFastFoam ? 0.033 : 0.011) * (tech.isBulletTeleport ? 1.43 : 1), //damage done over time
scale: 1 - 0.006 / tech.isBulletsLastLonger * (tech.isFastFoam ? 1.65 : 1),
classType: "bullet",
collisionFilter: {
@@ -5102,7 +5143,7 @@ const b = {
}
}
b.harpoon(where, closest.target, m.angle, length, false, 15)
- m.fireCDcycle = m.cycle + 40 * b.fireCDscale; // cool down
+ m.fireCDcycle = m.cycle + 50 * b.fireCDscale; // cool down
} else if (tech.extraHarpoons) {
const range = 450 * (tech.isFilament ? 1 + Math.min(100, this.ammo) / 100 : 1)
let targetCount = 0
@@ -5144,7 +5185,7 @@ const b = {
const recoil = Vector.mult(Vector.normalise(Vector.sub(where, m.pos)), input.down ? 0.015 : 0.035)
player.force.x -= recoil.x
player.force.y -= recoil.y
- tech.harpoonDensity = 0.005
+ tech.harpoonDensity = 0.008
}
},
{
diff --git a/js/engine.js b/js/engine.js
index 3d213f3..1a1d97e 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -107,7 +107,7 @@ function collisionChecks(event) {
!(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.isBodiesAsleep || m.isCloak) dmg *= 0.5
+ 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);
diff --git a/js/level.js b/js/level.js
index a194bae..1e492ec 100644
--- a/js/level.js
+++ b/js/level.js
@@ -2300,11 +2300,11 @@ const level = {
// spawn.laserBombingBoss(1900, -500)
// for (let i = 0; i < 5; i++) spawn.focuser(1900, -500)
- // spawn.grenadier(1900, -500)
+ spawn.slasher(1900, -500)
// spawn.sneaker(1900, -500, 200)
// spawn.shield(mob[mob.length - 1], 1900, -500, 1);
// mob[mob.length - 1].isShielded = true
- // spawn.historyBoss(1200, -500)
+ // spawn.growBossCulture(1200, -500)
// spawn.laserTargetingBoss(1600, -400)
// spawn.focuser(1600, -500)
// spawn.laserTargetingBoss(1700, -120)
@@ -2313,7 +2313,7 @@ const level = {
// spawn.laserBombingBoss(1600, -500)
// spawn.laserTargetingBoss(1600, -500)
// spawn.laserBoss(1600, -500)
- spawn.cellBossCulture(1600, -500)
+ // spawn.cellBossCulture(1600, -500)
// spawn.nodeGroup(1200, -500, "grenadier")
// spawn.nodeGroup(1800, -500, "grenadier")
// spawn.nodeGroup(1200, 0, "grenadier")
@@ -4420,7 +4420,7 @@ const level = {
spawn.randomSmallMob(-900, 825);
if (simulation.difficulty > 1) {
- if (Math.random() < 0.33) {
+ if (Math.random() < 0.70) {
spawn.randomLevelBoss(-800, -1300)
} else {
spawn.snakeBoss(-1000 + Math.random() * 2500, -1300); //boss snake with head
diff --git a/js/mob.js b/js/mob.js
index 0c63e09..ace5981 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -1264,7 +1264,7 @@ const mobs = {
//if there are too many bodies don't turn into blocks to help performance
if (this.leaveBody && body.length < 40 && this.mass < 200 && this.radius > 18) {
let v = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //might help with vertex collision issue, not sure
- if (v.length > 5 && body.length < 35 && Math.random() < 0.5) {
+ if (v.length > 5 && body.length < 35 && Math.random() < 0.25) {
const cutPoint = 3 + Math.floor((v.length - 6) * Math.random()) //Math.floor(v.length / 2)
const v2 = v.slice(0, cutPoint + 1)
v = v.slice(cutPoint - 1)
diff --git a/js/player.js b/js/player.js
index c0977c2..7333ab4 100644
--- a/js/player.js
+++ b/js/player.js
@@ -1121,12 +1121,12 @@ const m = {
m.fieldCDcycle = m.cycle + 15;
m.isHolding = false;
- if (tech.isTokamak && m.throwCharge > 5) { //remove the block body and pulse in the direction you are facing
+ if (tech.isTokamak && m.throwCharge > 3) { //remove the block body and pulse in the direction you are facing
//m.throwCharge > 5 seems to be when the field full colors in a block you are holding
- m.throwCharge = 0;
m.throwCycle = m.cycle + 180 //used to detect if a block was thrown in the last 3 seconds
+ if (m.immuneCycle < m.cycle) m.energy += 0.25 * Math.sqrt(m.holdingTarget.mass) * Math.min(5, m.throwCharge)
+ m.throwCharge = 0;
m.definePlayerMass() //return to normal player mass
- if (m.immuneCycle < m.cycle) m.energy += 2.5 * Math.sqrt(m.holdingTarget.mass)
//remove block before pulse, so it doesn't get in the way
for (let i = 0; i < body.length; i++) {
if (body[i] === m.holdingTarget) {
@@ -1134,7 +1134,7 @@ const m = {
body.splice(i, 1);
}
}
- b.pulse(50 * Math.pow(m.holdingTarget.mass, 0.25), m.angle)
+ b.pulse(60 * Math.pow(m.holdingTarget.mass, 0.25), m.angle)
} else { //normal throw
//bullet-like collisions
m.holdingTarget.collisionFilter.category = cat.bullet
@@ -2027,7 +2027,8 @@ const m = {
},
{
name: "time dilation",
- description: "use energy to stop time
while time is stopped you can move and fire
and collisions do 50% less harm",
+ // description: "use energy to stop time
while time is stopped you can move and fire
and collisions do 50% less harm",
+ description: "use energy to stop time
move and fire while time is stopped
but, collisions still do harm",
effect: () => {
// m.fieldMeterColor = "#000"
m.fieldFire = true;
diff --git a/js/powerup.js b/js/powerup.js
index 40887f0..1b2ff89 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -463,54 +463,56 @@ const powerUps = {
return 17;
},
effect() {
- if (tech.isAmmoForGun && b.inventory.length > 0 && b.activeGun) { //give extra ammo to one gun only with tech logistics
- const target = b.guns[b.activeGun]
- if (target.ammo !== Infinity) {
- if (tech.ammoCap) {
- const ammoAdded = Math.ceil(target.ammoPack * 0.7 * tech.ammoCap) //0.7 is average
- target.ammo = ammoAdded
- simulation.makeTextLog(`${target.name}.ammo = ${ammoAdded}`)
- } else {
- const ammoAdded = Math.ceil((0.7 * Math.random() + 0.7 * Math.random()) * target.ammoPack)
- target.ammo += ammoAdded
- simulation.makeTextLog(`${target.name}.ammo += ${ammoAdded}`)
- }
- }
- } else { //give ammo to all guns in inventory
- let textLog = ""
- for (let i = 0, len = b.inventory.length; i < len; i++) {
- const target = b.guns[b.inventory[i]]
+ if (b.inventory.length > 0) {
+ if (tech.isAmmoForGun && b.activeGun) { //give extra ammo to one gun only with tech logistics
+ const target = b.guns[b.activeGun]
if (target.ammo !== Infinity) {
if (tech.ammoCap) {
- const ammoAdded = Math.ceil(target.ammoPack * 0.45 * tech.ammoCap) //0.45 is average
+ const ammoAdded = Math.ceil(target.ammoPack * 0.7 * tech.ammoCap) //0.7 is average
target.ammo = ammoAdded
- textLog += `${target.name}.ammo = ${ammoAdded}
`
+ simulation.makeTextLog(`${target.name}.ammo = ${ammoAdded}`)
} else {
- const ammoAdded = Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack) //Math.ceil(Math.random() * target.ammoPack)
+ const ammoAdded = Math.ceil((0.7 * Math.random() + 0.7 * Math.random()) * target.ammoPack)
target.ammo += ammoAdded
- textLog += `${target.name}.ammo += ${ammoAdded}
`
+ simulation.makeTextLog(`${target.name}.ammo += ${ammoAdded}`)
}
}
+ } else { //give ammo to all guns in inventory
+ let textLog = ""
+ for (let i = 0, len = b.inventory.length; i < len; i++) {
+ const target = b.guns[b.inventory[i]]
+ if (target.ammo !== Infinity) {
+ if (tech.ammoCap) {
+ const ammoAdded = Math.ceil(target.ammoPack * 0.45 * tech.ammoCap) //0.45 is average
+ target.ammo = ammoAdded
+ textLog += `${target.name}.ammo = ${ammoAdded}
`
+ } else {
+ const ammoAdded = Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack) //Math.ceil(Math.random() * target.ammoPack)
+ target.ammo += ammoAdded
+ textLog += `${target.name}.ammo += ${ammoAdded}
`
+ }
+ }
+ }
+ simulation.makeTextLog(textLog)
}
- simulation.makeTextLog(textLog)
+ // } else { //give ammo to all guns in inventory
+ // for (let i = 0, len = b.inventory.length; i < len; i++) {
+ // const target = b.guns[b.inventory[i]]
+ // if (target.ammo !== Infinity) {
+ // if (tech.ammoCap) {
+ // const ammoAdded = Math.ceil(target.ammoPack * 0.45 * tech.ammoCap) //0.45 is average
+ // target.ammo = ammoAdded
+ // simulation.makeTextLog(`${target.name}.ammo = ${ammoAdded}`)
+ // } else {
+ // const ammoAdded = Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack) //Math.ceil(Math.random() * target.ammoPack)
+ // target.ammo += ammoAdded
+ // simulation.makeTextLog(`${target.name}.ammo += ${ammoAdded}`)
+ // }
+ // }
+ // }
+ // }
+ simulation.updateGunHUD();
}
- // } else { //give ammo to all guns in inventory
- // for (let i = 0, len = b.inventory.length; i < len; i++) {
- // const target = b.guns[b.inventory[i]]
- // if (target.ammo !== Infinity) {
- // if (tech.ammoCap) {
- // const ammoAdded = Math.ceil(target.ammoPack * 0.45 * tech.ammoCap) //0.45 is average
- // target.ammo = ammoAdded
- // simulation.makeTextLog(`${target.name}.ammo = ${ammoAdded}`)
- // } else {
- // const ammoAdded = Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack) //Math.ceil(Math.random() * target.ammoPack)
- // target.ammo += ammoAdded
- // simulation.makeTextLog(`${target.name}.ammo += ${ammoAdded}`)
- // }
- // }
- // }
- // }
- simulation.updateGunHUD();
}
},
field: {
diff --git a/js/simulation.js b/js/simulation.js
index 0679ecd..9b3269d 100644
--- a/js/simulation.js
+++ b/js/simulation.js
@@ -261,7 +261,7 @@ const simulation = {
const bolts = []
colors = [powerUps.research.color, powerUps.ammo.color, powerUps.heal.color, powerUps.tech.color, powerUps.field.color, powerUps.gun.color]
for (let i = 0; i < boltNum; ++i) {
- const mag = 4 + 20 * Math.random()
+ const mag = 6 + 20 * Math.random()
const angle = 2 * Math.PI * Math.random()
bolts.push({
x: m.pos.x,
diff --git a/js/spawn.js b/js/spawn.js
index 3b53316..74bce3b 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -8,6 +8,7 @@ const spawn = {
pickList: ["starter", "starter"],
fullPickList: [
"hopper", "hopper", "hopper",
+ "slasher", "slasher",
"shooter", "shooter",
"grenadier", "grenadier",
"striker", "striker",
@@ -27,7 +28,7 @@ const spawn = {
"spawner",
"ghoster",
],
- allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "stabber", "sniper", "pulsar", "grenadier"],
+ allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "stabber", "sniper", "pulsar", "grenadier", "slasher"],
setSpawnList() { //this is run at the start of each new level to determine the possible mobs for the level
//each level has 2 mobs: one new mob and one from the last level
spawn.pickList.splice(0, 1);
@@ -1079,7 +1080,7 @@ const spawn = {
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body //| cat.map //"rgba(255,60,0,0.3)"
me.buffCount = 0
- me.accelMag = 0.00006 //* simulation.accelScale;
+ me.accelMag = 0.00005 //* simulation.accelScale;
me.setBuffed = function() {
this.buffCount++
this.accelMag += 0.000035 //* Math.sqrt(simulation.accelScale)
@@ -1104,10 +1105,11 @@ const spawn = {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
} else {
this.leaveBody = false;
- if (!count % 2) powerUps.spawnRandomPowerUp(this.position.x, this.position.y) // higher then normal chance to drop heals and ammo
+ this.isDropPowerUp = false;
+ powerUps.spawnRandomPowerUp(this.position.x, this.position.y) // manual power up spawn to avoid spawning too many tech with "symbiosis"
}
}
- me.damageReduction = 0.22
+ me.damageReduction = 0.18
me.do = function() {
// this.armor();
this.alwaysSeePlayer();
@@ -2910,6 +2912,117 @@ const spawn = {
}
};
},
+ slasher(x, y, radius = 36 + Math.ceil(Math.random() * 25)) {
+ mobs.spawn(x, y, 5, radius, "rgb(201,202,225)");
+ let me = mob[mob.length - 1];
+ Matter.Body.rotate(me, 2 * Math.PI * Math.random());
+ me.accelMag = 0.00085 * simulation.accelScale;
+ me.torqueMagnitude = 0.00002 * me.inertia * (Math.random() > 0.5 ? -1 : 1);
+ me.frictionStatic = 0;
+ me.friction = 0;
+ me.frictionAir = 0.035;
+ me.delay = 120 * simulation.CDScale;
+ me.cd = 0;
+ me.swordRadius = 0;
+ me.swordRadiusMax = 350 + 5 * simulation.difficulty;
+ me.swordRadiusGrowRate = me.swordRadiusMax * (0.02 + 0.0008 * simulation.difficulty)
+ me.isSlashing = false;
+ me.swordDamage = 0.07 * simulation.dmgScale
+ const laserAngle = 3 * Math.PI / 5
+ const seeDistance2 = 200000
+ spawn.shield(me, x, y);
+ me.onDamage = function() {};
+ me.do = function() {
+ this.checkStatus();
+ this.seePlayerByHistory(15);
+ this.attraction();
+ if (!m.isBodiesAsleep) this.sword() //does various things depending on what stage of the sword swing
+ };
+
+ me.swordWaiting = function() {
+ if (
+ this.seePlayer.recall &&
+ this.cd < simulation.cycle &&
+ this.distanceToPlayer2() < seeDistance2 &&
+ Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 &&
+ Matter.Query.ray(body, this.position, this.playerPosRandomY()).length === 0
+ ) {
+ this.sword = this.swordGrow
+ // Matter.Body.setVelocity(this, { x: 0, y: 0 });
+ this.accelMag = 0
+ }
+ }
+ me.sword = me.swordWaiting //base function that changes during different aspects of the sword swing
+ me.swordGrow = function() {
+ this.laserSword(this.vertices[1], this.angle + laserAngle);
+ this.swordRadius += this.swordRadiusGrowRate
+ if (this.swordRadius > this.swordRadiusMax) {
+ this.sword = this.swordSlash
+ this.spinCount = 0
+ }
+ }
+ me.swordSlash = function() {
+ this.laserSword(this.vertices[1], this.angle + laserAngle);
+ this.torque += this.torqueMagnitude;
+ this.spinCount++
+ if (this.spinCount > 60) {
+ this.sword = this.swordWaiting
+ this.swordRadius = 0
+ this.accelMag = 0.001 * simulation.accelScale;
+ this.cd = simulation.cycle + this.delay;
+ }
+ }
+ me.laserSword = function(where, angle) {
+ const vertexCollision = function(v1, v1End, domain) {
+ for (let i = 0; i < domain.length; ++i) {
+ let vertices = domain[i].vertices;
+ const len = vertices.length - 1;
+ for (let j = 0; j < len; j++) {
+ results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
+ if (results.onLine1 && results.onLine2) {
+ const dx = v1.x - results.x;
+ const dy = v1.y - results.y;
+ const dist2 = dx * dx + dy * dy;
+ if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: vertices[j], v2: vertices[j + 1] };
+ }
+ }
+ results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
+ if (results.onLine1 && results.onLine2) {
+ const dx = v1.x - results.x;
+ const dy = v1.y - results.y;
+ const dist2 = dx * dx + dy * dy;
+ if (dist2 < best.dist2) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: vertices[0], v2: vertices[len] };
+ }
+ }
+ };
+ best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
+ const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
+ vertexCollision(where, look, body); // vertexCollision(where, look, mob);
+ vertexCollision(where, look, map);
+ if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]);
+ if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
+ m.immuneCycle = m.cycle + tech.collisionImmuneCycles + 60; //player is immune to damage for an extra second
+ m.damage(this.swordDamage);
+ simulation.drawList.push({ //add dmg to draw queue
+ x: best.x,
+ y: best.y,
+ radius: this.swordDamage * 1500,
+ color: "rgba(80,0,255,0.5)",
+ time: 20
+ });
+ }
+ if (best.dist2 === Infinity) best = look;
+ ctx.beginPath(); //draw beam
+ ctx.moveTo(where.x, where.y);
+ ctx.lineTo(best.x, best.y);
+ ctx.strokeStyle = "rgba(100,100,255,0.1)"; // Purple path
+ ctx.lineWidth = 15;
+ ctx.stroke();
+ ctx.strokeStyle = "rgba(100,100,255,0.5)"; // Purple path
+ ctx.lineWidth = 4;
+ ctx.stroke();
+ }
+ },
sneaker(x, y, radius = 15 + Math.ceil(Math.random() * 10)) {
mobs.spawn(x, y, 5, radius, "transparent");
let me = mob[mob.length - 1];
@@ -2961,11 +3074,11 @@ const spawn = {
}
};
},
- ghoster(x, y, radius = 40 + Math.ceil(Math.random() * 100)) {
+ ghoster(x, y, radius = 50 + Math.ceil(Math.random() * 90)) {
mobs.spawn(x, y, 7, radius, "transparent");
let me = mob[mob.length - 1];
me.seeAtDistance2 = 300000;
- me.accelMag = 0.00012 * simulation.accelScale;
+ me.accelMag = 0.00013 * simulation.accelScale;
if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search
// Matter.Body.setDensity(me, 0.001); //normal is 0.001 //makes effective life much lower
me.stroke = "transparent"; //used for drawGhost
@@ -2989,10 +3102,10 @@ const spawn = {
this.search();
//draw
if (!m.isBodiesAsleep) {
- if (this.distanceToPlayer2() - this.seeAtDistance2 < 0) {
- if (this.alpha < 1) this.alpha += 0.002 * simulation.CDScale;
+ if (this.distanceToPlayer2() < this.seeAtDistance2) {
+ if (this.alpha < 1) this.alpha += 0.003 * simulation.CDScale; //near player go solid
} else {
- if (this.alpha > 0) this.alpha -= 0.03;
+ if (this.alpha > 0) this.alpha -= 0.03; ///away from player, hide
}
}
if (this.alpha > 0) {
@@ -4146,6 +4259,7 @@ const spawn = {
me.accelMag = 0.0004 * simulation.accelScale;
me.leaveBody = false;
me.showHealthBar = false;
+ me.isDropPowerUp = false;
// Matter.Body.setDensity(me, 0.00004); //normal is 0.001
me.frictionAir = 0.02;
me.isSnakeTail = true;
diff --git a/js/tech.js b/js/tech.js
index 0358128..2e54e1b 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -443,7 +443,7 @@
},
{
name: "cache",
- description: `${powerUps.orb.ammo()} give 11x more ammo, but
you can't store any more ammo than that`,
+ description: `${powerUps.orb.ammo()} give 13x more ammo, but
you can't store any more ammo than that`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -453,7 +453,7 @@
},
requires: "not exciton-lattice",
effect() {
- tech.ammoCap = 11;
+ tech.ammoCap = 13;
powerUps.ammo.effect()
},
remove() {
@@ -4932,7 +4932,7 @@
},
{
name: "aerogel",
- description: "foam bubbles float and dissipate 50% faster
increase foam damage per second by 260%",
+ description: "foam bubbles float and dissipate 50% faster
increase foam damage per second by 200%",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -5044,7 +5044,7 @@
},
remove() {
tech.isHarpoonPowerUp = false
- tech.harpoonDensity = 0.006
+ tech.harpoonDensity = 0.008
}
},
{
@@ -5876,6 +5876,25 @@
// tech.isPlasmaRange = 1;
// }
// },
+ {
+ name: "tokamak",
+ description: "throwing a block converts it into energy
and a pulsed fusion explosion",
+ isFieldTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return m.fieldUpgrades[m.fieldMode].name === "plasma torch" || m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing"
+ },
+ requires: "plasma torch",
+ effect() {
+ tech.isTokamak = true;
+ },
+ remove() {
+ tech.isTokamak = false;
+ }
+ },
{
name: "plasma-bot",
description: "remove your field to build a bot
that uses energy to emit plasma",
@@ -5936,25 +5955,6 @@
if (this.count > 0) powerUps.research.changeRerolls(this.count)
}
},
- {
- name: "tokamak",
- description: "throwing a block converts it into energy
and a pulsed fusion explosion",
- isFieldTech: true,
- maxCount: 1,
- count: 0,
- frequency: 2,
- frequencyDefault: 2,
- allowed() {
- return m.fieldUpgrades[m.fieldMode].name === "plasma torch"
- },
- requires: "plasma torch",
- effect() {
- tech.isTokamak = true;
- },
- remove() {
- tech.isTokamak = false;
- }
- },
{
name: "micro-extruder",
description: "plasma torch extrudes a thin hot wire
increases damage, energy drain, and lag",
@@ -6074,7 +6074,7 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
- return (m.fieldUpgrades[m.fieldMode].name === "time dilation" || m.fieldUpgrades[m.fieldMode].name === "metamaterial cloaking")
+ return m.fieldUpgrades[m.fieldMode].name === "metamaterial cloaking"
},
requires: "metamaterial cloaking",
effect() {
@@ -6221,7 +6221,7 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
- return m.fieldUpgrades[m.fieldMode].name === "metamaterial cloaking" || m.fieldUpgrades[m.fieldMode].name === "pilot wave"
+ return m.fieldUpgrades[m.fieldMode].name === "metamaterial cloaking" || m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing"
},
requires: "metamaterial cloaking or pilot wave",
effect() {
diff --git a/todo.txt b/todo.txt
index e7eeb9b..471d34b 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,14 +1,30 @@
******************************************************** NEXT PATCH **************************************************
-blackhole mobs can no longer see past stealth
-adding dup chance has graphics now
+new mob: slasher - it's basically a jedi
+
+harpoon: +33% damage, +33% delay after firing
+time dilation reverted 50% -> 0% collision harm reduction
+time dilation can no longer get tech: symbiosis
+nano-scale: can access tokamak and discrete optimization
+cache: 11x -> 13x ammo
bug fixes
******************************************************** TODO ********************************************************
-how to make only killing mobs more viable:
- reduce damage from mobs that are asleep or unaware of the player when you touch them?
+slasher compute fastest direction to rotate towards player
+ cross product
+
+death animation ideas:
+ redraw game in strange ways, to show that it's a simulation (for example the testing mode is a strange redraw of map)
+ stroke only, but connect all vertices together, no moveTo
+ draw dots at all the vertices
+
+be nice if block throwing had a projected path
+
+slasher mob: extends a thin radial line, then spins around and damages player if in circle around mob
+ do short length laser damage
+ doesn't have to be a full spin
JUNK tech: planetesimals game inside n-gon
https://codepen.io/lilgreenland/pen/jrMvaB?editors=0010
@@ -63,10 +79,6 @@ Pilot wave tech
Grouping blocks will merge them into a massive ball
Size, density is determined by total mass
-make another boss with a tail
- but the tail is made of interesting mobs
- stabbers maybe
- suckers maybe
make experiment and understand vibe more obvious
mostly in early game or first time players
@@ -76,8 +88,6 @@ look into 360 wave beam lag
aoe effect pushes mobs away, then rapidly pulls them in
for mines?
-tech: shrapnel - nails have an larger randomized 3 point shape triangle shape and they do more damage
-
mob: spawning seekers on death
drones can combine with other drones to get bigger?