let mob=[];const mobs={loop(){let t=mob.length;for(;t--;)mob[t].alive?mob[t].do():mob[t].replace(t)},draw(){ctx.lineWidth=2;let t=mob.length;for(;t--;){ctx.beginPath();const e=mob[t].vertices;ctx.moveTo(e[0].x,e[0].y);for(let t=1,s=e.length;t<s;++t)ctx.lineTo(e[t].x,e[t].y);ctx.lineTo(e[0].x,e[0].y),ctx.fillStyle=mob[t].fill,ctx.strokeStyle=mob[t].stroke,ctx.fill(),ctx.stroke()}},healthBar(){for(let t=0,e=mob.length;t<e;t++)if(mob[t].seePlayer.recall&&mob[t].showHealthBar){const e=.3*mob[t].radius,s=2*mob[t].radius,i=mob[t].position.x-s/2,o=mob[t].position.y-.7*s;ctx.fillStyle="rgba(100, 100, 100, 0.3)",ctx.fillRect(i,o,s,e),ctx.fillStyle="rgba(255,0,0,0.7)",ctx.fillRect(i,o,s*mob[t].health,e)}},statusSlow(t,e=60){if(s(t),tech.isAoESlow){const e=(200+170*Math.random())**2;for(let i=0,o=mob.length;i<o;i++)t!==mob[i]&&Vector.magnitudeSquared(Vector.sub(t.position,mob[i].position))<e+mob[i].radius&&s(mob[i]);simulation.drawList.push({x:t.position.x,y:t.position.y,radius:Math.sqrt(e),color:"rgba(0,100,255,0.05)",time:simulation.drawTime})}function s(t){if(!t.shield&&!t.isShielded&&!m.isBodiesAsleep){t.isBoss&&(e=Math.floor(.25*e));let s=t.status.length;for(;s--;)"slow"===t.status[s].type&&t.status.splice(s,1);t.isSlowed=!0,t.status.push({effect(){Matter.Body.setVelocity(t,{x:.95*Math.min(2,t.velocity.x),y:.95*Math.min(2,t.velocity.y)}),Matter.Body.setAngularVelocity(t,0),ctx.beginPath(),ctx.moveTo(t.vertices[0].x,t.vertices[0].y);for(let e=1,s=t.vertices.length;e<s;++e)ctx.lineTo(t.vertices[e].x,t.vertices[e].y);ctx.lineTo(t.vertices[0].x,t.vertices[0].y),ctx.strokeStyle="rgba(0,100,255,0.8)",ctx.lineWidth=15,ctx.stroke(),ctx.fillStyle=t.fill,ctx.fill()},endEffect(){t.isSlowed=!1},type:"slow",endCycle:simulation.cycle+e})}}},statusStun(t,e=180){if(!t.shield&&!t.isShielded&&!m.isBodiesAsleep){Matter.Body.setVelocity(t,{x:.8*t.velocity.x,y:.8*t.velocity.y}),Matter.Body.setAngularVelocity(t,.8*t.angularVelocity);let s=t.status.length;for(;s--;)"stun"===t.status[s].type&&t.status.splice(s,1);t.isStunned=!0,t.status.push({effect(){t.seePlayer.yes=!1,t.seePlayer.recall=0,t.seePlayer.position={x:t.position.x+100*(Math.random()-.5),y:t.position.y+100*(Math.random()-.5)},t.velocity.y<2&&(t.force.y+=4e-4*t.mass);const e=.3*t.radius,s=2*t.radius,i=t.position.x-s/2,o=t.position.y-.7*s;ctx.fillStyle="rgba(100, 100, 100, 0.3)",ctx.fillRect(i,o,s,e),ctx.fillStyle=`rgba(${Math.floor(255*Math.random())},${Math.floor(255*Math.random())},${Math.floor(255*Math.random())},0.5)`,ctx.fillRect(i,o,s*t.health,e),ctx.beginPath(),ctx.moveTo(t.vertices[0].x,t.vertices[0].y);for(let e=1,s=t.vertices.length;e<s;++e)ctx.lineTo(t.vertices[e].x,t.vertices[e].y);ctx.lineTo(t.vertices[0].x,t.vertices[0].y),ctx.stroke(),ctx.fill()},endEffect(){t.isStunned=!1},type:"stun",endCycle:simulation.cycle+e*(t.isBoss?.2:1)})}},statusDoT(t,e,s=180){!t.isShielded&&t.alive&&t.damageReduction>0&&t.status.push({effect(){if((simulation.cycle-this.startCycle)%30==0&&!m.isBodiesAsleep){let e=b.dmgScale*this.dmg;t.damage(e),t.damageReduction&&simulation.drawList.push({x:t.position.x+(Math.random()-.5)*t.radius*.5,y:t.position.y+(Math.random()-.5)*t.radius*.5,radius:40*Math.log(e+1.1)*t.damageReduction+3,color:"rgba(0,80,80,0.9)",time:simulation.drawTime})}},endEffect(){},dmg:e,type:"dot",endCycle:simulation.cycle+s,startCycle:simulation.cycle+29})},spawn(t,e,s,i,o){let a=mob.length;mob[a]=Matter.Bodies.polygon(t,e,s,i,{mob:!0,density:.001,frictionAir:.005,restitution:.5,collisionFilter:{group:0,category:cat.mob,mask:cat.player|cat.map|cat.body|cat.bullet|cat.mob},onHit:void 0,alive:!0,index:a,health:tech.mobSpawnWithHealth,showHealthBar:!0,accelMag:.001*simulation.accelScale,cd:0,delay:60,fill:o,stroke:"#000",seePlayer:{yes:!1,recall:0,position:{x:t,y:e}},radius:i,spawnPos:{x:t,y:e},status:[],checkStatus(){let t=this.status.length;for(;t--;)this.status[t].effect(),this.status[t].endCycle<simulation.cycle&&(this.status[t].endEffect(),this.status.splice(t,1))},isSlowed:!1,isStunned:!1,seeAtDistance2:1/0,distanceToPlayer(){const t=this.position.x-player.position.x,e=this.position.y-player.position.y;return Math.sqrt(t*t+e*e)},distanceToPlayer2(){const t=this.position.x-player.position.x,e=this.position.y-player.position.y;return t*t+e*e},gravity(){this.force.y+=this.mass*this.g},seePlayerFreq:Math.floor(30+30*Math.random()),foundPlayer(){this.locatePlayer(),this.seePlayer.yes||(this.alertNearByMobs(),this.seePlayer.yes=!0)},lostPlayer(){this.seePlayer.yes=!1,this.seePlayer.recall-=this.seePlayerFreq,this.seePlayer.recall<0&&(this.seePlayer.recall=0)},memory:120,locatePlayer(){this.seePlayer.recall=this.memory+Math.round(this.memory*Math.random()),this.seePlayer.position.x=player.position.x,this.seePlayer.position.y=player.position.y},alertNearByMobs(){for(let t=0;t<mob.length;t++)!mob[t].seePlayer.recall&&Vector.magnitudeSquared(Vector.sub(this.position,mob[t].position))<this.alertRange2&&mob[t].locatePlayer()},alwaysSeePlayer(){m.isCloak||(this.seePlayer.recall=!0,this.seePlayer.position.x=player.position.x,this.seePlayer.position.y=player.position.y)},seePlayerByHistory(t=30){if(!(simulation.cycle%this.seePlayerFreq))if(0!==Matter.Query.ray(map,this.position,this.playerPosRandomY()).length||m.isCloak){if(this.seePlayer.recall&&(this.lostPlayer(),!m.isCloak))for(let e=0;e<t;e++){let t=m.history[(m.cycle-10*e)%600];if(0===Matter.Query.ray(map,this.position,t.position).length){this.seePlayer.recall=this.memory+Math.round(this.memory*Math.random()),this.seePlayer.position.x=t.position.x,this.seePlayer.position.y=t.position.y,this.seePlayer.yes=!0;break}}}else this.foundPlayer()},seePlayerCheck(){simulation.cycle%this.seePlayerFreq||(this.distanceToPlayer2()<this.seeAtDistance2&&0===Matter.Query.ray(map,this.position,this.playerPosRandomY()).length&&!m.isCloak?this.foundPlayer():this.seePlayer.recall&&this.lostPlayer())},seePlayerCheckByDistance(){simulation.cycle%this.seePlayerFreq||(this.distanceToPlayer2()<this.seeAtDistance2&&!m.isCloak?this.foundPlayer():this.seePlayer.recall&&this.lostPlayer())},seePlayerByDistOrLOS(){simulation.cycle%this.seePlayerFreq||((this.distanceToPlayer2()<this.seeAtDistance2||0===Matter.Query.ray(map,this.position,this.playerPosRandomY()).length)&&!m.isCloak?this.foundPlayer():this.seePlayer.recall&&this.lostPlayer())},isLookingAtPlayer(t){const e=Vector.normalise(Vector.sub(player.position,this.position)),s={x:Math.cos(this.angle),y:Math.sin(this.angle)};return Vector.dot(s,e)>t},lookRange:.2+.2*Math.random(),lookTorque:4e-7*(Math.random()>.5?-1:1),seePlayerByLookingAt(){if(simulation.cycle%this.seePlayerFreq||!this.seePlayer.recall&&!this.isLookingAtPlayer(this.lookRange)||(this.distanceToPlayer2()<this.seeAtDistance2&&0===Matter.Query.ray(map,this.position,this.playerPosRandomY()).length&&!m.isCloak?this.foundPlayer():this.seePlayer.recall&&this.lostPlayer()),!this.seePlayer.recall){this.torque=this.lookTorque*this.inertia;const t=Math.PI*this.lookRange;ctx.beginPath(),ctx.arc(this.position.x,this.position.y,2.5*this.radius,this.angle-t,this.angle+t),ctx.arc(this.position.x,this.position.y,1.4*this.radius,this.angle+t,this.angle-t,!0),ctx.fillStyle="rgba(0,0,0,0.07)",ctx.fill()}},playerPosRandomY:()=>({x:player.position.x,y:player.position.y+110*(Math.random()-.5)}),harmZone(){this.seePlayer.yes&&(ctx.setLineDash([125*Math.random(),125*Math.random()]),this.distanceToPlayer()<this.laserRange&&(m.immuneCycle<m.cycle&&(m.damage(3e-4*simulation.dmgScale),m.energy>.1&&(m.energy-=.003)),ctx.beginPath(),ctx.moveTo(this.position.x,this.position.y),ctx.lineTo(m.pos.x,m.pos.y),ctx.lineTo(m.pos.x+3e3*(Math.random()-.5),m.pos.y+3e3*(Math.random()-.5)),ctx.lineWidth=2,ctx.strokeStyle="rgb(255,0,170)",ctx.stroke(),ctx.beginPath(),ctx.arc(m.pos.x,m.pos.y,40,0,2*Math.PI),ctx.fillStyle="rgba(255,0,170,0.15)",ctx.fill()),ctx.beginPath(),ctx.arc(this.position.x,this.position.y,.9*this.laserRange,0,2*Math.PI),ctx.strokeStyle="rgba(255,0,170,0.5)",ctx.lineWidth=1,ctx.stroke(),ctx.setLineDash([]),ctx.fillStyle="rgba(255,0,170,0.03)",ctx.fill())},laser(){const t=function(t,e,s){for(let i=0;i<s.length;++i){let o=s[i].vertices;const a=o.length-1;for(let l=0;l<a;l++)if(results=simulation.checkLineIntersection(t,e,o[l],o[l+1]),results.onLine1&&results.onLine2){const e=t.x-results.x,a=t.y-results.y,h=e*e+a*a;h<best.dist2&&(!s[i].mob||s[i].alive)&&(best={x:results.x,y:results.y,dist2:h,who:s[i],v1:o[l],v2:o[l+1]})}if(results=simulation.checkLineIntersection(t,e,o[0],o[a]),results.onLine1&&results.onLine2){const e=t.x-results.x,l=t.y-results.y,h=e*e+l*l;h<best.dist2&&(best={x:results.x,y:results.y,dist2:h,who:s[i],v1:o[0],v2:o[a]})}}};if(this.seePlayer.recall&&!this.isSlowed){const e=2500;best={x:null,y:null,dist2:1/0,who:null,v1:null,v2:null};const s={x:this.position.x+e*Math.cos(this.angle),y:this.position.y+e*Math.sin(this.angle)};if(t(this.position,s,map),t(this.position,s,body),m.isCloak||t(this.position,s,[playerBody,playerHead]),(best.who===playerBody||best.who===playerHead)&&m.immuneCycle<m.cycle){const t=.0014*simulation.dmgScale;m.damage(t),ctx.fillStyle="#f00",ctx.beginPath(),ctx.arc(best.x,best.y,1e4*t,0,2*Math.PI),ctx.fill()}best.dist2===1/0&&(best=s),ctx.beginPath(),ctx.moveTo(this.position.x,this.position.y),ctx.lineTo(best.x,best.y),ctx.strokeStyle="#f00",ctx.lineWidth=1,ctx.setLineDash([50+120*Math.random(),50*Math.random()]),ctx.stroke(),ctx.setLineDash([])}},searchSpring(){ctx.beginPath(),ctx.arc(this.cons.pointA.x,this.cons.pointA.y,6,0,2*Math.PI),ctx.arc(this.cons2.pointA.x,this.cons2.pointA.y,6,0,2*Math.PI),ctx.fillStyle="#222",ctx.fill(),simulation.cycle%this.seePlayerFreq||((this.seePlayer.recall||this.isLookingAtPlayer(this.lookRange))&&this.distanceToPlayer2()<this.seeAtDistance2&&0===Matter.Query.ray(map,this.position,player.position).length&&0===Matter.Query.ray(body,this.position,player.position).length&&!m.isCloak?this.foundPlayer():this.seePlayer.recall&&this.lostPlayer())},springAttack(){if(this.seePlayer.recall&&0===Matter.Query.ray(map,this.position,this.seePlayer.position).length)if(simulation.cycle%(2*this.seePlayerFreq)){if(!(simulation.cycle%this.seePlayerFreq)){const t=Vector.normalise(Vector.sub(this.seePlayer.position,this.position)),e=Vector.add(this.position,Vector.mult(t,600));this.springTarget2.x=e.x,this.springTarget2.y=e.y,this.cons.length=100+1.5*this.radius,this.cons2.length=-200}}else{const t=Vector.normalise(Vector.sub(this.seePlayer.position,this.position)),e=Vector.add(this.position,Vector.mult(t,600));this.springTarget.x=e.x,this.springTarget.y=e.y,this.cons.length=-200,this.cons2.length=100+1.5*this.radius}else{this.torque=this.lookTorque*this.inertia;const t=Math.PI*this.lookRange;ctx.beginPath(),ctx.arc(this.position.x,this.position.y,2.5*this.radius,this.angle-t,this.angle+t),ctx.arc(this.position.x,this.position.y,1.4*this.radius,this.angle+t,this.angle-t,!0),ctx.fillStyle="rgba(0,0,0,0.07)",ctx.fill();const e=function(t,e,s){for(let i=0;i<s.length;++i){let o=s[i].vertices;const a=o.length-1;for(let l=0;l<a;l++)if(results=simulation.checkLineIntersection(t,e,o[l],o[l+1]),results.onLine1&&results.onLine2){const e=t.x-results.x,a=t.y-results.y,h=e*e+a*a;h<best.dist2&&(!s[i].mob||s[i].alive)&&(best={x:results.x,y:results.y,dist2:h,who:s[i],v1:o[l],v2:o[l+1]})}if(results=simulation.checkLineIntersection(t,e,o[0],o[a]),results.onLine1&&results.onLine2){const e=t.x-results.x,l=t.y-results.y,h=e*e+l*l;h<best.dist2&&(best={x:results.x,y:results.y,dist2:h,who:s[i],v1:o[0],v2:o[a]})}}};if(!(simulation.cycle%(4*this.seePlayerFreq))){best={x:null,y:null,dist2:1/0,who:null,v1:null,v2:null};const t=3e3,s={x:this.position.x+t*Math.cos(this.angle),y:this.position.y+t*Math.sin(this.angle)};e(this.position,s,map),e(this.position,s,body),best.dist2!=1/0&&(this.springTarget.x=best.x,this.springTarget.y=best.y,this.cons.length=100+1.5*this.radius,this.cons2.length=100+1.5*this.radius)}}},curl(t=1e3,e=-10){applyCurl=function(s,i,o=!0){for(let a=0;a<i.length;++a)if(!i[a].isNotHoldable){const l=Vector.sub(s,i[a].position),h=Vector.magnitudeSquared(l);if(h<t*t&&h>1e4){const t=Vector.mult(Vector.perp(Vector.normalise(l)),e);i[a].isMobBullet?Matter.Body.setVelocity(i[a],{x:.97*i[a].velocity.x+.06*t.x,y:.97*i[a].velocity.y+.06*t.y}):Matter.Body.setVelocity(i[a],{x:.94*i[a].velocity.x+.06*t.x,y:.94*i[a].velocity.y+.06*t.y}),o&&(i[a].force.y-=.8*simulation.g*i[a].mass)}}},applyCurl(this.position,mob,!1),applyCurl(this.position,body),applyCurl(this.position,powerUp)},pullPlayer(){if(this.seePlayer.yes&&Vector.magnitudeSquared(Vector.sub(this.position,player.position))<1e6){const t=Math.atan2(player.position.y-this.position.y,player.position.x-this.position.x);player.force.x-=.00113*simulation.accelScale*player.mass*Math.cos(t)*(m.onGround?2:1),player.force.y-=84e-5*simulation.accelScale*player.mass*Math.sin(t),ctx.beginPath(),ctx.moveTo(this.position.x,this.position.y),ctx.lineTo(m.pos.x,m.pos.y),ctx.lineWidth=Math.min(60,2*this.radius),ctx.strokeStyle="rgba(0,0,0,0.5)",ctx.stroke(),ctx.beginPath(),ctx.arc(m.pos.x,m.pos.y,40,0,2*Math.PI),ctx.fillStyle="rgba(0,0,0,0.3)",ctx.fill()}},repelBullets(){if(this.seePlayer.yes){ctx.lineWidth="8",ctx.strokeStyle=this.fill,ctx.beginPath();for(let t=0,e=bullet.length;t<e;++t){const e=bullet[t].position.x-this.position.x,s=bullet[t].position.y-this.position.y,i=Math.sqrt(e*e+s*s);if(i<500){ctx.moveTo(this.position.x,this.position.y),ctx.lineTo(bullet[t].position.x,bullet[t].position.y);const o=Math.atan2(s,e),a=1500*bullet[t].mass*simulation.g/i;bullet[t].force.x+=a*Math.cos(o),bullet[t].force.y+=a*Math.sin(o)}}ctx.stroke()}},attraction(){if(this.seePlayer.recall){const t=Vector.mult(Vector.normalise(Vector.sub(this.seePlayer.position,this.position)),this.accelMag*this.mass);this.force.x+=t.x,this.force.y+=t.y}},repulsionRange:5e5,repulsion(){if(this.seePlayer.recall&&this.distanceToPlayer2()<this.repulsionRange){const t=this.accelMag*this.mass,e=Math.atan2(this.seePlayer.position.y-this.position.y,this.seePlayer.position.x-this.position.x);this.force.x-=2*t*Math.cos(e),this.force.y-=2*t*Math.sin(e)}},hoverOverPlayer(){if(this.seePlayer.recall){const t=250;this.position.y>this.seePlayer.position.y-this.hoverElevation+t?this.force.y-=this.accelMag*this.mass:this.position.y<this.seePlayer.position.y-this.hoverElevation-t&&(this.force.y+=this.accelMag*this.mass);const e=150;this.position.x>this.seePlayer.position.x+this.hoverXOff+e?this.force.x-=this.accelMag*this.mass:this.position.x<this.seePlayer.position.x+this.hoverXOff-e&&(this.force.x+=this.accelMag*this.mass)}},invulnerability(){if(this.isInvulnerable)if(this.invulnerabilityCountDown>0){this.invulnerabilityCountDown--,ctx.beginPath();let t=this.vertices;ctx.moveTo(t[0].x,t[0].y);for(let e=1;e<t.length;e++)ctx.lineTo(t[e].x,t[e].y);ctx.lineTo(t[0].x,t[0].y),ctx.lineWidth=20,ctx.strokeStyle="rgba(255,255,255,0.4)",ctx.stroke()}else this.isInvulnerable=!1,this.damageReduction=this.startingDamageReduction},grow(){if(!m.isBodiesAsleep)if(this.seePlayer.recall){if(this.radius<80){const t=1.01;Matter.Body.scale(this,t,t),this.radius*=t,this.fill=`hsl(144, ${this.radius}%, 50%)`,this.isShielded&&(this.isShielded=!1,this.removeConsBB())}}else if(this.radius>15){const t=.99;Matter.Body.scale(this,t,t),this.radius*=t,this.fill=`hsl(144, ${this.radius}%, 50%)`}},search(){if(!this.seePlayer.recall){const t=function(t){Math.random()<5e-4?t.searchTarget=player.position:t.searchTarget=map[Math.floor(Math.random()*(map.length-1))].position},e=Vector.sub(this.searchTarget,this.position);Vector.magnitude(e)>2*this.radius?this.force=Vector.mult(Vector.normalise(e),this.accelMag*this.mass*.2):t(this),simulation.cycle%(15*this.seePlayerFreq)||t(this)}},blink(){if(this.seePlayer.recall&&!(simulation.cycle%this.blinkRate)){ctx.beginPath(),ctx.moveTo(this.position.x,this.position.y);const t=Vector.sub(this.seePlayer.position,this.position),e=Vector.magnitude(t),s=Vector.normalise(t),o=50*(Math.random()-.5);e<this.blinkLength?Matter.Body.translate(this,Vector.mult(s,e+o)):Matter.Body.translate(this,Vector.mult(s,this.blinkLength+o)),ctx.lineTo(this.position.x,this.position.y),ctx.lineWidth=2*i,ctx.strokeStyle=this.stroke,ctx.stroke()}},drift(){if(this.seePlayer.recall&&!(simulation.cycle%this.blinkRate)){ctx.beginPath(),ctx.moveTo(this.position.x,this.position.y);const t=Vector.sub(this.seePlayer.position,this.position),e=Vector.magnitude(t),s=Vector.mult(Vector.normalise(t),this.blinkLength);e<this.blinkLength?(Matter.Body.setPosition(this,this.seePlayer.position),Matter.Body.translate(this,{x:50*(Math.random()-.5),y:50*(Math.random()-.5)})):(s.x+=200*(Math.random()-.5),s.y+=200*(Math.random()-.5),Matter.Body.translate(this,s)),ctx.lineTo(this.position.x,this.position.y),ctx.lineWidth=2*i,ctx.strokeStyle=this.stroke,ctx.stroke()}},bomb(){!(simulation.cycle%this.fireFreq)&&Math.abs(this.position.x-this.seePlayer.position.x)<400&&0===Matter.Query.ray(map,this.position,this.playerPosRandomY()).length&&0===Matter.Query.ray(body,this.position,this.playerPosRandomY()).length&&(spawn.bomb(this.position.x,this.position.y+.7*this.radius,9+Math.ceil(this.radius/15),5),Matter.Body.setAngularVelocity(mob[mob.length-1],.5*(Math.random()-.5)),Matter.Body.setVelocity(mob[mob.length-1],{x:this.velocity.x,y:this.velocity.y}),Matter.Body.setAngularVelocity(this,.25*(Math.random()-.5)))},fire(){if(!m.isBodiesAsleep){const t=()=>{const t=this.radius+this.radius*this.noseLength;this.vertices[1].x=this.position.x+Math.cos(this.angle)*t,this.vertices[1].y=this.position.y+Math.sin(this.angle)*t};if(this.seePlayer.recall){simulation.cycle%this.seePlayerFreq||(this.fireDir=Vector.normalise(Vector.sub(this.seePlayer.position,this.position)),this.fireDir.y-=Math.abs(this.seePlayer.position.x-this.position.x)/2500);const e=this.angle+Math.PI/2,s=Vector.dot({x:Math.cos(e),y:Math.sin(e)},this.fireDir),i=.1;if(s>i)this.torque+=4e-6*this.inertia;else if(s<-i)this.torque-=4e-6*this.inertia;else if(this.noseLength>1.5&&s>-.2&&s<.2){spawn.bullet(this.vertices[1].x,this.vertices[1].y,9+Math.ceil(this.radius/15));const t=15;Matter.Body.setVelocity(mob[mob.length-1],{x:this.velocity.x+this.fireDir.x*t+3*Math.random(),y:this.velocity.y+this.fireDir.y*t+3*Math.random()}),this.noseLength=0,this.force.x-=.005*this.fireDir.x*this.mass,this.force.y-=.005*this.fireDir.y*this.mass}this.noseLength<1.5&&(this.noseLength+=this.fireFreq),t()}else this.noseLength>.1&&(this.noseLength-=this.fireFreq/2,t())}},turnToFacePlayer(){const t=player.position.x-this.position.x,e=-player.position.y+this.position.y,s=this.distanceToPlayer(),i=this.angle+Math.PI/2;c=Math.cos(i)*t-Math.sin(i)*e,c>.04*s?this.torque+=.002*this.mass:c<.04&&(this.torque-=.002*this.mass)},facePlayer(){const t=Vector.normalise(Vector.sub(this.seePlayer.position,this.position)),e=Math.atan2(t.y,t.x);Matter.Body.setAngle(this,e-Math.PI)},explode(t=this.mass){m.immuneCycle<m.cycle&&(m.damage(Math.min(Math.max(.02*Math.sqrt(t),.01),.35)*simulation.dmgScale),this.isDropPowerUp=!1,this.death())},timeLimit(){m.isBodiesAsleep||(this.timeLeft--,this.timeLeft<0&&(this.isDropPowerUp=!1,this.death()))},healthBar(){if(this.seePlayer.recall){const t=.3*this.radius,e=2*this.radius,s=this.position.x-e/2,i=this.position.y-.7*e;ctx.fillStyle="rgba(100, 100, 100, 0.3)",ctx.fillRect(s,i,e,t),ctx.fillStyle="rgba(255,0,0,0.7)",ctx.fillRect(s,i,e*this.health,t)}},damage(t,e=!1){this.isShielded&&!e||!this.alive||(t*=tech.damageFromTech(),tech.isFarAwayDmg&&(t*=1+.0067*Math.sqrt(Math.max(500,Math.min(3e3,this.distanceToPlayer()))-500)),t*=this.damageReduction,tech.energySiphon&&t!==1/0&&this.isDropPowerUp&&m.immuneCycle<m.cycle&&(m.energy+=Math.min(this.health,t)*tech.energySiphon),tech.healthDrain&&t!==1/0&&this.isDropPowerUp&&(m.addHealth(Math.min(this.health,t)*tech.healthDrain),m.health>m.maxHealth&&(m.health=m.maxHealth)),t/=Math.sqrt(this.mass),this.health-=t,this.onDamage(t),this.health<.05&&this.alive&&this.death())},onDamage(){},onDeath(){},damageReduction:1,leaveBody:!0,isDropPowerUp:!0,death(){if(this.onDeath(this),this.removeConsBB(),this.alive=!1,this.isDropPowerUp){if(tech.iceIXOnDeath&&this.isSlowed)for(let t=0,e=2*Math.sqrt(Math.min(this.mass,25))*tech.iceIXOnDeath;t<e;t++)b.iceIX(3,2*Math.random()*Math.PI,this.position);if(tech.deathSpawnsFromBoss||tech.deathSpawns&&this.isDropPowerUp){const t=tech.deathSpawns+tech.deathSpawnsFromBoss,e=Math.min(12,t*Math.ceil(Math.random()*simulation.difficulty*t));for(let t=0;t<e;t++)spawn.spawns(this.position.x+(Math.random()-.5)*i*2.5,this.position.y+(Math.random()-.5)*i*2.5),Matter.Body.setVelocity(mob[mob.length-1],{x:this.velocity.x+10*(Math.random()-.5),y:this.velocity.x+10*(Math.random()-.5)})}if(tech.isEnergyLoss&&(m.energy*=.75),powerUps.spawnRandomPowerUp(this.position.x,this.position.y),m.lastKillCycle=m.cycle,Math.random()<tech.sporesOnDeath)if(tech.isSporeWorm){const t=Math.min(25,Math.floor(2+this.mass*(.5+.5*Math.random())))/2;for(let e=0;e<t;e++)b.worm(this.position)}else{const t=Math.min(25,Math.floor(2+this.mass*(.5+.5*Math.random())));for(let e=0;e<t;e++)b.spore(this.position)}else tech.isExplodeMob?b.explosion(this.position,Math.min(600,Math.sqrt(this.mass+1.5)*(22+60*Math.random()))):tech.nailsDeathMob&&b.targetedNail(this.position,tech.nailsDeathMob,39+6*Math.random());if(tech.isBotSpawnerReset)for(let t=0,e=bullet.length;t<e;t++)bullet[t].botType&&bullet[t].endCycle!==1/0&&(bullet[t].endCycle=simulation.cycle+840);if(Math.random()<tech.botSpawner&&(b.randomBot(this.position,!1),bullet[bullet.length-1].endCycle=simulation.cycle+840,this.leaveBody=!1),tech.isAddRemoveMaxHealth)if(this.isBoss&&this.isDropPowerUp)powerUps.spawn(this.position.x,this.position.y,"tech",!1);else{const t=.005;tech.isEnergyHealth?m.maxEnergy>t&&(tech.healMaxEnergyBonus-=t,m.setMaxEnergy()):m.maxHealth>t&&(tech.extraMaxHealth-=t,m.setMaxHealth())}if(tech.removeMaxHealthOnKill){const t=.002;tech.isEnergyHealth?m.maxEnergy>t&&(tech.healMaxEnergyBonus-=t,m.setMaxEnergy()):m.maxHealth>t&&(tech.extraMaxHealth-=t,m.setMaxHealth())}tech.cloakDuplication&&!this.isBoss&&(tech.cloakDuplication-=.02,powerUps.setDupChance())}else if(tech.isShieldAmmo&&this.shield&&!this.isExtraShield){let t=tech.isEnergyNoAmmo?"heal":"ammo";Math.random()<.4?t="heal":Math.random()<.3&&!tech.isSuperDeterminism&&(t="research");for(let e=0,s=Math.ceil(2*Math.random());e<s;e++)powerUps.spawn(this.position.x,this.position.y,t)}if(tech.isRadioactive){let t=0;for(let e=0,s=this.status.length;e<s;e++)"dot"===this.status[e].type&&(t+=this.status[e].dmg*(this.status[e].endCycle-simulation.cycle));if(t>0){let e=500,s=null;for(let t=0,i=mob.length;t<i;++t){const i=Vector.magnitude(Vector.sub(this.position,mob[t].position));mob[t].alive&&!mob[t].isShielded&&i<e&&(e=i,s=t)}s&&(mobs.statusDoT(mob[s],t/180,180),ctx.beginPath(),ctx.moveTo(this.position.x,this.position.y),ctx.lineTo(mob[s].position.x,mob[s].position.y),ctx.lineWidth=this.radius,ctx.strokeStyle="rgba(0,80,80,1)",ctx.stroke())}}},removeConsBB(){for(let t=0,e=consBB.length;t<e;++t){if(consBB[t].bodyA===this){consBB[t].bodyB.shield&&(consBB[t].bodyB.do=function(){this.death()}),consBB[t].bodyA=consBB[t].bodyB,consBB.splice(t,1),this.removeConsBB();break}if(consBB[t].bodyB===this){consBB[t].bodyA.shield&&(consBB[t].bodyA.do=function(){this.death()}),consBB[t].bodyB=consBB[t].bodyA,consBB.splice(t,1),this.removeConsBB();break}}},removeCons(){for(let t=0,e=cons.length;t<e;++t){if(cons[t].bodyA===this){cons[t].bodyA=cons[t].bodyB,cons.splice(t,1),this.removeCons();break}if(cons[t].bodyB===this){cons[t].bodyB=cons[t].bodyA,cons.splice(t,1),this.removeCons();break}}},replace(t){if(this.leaveBody&&body.length<40&&this.mass<200&&this.radius>18){let e=Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices));if(e.length>5&&body.length<35&&Math.random()<.25){const t=3+Math.floor((e.length-6)*Math.random()),s=e.slice(0,t+1);e=e.slice(t-1);const i=body.length;body[i]=Matter.Bodies.fromVertices(this.position.x,this.position.y,s),Matter.Body.setVelocity(body[i],Vector.mult(this.velocity,.5)),Matter.Body.setAngularVelocity(body[i],this.angularVelocity),body[i].collisionFilter.category=cat.body,body[i].collisionFilter.mask=cat.player|cat.map|cat.body|cat.bullet|cat.mob|cat.mobBullet,body[i].classType="body",Composite.add(engine.world,body[i]);const o=body.length;if(body[o]=Matter.Bodies.fromVertices(this.position.x,this.position.y,e),Matter.Body.setVelocity(body[o],Vector.mult(this.velocity,.5)),Matter.Body.setAngularVelocity(body[o],this.angularVelocity),body[o].collisionFilter.category=cat.body,body[o].collisionFilter.mask=cat.player|cat.map|cat.body|cat.bullet|cat.mob|cat.mobBullet,body[o].classType="body",Composite.add(engine.world,body[o]),body[i].mass+body[o].mass>16){const t=8+6*Math.random(),e=function(s,i){if(s.mass+i.mass>t){const t=.95;Matter.Body.scale(s,t,t),Matter.Body.scale(i,t,t),setTimeout(e,20,s,i)}};e(body[i],body[o])}}else{const t=body.length;if(body[t]=Matter.Bodies.fromVertices(this.position.x,this.position.y,e),Matter.Body.setVelocity(body[t],Vector.mult(this.velocity,.5)),Matter.Body.setAngularVelocity(body[t],this.angularVelocity),body[t].collisionFilter.category=cat.body,body[t].collisionFilter.mask=cat.player|cat.map|cat.body|cat.bullet|cat.mob|cat.mobBullet,body[t].classType="body",Composite.add(engine.world,body[t]),body[t].mass>9){const e=7+4*Math.random(),s=function(t){if(t.mass>e){const e=.95;Matter.Body.scale(t,e,e),setTimeout(s,20,t)}};s(body[t])}}if(Matter.Composite.remove(engine.world,this),mob.splice(t,1),tech.isMobBlockFling){const t=body[body.length-1];b.targetedBlock(t,!0),Matter.Body.setAngularVelocity(t,(.5+.2*Math.random())*(Math.random()<.5?-1:1))}}else Matter.Composite.remove(engine.world,this),mob.splice(t,1)}}),mob[a].alertRange2=Math.pow(3*mob[a].radius+550,2),Composite.add(engine.world,mob[a])}};