foam bots

This commit is contained in:
landgreen
2020-05-10 05:28:24 -07:00
parent fd67ee9aae
commit 92b264cea9
5 changed files with 242 additions and 129 deletions

View File

@@ -32,6 +32,7 @@ const b = {
isModExtraChoice: null, isModExtraChoice: null,
modLaserBotCount: null, modLaserBotCount: null,
modNailBotCount: null, modNailBotCount: null,
modFoamBotCount: null,
modCollisionImmuneCycles: null, modCollisionImmuneCycles: null,
modBlockDmg: null, modBlockDmg: null,
isModPiezo: null, isModPiezo: null,
@@ -47,7 +48,6 @@ const b = {
isModEnergyRecovery: null, isModEnergyRecovery: null,
isModHealthRecovery: null, isModHealthRecovery: null,
isModEnergyLoss: null, isModEnergyLoss: null,
isModFoamShieldSKip: null,
isModDeathAvoid: null, isModDeathAvoid: null,
isModDeathAvoidOnCD: null, isModDeathAvoidOnCD: null,
modWaveSpeedMap: null, modWaveSpeedMap: null,
@@ -334,6 +334,23 @@ const b = {
b.modNailBotCount = 0; b.modNailBotCount = 0;
} }
}, },
{
name: "foam-bot",
description: "a bot fires <strong>foam</strong> at targets in line of sight",
maxCount: 9,
count: 0,
allowed() {
return true
},
requires: "",
effect() {
b.modFoamBotCount++;
b.foamBot();
},
remove() {
b.modFoamBotCount = 0;
}
},
{ {
name: "scrap bots", name: "scrap bots",
description: "<strong>+12%</strong> chance to build a <strong>bot</strong> after killing a mob<br>the bot will follow you until you <strong>exit</strong> the map", description: "<strong>+12%</strong> chance to build a <strong>bot</strong> after killing a mob<br>the bot will follow you until you <strong>exit</strong> the map",
@@ -1358,8 +1375,8 @@ const b = {
} }
}, },
{ {
name: "quantum tunneling", name: "diffusiophoresis",
description: "<strong>foam</strong> bypasses <strong>shields</strong> and sticks to mobs", description: "<strong>foam's</strong> radius increases by <strong>3x</strong><br>after the mob it's stuck to <strong>dies</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
@@ -1367,12 +1384,13 @@ const b = {
}, },
requires: "foam", requires: "foam",
effect() { effect() {
b.isModFoamShieldSKip = true; b.isModFoamGrowOnDeath = true
}, },
remove() { remove() {
b.isModFoamShieldSKip = false; b.isModFoamGrowOnDeath = false;
} }
}, },
{ {
name: "fragmenting projectiles", name: "fragmenting projectiles",
description: "<strong>rail gun</strong> fragments into <strong>nails</strong><br>after hitting mobs at high speeds", description: "<strong>rail gun</strong> fragments into <strong>nails</strong><br>after hitting mobs at high speeds",
@@ -2427,6 +2445,129 @@ const b = {
y: speed * Math.sin(dir) y: speed * Math.sin(dir)
}); });
}, },
foam(position, velocity, radius) {
const me = bullet.length;
bullet[me] = Bodies.polygon(position.x, position.y, 20, radius, {
angle: 0,
density: 0.00005, // 0.001 is normal density
inertia: Infinity,
frictionAir: 0.003,
friction: 0.2,
restitution: 0.2,
dmg: 0.1, //damage done in addition to the damage from momentum
classType: "bullet",
collisionFilter: {
category: cat.bullet,
mask: cat.mob | cat.mobBullet // cat.map | cat.body | cat.mob | cat.mobShield
},
minDmgSpeed: 0,
endCycle: Infinity,
count: 0,
radius: radius,
target: null,
targetVertex: null,
targetRelativePosition: null,
onDmg(who) {
if (!this.target && who.alive) {
this.target = who;
if (Matter.Query.collides(this, [who]).length > 0) {
const normal = Matter.Query.collides(this, [who])[0].normal
this.targetRelativePosition = Vector.rotate(Vector.sub(Vector.sub(this.position, who.position), Vector.mult(normal, -this.radius)), -who.angle) //find relative position vector for zero mob rotation
} else {
this.targetRelativePosition = Vector.rotate(Vector.sub(this.position, who.position), -who.angle) //find relative position vector for zero mob rotation
}
this.collisionFilter.category = cat.body;
this.collisionFilter.mask = null;
let bestVertexDistance = Infinity
let bestVertex = null
for (let i = 0; i < this.target.vertices.length; i++) {
const dist = Vector.magnitude(Vector.sub(this.position, this.target.vertices[i]));
if (dist < bestVertexDistance) {
bestVertex = i
bestVertexDistance = dist
}
}
this.targetVertex = bestVertex
}
},
onEnd() {},
do() {
if (!mech.isBodiesAsleep) { //if time dilation isn't active
//check for touching map
// if (Matter.Query.collides(this, map).length > 0) {
if (Matter.Query.point(map, this.position).length > 0) {
const slow = 0.85
Matter.Body.setVelocity(this, {
x: this.velocity.x * slow,
y: this.velocity.y * slow
});
const SCALE = 0.96
Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE;
// } else if (Matter.Query.collides(this, body).length > 0) {
} else if (Matter.Query.point(body, this.position).length > 0) {
const slow = 0.9
Matter.Body.setVelocity(this, {
x: this.velocity.x * slow,
y: this.velocity.y * slow
});
const SCALE = 0.96
Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE;
} else {
this.force.y += this.mass * 0.00008; //gravity
}
if (this.count < 20) {
this.count++
//grow
const SCALE = 1.06
Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE;
} else {
//shrink
const SCALE = 1 - 0.005 / b.isModBulletsLastLonger
Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE;
if (this.radius < 8) this.endCycle = 0;
}
if (this.target && this.target.alive) { //if stuck to a target
const rotate = Vector.rotate(this.targetRelativePosition, this.target.angle) //add in the mob's new angle to the relative position vector
if (this.target.isVerticesChange) {
Matter.Body.setPosition(this, this.target.vertices[this.targetVertex])
} else {
Matter.Body.setPosition(this, Vector.add(Vector.add(rotate, this.target.velocity), this.target.position))
}
Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.9))
// Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9)
if (this.target.isShielded) {
this.target.damage(b.dmgScale * 0.005, true); //shield damage bypass
//shrink if mob is shielded
const SCALE = 1 - 0.025 / b.isModBulletsLastLonger
Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE;
} else {
this.target.damage(b.dmgScale * 0.005);
}
} else if (this.target !== null) { //look for a new target
this.target = null
this.collisionFilter.category = cat.bullet;
this.collisionFilter.mask = cat.mob //| cat.mobShield //cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
if (b.isModFoamGrowOnDeath && this.radius < 30) {
const SCALE = 3
Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE;
}
}
}
}
});
World.add(engine.world, bullet[me]); //add bullet to world
Matter.Body.setVelocity(bullet[me], velocity);
},
targetedNail(position, num = 1, speed = 50 + 10 * Math.random(), range = 1200) { targetedNail(position, num = 1, speed = 50 + 10 * Math.random(), range = 1200) {
const targets = [] //target nearby mobs const targets = [] //target nearby mobs
for (let i = 0, len = mob.length; i < len; i++) { for (let i = 0, len = mob.length; i < len; i++) {
@@ -2526,6 +2667,61 @@ const b = {
}) })
World.add(engine.world, bullet[me]); //add bullet to world World.add(engine.world, bullet[me]); //add bullet to world
}, },
foamBot(position = mech.pos) {
const me = bullet.length;
const dir = mech.angle;
const RADIUS = (10 + 5 * Math.random())
bullet[me] = Bodies.polygon(position.x, position.y, 6, RADIUS, {
angle: dir,
friction: 0,
frictionStatic: 0,
frictionAir: 0.05,
restitution: 0.6 * (1 + 0.5 * Math.random()),
dmg: 0, // 0.14 //damage done in addition to the damage from momentum
minDmgSpeed: 2,
lookFrequency: 27 + Math.floor(11 * Math.random()),
cd: 0,
delay: 110,
acceleration: 0.005 * (1 + 0.5 * Math.random()),
range: 70 * (1 + 0.3 * Math.random()),
endCycle: Infinity,
classType: "bullet",
collisionFilter: {
category: cat.bullet,
mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield
},
lockedOn: null,
onDmg() {
this.lockedOn = null
},
onEnd() {},
do() {
if (this.cd < game.cycle && !(game.cycle % this.lookFrequency) && !mech.isStealth) {
let target
for (let i = 0, len = mob.length; i < len; i++) {
const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
if (dist < 1000000 && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
this.cd = game.cycle + this.delay;
target = Vector.add(mob[i].position, Vector.mult(mob[i].velocity, Math.sqrt(dist) / 60))
const radius = 6 + 6 * Math.random()
const SPEED = 27 - radius * 0.4; //(mech.crouch ? 32 : 20) - radius * 0.7;
const velocity = Vector.mult(Vector.normalise(Vector.sub(target, this.position)), SPEED)
b.foam(this.position, velocity, radius)
break;
}
}
}
const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos))
if (distanceToPlayer > this.range) { //if far away move towards player
this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.acceleration)
} else { //close to player
Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.90), Vector.mult(player.velocity, 0.17))); //add player's velocity
}
}
})
World.add(engine.world, bullet[me]); //add bullet to world
},
laserBot(position = mech.pos) { laserBot(position = mech.pos) {
const me = bullet.length; const me = bullet.length;
const dir = mech.angle; const dir = mech.angle;
@@ -3624,116 +3820,24 @@ const b = {
name: "foam", name: "foam",
description: "spray bubbly foam that <strong>sticks</strong> to mobs<br><strong class='color-s'>slows</strong> mobs and does <strong class='color-d'>damage</strong> over time", description: "spray bubbly foam that <strong>sticks</strong> to mobs<br><strong class='color-s'>slows</strong> mobs and does <strong class='color-d'>damage</strong> over time",
ammo: 0, ammo: 0,
ammoPack: 35, ammoPack: 50,
have: false, have: false,
isStarterGun: true, isStarterGun: true,
isEasyToAim: false, isEasyToAim: false,
fire() { fire() {
mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 13 : 6) * b.modFireRate); // cool down mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 20 : 6) * b.modFireRate); // cool down
const me = bullet.length; const radius = mech.crouch ? 10 + 7 * Math.random() : 4 + 6 * Math.random() //(4 + (mech.crouch ? 15 : 6) * Math.random())
const dir = mech.angle + 0.2 * (Math.random() - 0.5) const dir = mech.angle + 0.2 * (Math.random() - 0.5)
const RADIUS = (8 + 16 * Math.random()) const position = {
bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 20, RADIUS, { x: mech.pos.x + 30 * Math.cos(mech.angle),
angle: dir, y: mech.pos.y + 30 * Math.sin(mech.angle)
density: 0.00005, // 0.001 is normal density
inertia: Infinity,
frictionAir: 0.003,
friction: 0.2,
restitution: 0.2,
dmg: 0.1, //damage done in addition to the damage from momentum
classType: "bullet",
collisionFilter: {
category: cat.bullet,
mask: cat.mob | cat.mobShield //cat.map | cat.body | cat.mob | cat.mobShield
},
minDmgSpeed: 0,
endCycle: Infinity,
count: 0,
radius: RADIUS,
target: null,
targetVertex: null,
onDmg(who) {
if (!this.target && who.alive && who.dropPowerUp && (!who.isShielded || b.isModFoamShieldSKip)) {
this.target = who;
this.collisionFilter.category = cat.body;
this.collisionFilter.mask = null;
let bestVertexDistance = Infinity
let bestVertex = null
for (let i = 0; i < this.target.vertices.length; i++) {
const dist = Vector.magnitude(Vector.sub(this.position, this.target.vertices[i]));
if (dist < bestVertexDistance) {
bestVertex = i
bestVertexDistance = dist
} }
} const SPEED = 21 - radius * 0.7; //(mech.crouch ? 32 : 20) - radius * 0.7;
this.targetVertex = bestVertex const velocity = {
}
},
onEnd() {},
do() {
// ctx.beginPath() //draw white circle
// ctx.arc(this.position.x, this.position.y, this.radius * 0.97 - 1.6, 0, 2 * Math.PI);
// ctx.fillStyle = "#fff"
// ctx.fill()
if (!mech.isBodiesAsleep) { //if time dilation isn't active
//check for touching map
if (Matter.Query.collides(this, map).length > 0) {
const slow = 0.94
Matter.Body.setVelocity(this, {
x: this.velocity.x * slow,
y: this.velocity.y * slow
});
} else if (Matter.Query.collides(this, body).length > 0) {
const slow = 0.97
Matter.Body.setVelocity(this, {
x: this.velocity.x * slow,
y: this.velocity.y * slow
});
} else {
this.force.y += this.mass * 0.00006; //gravity
}
if (this.count < 17) {
this.count++
//grow
const SCALE = 1.08
Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE;
} else {
//shrink
const SCALE = 1 - 0.0033 / b.isModBulletsLastLonger
Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE;
if (this.radius < 14) this.endCycle = 0;
}
if (this.target && this.target.alive) { //if stuck to a target
Matter.Body.setPosition(this, this.target.vertices[this.targetVertex])
Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.9))
Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9)
if (b.isModFoamShieldSKip && this.target.isShielded) {
this.target.damage(b.dmgScale * 0.0025, true); //shield damage bypass
} else {
this.target.damage(b.dmgScale * 0.005);
}
} else if (this.target !== null) { //look for a new target
this.target = null
this.collisionFilter.category = cat.bullet;
this.collisionFilter.mask = cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
}
}
}
});
World.add(engine.world, bullet[me]); //add bullet to world
if (b.isModFoamShieldSKip) bullet[me].collisionFilter.mask = cat.mob // | cat.mobShield
const SPEED = (mech.crouch ? 17 : 12) - RADIUS * 0.25;
Matter.Body.setVelocity(bullet[me], {
x: SPEED * Math.cos(dir), x: SPEED * Math.cos(dir),
y: SPEED * Math.sin(dir) y: SPEED * Math.sin(dir)
}); }
b.foam(position, velocity, radius)
} }
}, },
{ {

View File

@@ -20,9 +20,9 @@ const level = {
// mech.setField("time dilation field") // mech.setField("time dilation field")
// b.giveMod("renormalization"); // b.giveMod("renormalization");
// b.giveMod("impact shear"); // b.giveMod("impact shear");
// b.giveMod("clock gating"); // b.giveMod("foam-bot");
// b.giveGuns("neutron bomb") // b.giveGuns("neutron bomb")
// b.giveGuns("spores") // b.giveGuns("foam")
// mech.setField("pilot wave") // mech.setField("pilot wave")
// mech.setField("phase decoherence field") // mech.setField("phase decoherence field")
@@ -54,6 +54,9 @@ const level = {
for (let i = 0; i < b.modNailBotCount; i++) { for (let i = 0; i < b.modNailBotCount; i++) {
b.nailBot() b.nailBot()
} }
for (let i = 0; i < b.modFoamBotCount; i++) {
b.foamBot()
}
}, },
isBuildRun: false, isBuildRun: false,
difficultyIncrease(num = 1) { difficultyIncrease(num = 1) {
@@ -158,8 +161,8 @@ const level = {
// spawn.bomberBoss(2900, -500) // spawn.bomberBoss(2900, -500)
// spawn.shooterBoss(1200, -500) // spawn.shooterBoss(1200, -500)
// spawn.spinner(1200, -500) spawn.spinner(1200, -500, 40)
spawn.stabber(1600, -500) // spawn.stabber(1600, -500)
// spawn.cellBossCulture(1600, -500) // spawn.cellBossCulture(1600, -500)
// spawn.shooter(1600, -500) // spawn.shooter(1600, -500)
// spawn.shield(mob[mob.length - 1], 1200, -500, 1); // spawn.shield(mob[mob.length - 1], 1200, -500, 1);

View File

@@ -44,7 +44,7 @@ const mobs = {
} }
}, },
statusSlow(who, cycles = 60) { statusSlow(who, cycles = 60) {
if (!who.shield && !who.isShielded) { if (!who.shield && !who.isShielded && !mech.isBodiesAsleep) {
//remove other "slow" effects on this mob //remove other "slow" effects on this mob
let i = who.status.length let i = who.status.length
while (i--) { while (i--) {
@@ -75,7 +75,7 @@ const mobs = {
} }
}, },
statusStun(who, cycles = 180) { statusStun(who, cycles = 180) {
if (!who.shield && !who.isShielded) { if (!who.shield && !who.isShielded && !mech.isBodiesAsleep) {
Matter.Body.setVelocity(who, { Matter.Body.setVelocity(who, {
x: who.velocity.x * 0.5, x: who.velocity.x * 0.5,
y: who.velocity.y * 0.5 y: who.velocity.y * 0.5
@@ -112,7 +112,7 @@ const mobs = {
} }
}, },
statusDoT(who, tickDamage, cycles = 180) { statusDoT(who, tickDamage, cycles = 180) {
if (!who.isShielded) { if (!who.isShielded && !mech.isBodiesAsleep) {
who.status.push({ who.status.push({
effect() { effect() {
if ((game.cycle - this.startCycle) % 30 === 0) { if ((game.cycle - this.startCycle) % 30 === 0) {
@@ -982,8 +982,14 @@ const mobs = {
} }
} }
if (Math.random() < b.isModBotSpawner) { if (Math.random() < b.isModBotSpawner) {
(Math.random() < 0.5) ? b.nailBot(this.position): b.laserBot(this.position) if (Math.random() < 0.33) {
if (mech.energy > 0.33) mech.energy -= 0.33 b.nailBot(this.position)
} else if (Math.random() < 0.5) {
b.laserBot(this.position)
} else {
b.foamBot(this.position)
}
// if (mech.energy > 0.33) mech.energy -= 0.33
} }
if (b.isModExplodeMob) b.explosion(this.position, Math.min(450, Math.sqrt(this.mass + 3) * 80)) if (b.isModExplodeMob) b.explosion(this.position, Math.min(450, Math.sqrt(this.mass + 3) * 80))
if (b.modNailsDeathMob) b.targetedNail(this.position, b.modNailsDeathMob) if (b.modNailsDeathMob) b.targetedNail(this.position, b.modNailsDeathMob)

View File

@@ -1036,12 +1036,15 @@ const mech = {
pushMass(who) { pushMass(who) {
const speed = Vector.magnitude(Vector.sub(who.velocity, player.velocity)) const speed = Vector.magnitude(Vector.sub(who.velocity, player.velocity))
const fieldBlockCost = (0.03 + Math.sqrt(who.mass) * speed * 0.003) * mech.fieldShieldingScale; const fieldBlockCost = (0.03 + Math.sqrt(who.mass) * speed * 0.003) * mech.fieldShieldingScale;
const unit = Vector.normalise(Vector.sub(player.position, who.position))
if (mech.energy > fieldBlockCost * 0.2) { //shield needs at least some of the cost to block if (mech.energy > fieldBlockCost * 0.2) { //shield needs at least some of the cost to block
mech.energy -= fieldBlockCost mech.energy -= fieldBlockCost
if (mech.energy < 0) mech.energy = 0; if (mech.energy < 0) {
mech.energy = 0;
}
if (mech.energy > mech.maxEnergy) mech.energy = mech.maxEnergy; if (mech.energy > mech.maxEnergy) mech.energy = mech.maxEnergy;
const unit = Vector.normalise(Vector.sub(player.position, who.position))
if (b.modBlockDmg) { if (b.modBlockDmg) {
who.damage(b.modBlockDmg) who.damage(b.modBlockDmg)
//draw electricity //draw electricity
@@ -1293,9 +1296,9 @@ 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.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
} }
if (mech.energy > 0.1 && mech.fieldCDcycle < mech.cycle) { if (mech.energy > 0.1 && mech.fieldCDcycle < mech.cycle) {
const fieldRange1 = (0.55 + 0.35 * Math.sin(mech.cycle / 23)) * mech.fieldRange const fieldRange1 = (0.6 + 0.35 * Math.sin(mech.cycle / 23)) * mech.fieldRange
const fieldRange2 = (0.5 + 0.4 * Math.sin(mech.cycle / 37)) * mech.fieldRange const fieldRange2 = (0.55 + 0.4 * Math.sin(mech.cycle / 37)) * mech.fieldRange
const fieldRange3 = (0.45 + 0.45 * Math.sin(mech.cycle / 47)) * mech.fieldRange const fieldRange3 = (0.5 + 0.45 * Math.sin(mech.cycle / 47)) * mech.fieldRange
const netfieldRange = Math.max(fieldRange1, fieldRange2, fieldRange3) const netfieldRange = Math.max(fieldRange1, fieldRange2, fieldRange3)
ctx.fillStyle = "rgba(110,170,200," + (0.04 + mech.energy * (0.12 + 0.13 * Math.random())) + ")"; ctx.fillStyle = "rgba(110,170,200," + (0.04 + mech.energy * (0.12 + 0.13 * Math.random())) + ")";
ctx.beginPath(); ctx.beginPath();

View File

@@ -1,16 +1,13 @@
sporangium gun now sticks to things, takes longer to germinate, ammo and fire rate are increased. foam bullets are faster, smaller, shrink slower, stick to mobs better
plasma field does 50% more damage, pushes 20% harder, but has 20% less range foam can now stick to shielded mobs, but shrinks faster
mod: foam-bots
************** TODO - n-gon ************** ************** TODO - n-gon **************
mod - if energy goes zero after shield block, knock back and stun nearby mobs sticking bullets don't always gain the correct speed from mobs after they die
mod - frozen mobs take +33% damage mod - frozen mobs take +33% damage
bot that punches nearby mobs
bot could have a regeneration phase, and a punching phase
indicate phase by the size, shape of bot
mod heal to full at the end of each level mod heal to full at the end of each level
heal mods no longer drop? heal mods no longer drop?