let player,jumpSensor,playerBody,playerHead,headSensor;const m={spawn(){let e=Vertices.fromPath("0,40, 50,40, 50,115, 30,130, 20,130, 0,115, 0,40");playerBody=Bodies.fromVertices(0,0,e),jumpSensor=Bodies.rectangle(0,46,36,6,{sleepThreshold:99999999999,isSensor:!0}),e=Vertices.fromPath("16 -82 2 -66 2 -37 43 -37 43 -66 30 -82"),playerHead=Bodies.fromVertices(0,-55,e),headSensor=Bodies.rectangle(0,-57,48,45,{sleepThreshold:99999999999,isSensor:!0}),player=Body.create({parts:[playerBody,playerHead,jumpSensor,headSensor],inertia:1/0,friction:.002,frictionAir:.001,restitution:0,sleepThreshold:1/0,collisionFilter:{group:0,category:cat.player,mask:cat.body|cat.map|cat.mob|cat.mobBullet|cat.mobShield},death(){m.death()}}),Matter.Body.setMass(player,m.mass),Composite.add(engine.world,[player])},cycle:600,lastKillCycle:0,lastHarmCycle:0,width:50,radius:30,eyeFillColor:null,fillColor:null,fillColorDark:null,bodyGradient:null,color:{hue:0,sat:0,light:100},setFillColors(){this.fillColor=`hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)`,this.fillColorDark=`hsl(${m.color.hue},${m.color.sat}%,${m.color.light-25}%)`;let e=ctx.createLinearGradient(-30,0,30,0);e.addColorStop(0,m.fillColorDark),e.addColorStop(1,m.fillColor),this.bodyGradient=e},height:42,yOffWhen:{crouch:22,stand:49,jump:70},defaultMass:5,mass:5,FxNotHolding:.015,Fx:.016,jumpForce:.42,setMovement(){m.Fx=tech.baseFx*tech.squirrelFx*(tech.isFastTime?1.5:1)/player.mass,m.jumpForce=tech.baseJumpForce*tech.squirrelJump*(tech.isFastTime?1.13:1)/player.mass/player.mass},FxAir:.016,yOff:70,yOffGoal:70,onGround:!1,standingOn:void 0,numTouching:0,crouch:!1,spawnPos:{x:0,y:0},spawnVel:{x:0,y:0},pos:{x:0,y:0},yPosDifference:24.2859,Sy:0,Vx:0,Vy:0,friction:{ground:.01,air:.0025},airSpeedLimit:125,angle:0,walk_cycle:0,stepSize:0,flipLegs:-1,hip:{x:12,y:24},knee:{x:0,y:0,x2:0,y2:0},foot:{x:0,y:0},legLength1:55,legLength2:45,transX:0,transY:0,history:[],rewindCount:0,resetHistory(){for(let e=0;e<600;e++)m.history[e]={position:{x:player.position.x,y:player.position.y},velocity:{x:player.velocity.x,y:player.velocity.y},yOff:m.yOff,angle:m.angle,health:m.health,energy:m.energy,activeGun:b.activeGun}},move(){m.pos.x=player.position.x,m.pos.y=playerBody.position.y-m.yOff,m.Vx=player.velocity.x,m.Vy=player.velocity.y,m.history.splice(m.cycle%600,1,{position:{x:player.position.x,y:player.position.y},velocity:{x:player.velocity.x,y:player.velocity.y},yOff:m.yOff,angle:m.angle,health:m.health,energy:m.energy,activeGun:b.activeGun})},transSmoothX:0,transSmoothY:0,lastGroundedPositionY:0,lookSmoothing:.07,look(){},lookDefault(){m.angle=Math.atan2(simulation.mouseInGame.y-m.pos.y,simulation.mouseInGame.x-m.pos.x);m.transSmoothX=canvas.width2-m.pos.x-.8*(simulation.mouse.x-canvas.width2),m.transSmoothY=canvas.height2-m.pos.y-.8*(simulation.mouse.y-canvas.height2),m.transX+=(m.transSmoothX-m.transX)*m.lookSmoothing,m.transY+=(m.transSmoothY-m.transY)*m.lookSmoothing},doCrouch(){m.crouch||(m.crouch=!0,m.yOffGoal=m.yOffWhen.crouch,playerHead.position.y-player.position.y<0&&Matter.Body.setPosition(playerHead,{x:player.position.x,y:player.position.y+9.1740767}))},undoCrouch(){m.crouch&&(m.crouch=!1,m.yOffGoal=m.yOffWhen.stand,playerHead.position.y-player.position.y>0&&Matter.Body.setPosition(playerHead,{x:player.position.x,y:player.position.y-30.28592321}))},hardLandCD:0,checkHeadClear:()=>!(Matter.Query.collides(headSensor,map).length>0),buttonCD_jump:0,groundControl(){if(m.crouch?!input.down&&m.checkHeadClear()&&m.hardLandCD<m.cycle&&m.undoCrouch():input.down||m.hardLandCD>m.cycle?m.doCrouch():input.up&&m.buttonCD_jump+20<m.cycle&&m.yOffWhen.stand>23&&(m.buttonCD_jump=m.cycle,Matter.Body.applyForce(m.standingOn,m.pos,{x:0,y:.12*m.jumpForce*Math.min(m.standingOn.mass,5)}),player.force.y=-m.jumpForce,Matter.Body.setVelocity(player,{x:player.velocity.x,y:Math.max(-10,Math.min(m.standingOn.velocity.y,10))})),input.left)player.velocity.x>-2?player.force.x-=1.5*m.Fx:player.force.x-=m.Fx;else if(input.right)player.velocity.x<2?player.force.x+=1.5*m.Fx:player.force.x+=m.Fx;else{const e=.92;Matter.Body.setVelocity(player,{x:player.velocity.x*e,y:player.velocity.y*e})}if(player.speed>4){const e=m.crouch?.65:.89;Matter.Body.setVelocity(player,{x:player.velocity.x*e,y:player.velocity.y*e})}},airControl(){m.buttonCD_jump+60>m.cycle&&!input.up&&m.Vy<0&&Matter.Body.setVelocity(player,{x:player.velocity.x,y:.94*player.velocity.y}),input.left?player.velocity.x>-m.airSpeedLimit/player.mass/player.mass&&(player.force.x-=m.FxAir):input.right&&player.velocity.x<m.airSpeedLimit/player.mass/player.mass&&(player.force.x+=m.FxAir)},alive:!1,switchWorlds(){const e=b.inventory.length;let t=0;for(let e=0,o=b.inventory.length;e<o;e++)b.guns[b.inventory[e]].ammo!==1/0?t+=b.guns[b.inventory[e]].ammo/b.guns[b.inventory[e]].ammoPack:t+=5;simulation.isTextLogOpen=!1;let o=0;for(let e=0,t=tech.tech.length;e<t;e++)tech.tech[e].isJunk&&(tech.tech[e].frequency=0),tech.tech[e].count>0&&!tech.tech[e].isLore&&(tech.tech[e].frequencyDefault?tech.tech[e].frequency=tech.tech[e].frequencyDefault:tech.tech[e].frequency=1,tech.tech[e].isNonRefundable||"many-worlds"===tech.tech[e].name||"Ψ(t) collapse"===tech.tech[e].name||"non-unitary operator"===tech.tech[e].name||"-quantum leap-"===tech.tech[e].name||(o+=tech.tech[e].count,tech.tech[e].remove(),tech.tech[e].isLost=!1,tech.tech[e].count=0));tech.cancelCount=0,tech.extraMaxHealth=0,tech.totalCount=0;const i=b.totalBots();b.zeroBotCount();for(let e=0;e<bullet.length;++e)Matter.Composite.remove(engine.world,bullet[e]);bullet=[],m.health=m.health*(1+.5*(Math.random()-.5)),m.health>1&&(m.health=1),m.displayHealth(),m.setField(Math.ceil(Math.random()*(m.fieldUpgrades.length-1))),b.inventory=[],b.activeGun=null,b.inventoryGun=0;for(let e=0,t=b.guns.length;e<t;++e)b.guns[e].have=!1,b.guns[e].ammo!==1/0&&(b.guns[e].ammo=0);for(let t=0;t<e;t++)b.giveGuns();for(let e=0,o=b.inventory.length;e<o;e++)b.guns[b.inventory[e]].ammo!==1/0&&(b.guns[b.inventory[e]].ammo=Math.max(0,Math.floor(t/b.inventory.length*b.guns[b.inventory[e]].ammoPack*(1.05+.3*(Math.random()-.5)))));for(let e=0;e<o;e++){let e=[];for(let t=0,o=tech.tech.length;t<o;t++)if(tech.tech[t].count<tech.tech[t].maxCount&&tech.tech[t].allowed()&&!tech.tech[t].isBadRandomOption&&!tech.tech[t].isLore&&!tech.tech[t].isJunk)for(let o=0;o<tech.tech[t].frequency;o++)e.push(t);e.length>0&&tech.giveTech(e[Math.floor(Math.random()*e.length)])}b.respawnBots();for(let e=0;e<i;e++)b.randomBot();simulation.makeGunHUD(),simulation.updateTechHUD(),simulation.isTextLogOpen=!0,m.drop(),simulation.paused&&build.pauseGrid()},death(){if(tech.isImmortal){m.setMaxHealth(),m.health=1,simulation.wipe=function(){ctx.fillStyle="rgba(255,255,255,0)",ctx.fillRect(0,0,canvas.width,canvas.height)},spawn.setSpawnList(),simulation.clearNow=!0,m.switchWorlds();const e=1e3;for(let t=0,o=5;t<o;t++)setTimeout((function(){simulation.wipe=function(){ctx.fillStyle="rgba(255,255,255,0)",ctx.fillRect(0,0,canvas.width,canvas.height)},spawn.setSpawnList(),simulation.clearNow=!0,m.switchWorlds(),simulation.isTextLogOpen=!0,simulation.makeTextLog("simulation.amplitude <span class='color-symbol'>=</span> 0."+(o-t-1),e),simulation.isTextLogOpen=!1,simulation.wipe=function(){ctx.fillStyle=`rgba(255,255,255,${(t+1)*(t+1)*.006})`,ctx.fillRect(0,0,canvas.width,canvas.height)}}),(t+1)*e);setTimeout((function(){simulation.wipe=function(){ctx.clearRect(0,0,canvas.width,canvas.height)},simulation.isTextLogOpen=!0,simulation.makeTextLog("simulation.amplitude <span class='color-symbol'>=</span> null"),tech.isImmortal=!1}),6*e)}else m.alive&&(m.alive=!1,simulation.paused=!0,m.health=0,m.displayHealth(),document.getElementById("text-log").style.opacity=0,document.getElementById("fade-out").style.opacity=.9,setTimeout((function(){Composite.clear(engine.world),Engine.clear(engine),simulation.splashReturn()}),5e3))},health:0,maxHealth:1,drawHealth(){m.health<1&&(ctx.fillStyle="rgba(100, 100, 100, 0.5)",ctx.fillRect(m.pos.x-m.radius,m.pos.y-50,60,10),ctx.fillStyle="#f00",ctx.fillRect(m.pos.x-m.radius,m.pos.y-50,60*m.health,10))},displayHealth(){id=document.getElementById("health"),id.style.width=Math.floor(300*m.maxHealth*Math.pow(m.health/m.maxHealth,1.4))+"px",m.health<.3?id.classList.add("low-health"):id.classList.remove("low-health")},addHealth(e){tech.isEnergyHealth||(m.health+=e*simulation.healScale,m.health>m.maxHealth&&(m.health=m.maxHealth),m.displayHealth())},baseHealth:1,setMaxHealth(){m.maxHealth=m.baseHealth+tech.extraMaxHealth+tech.isFallingDamage,document.getElementById("health-bg").style.width=`${Math.floor(300*m.maxHealth)}px`,simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-h'>maxHealth</span> <span class='color-symbol'>=</span> ${m.maxHealth.toFixed(2)}`),m.health>m.maxHealth&&(m.health=m.maxHealth),m.displayHealth()},defaultFPSCycle:0,immuneCycle:0,harmReduction(){let e=1;if(e*=m.fieldHarmReduction,tech.isZeno&&(e*=.17),tech.isFieldHarmReduction&&(e*=.5),tech.isHarmMACHO&&(e*=.33),tech.isImmortal&&(e*=.66),tech.isHarmReduceNoKill&&m.lastKillCycle+300<m.cycle&&(e*=.33),tech.healthDrain&&(e*=1+3.33*tech.healthDrain),1!==tech.squirrelFx&&(e*=1+(tech.squirrelFx-1)/5),tech.isAddBlockMass&&m.isHolding&&(e*=.15),tech.isSpeedHarm&&(e*=1-Math.min(.0165*player.speed,.66)),tech.isSlowFPS&&(e*=.8),tech.isHarmReduce&&input.field&&m.fieldCDcycle<m.cycle&&(e*=.4),tech.isNeutronium&&input.field&&m.fieldCDcycle<m.cycle&&(e*=.1),tech.isBotArmor&&(e*=.92**b.totalBots()),tech.isHarmArmor&&m.lastHarmCycle+600>m.cycle&&(e*=.33),tech.isNoFireDefense&&m.cycle>m.fireCDcycle+120&&(e*=.3),0===tech.energyRegen&&(e*=.34),tech.isTurret&&m.crouch&&(e*=.34),tech.isEntanglement&&b.inventory[0]===b.activeGun)for(let t=0,o=b.inventory.length;t<o;t++)e*=.87;return e},rewind(e){if(tech.isRewindGrenade){const t=65,o=m.cycle+t+10;m.immuneCycle<o&&(m.immuneCycle=o);for(let o=1,i=Math.floor(4+e/40);o<i;o++){b.grenade(Vector.add(m.pos,{x:10*(Math.random()-.5),y:10*(Math.random()-.5)}),-o*Math.PI/i);const e=bullet[bullet.length-1];tech.isVacuumBomb?Matter.Body.setVelocity(e,{x:.5*e.velocity.x,y:.5*e.velocity.y}):tech.isRPG?e.endCycle=simulation.cycle+10:tech.isNeutronBomb?Matter.Body.setVelocity(e,{x:.3*e.velocity.x,y:.3*e.velocity.y}):(Matter.Body.setVelocity(e,{x:.5*e.velocity.x,y:.5*e.velocity.y}),e.endCycle=simulation.cycle+t)}}let t=m.history[(m.cycle-e)%600];Matter.Body.setPosition(player,t.position),Matter.Body.setVelocity(player,{x:t.velocity.x,y:t.velocity.y}),m.yOff=t.yOff,m.yOff<48?m.doCrouch():m.undoCrouch();for(let e=0;e<bullet.length;e++)bullet[e].botType&&(Matter.Body.setPosition(bullet[e],Vector.add(player.position,{x:250*(Math.random()-.5),y:250*(Math.random()-.5)})),Matter.Body.setVelocity(bullet[e],{x:0,y:0}));m.energy=Math.max(m.energy-e/150,.01),m.immuneCycle<m.cycle+tech.collisionImmuneCycles&&(m.immuneCycle=m.cycle+tech.collisionImmuneCycles);let o=!0;const i=function(){if(m.defaultFPSCycle<m.cycle)simulation.fpsCap=simulation.fpsCapDefault,simulation.fpsInterval=1e3/simulation.fpsCap,document.getElementById("dmg").style.transition="opacity 1s",document.getElementById("dmg").style.opacity="0";else if(requestAnimationFrame(i),o){o=!1,ctx.save(),ctx.translate(canvas.width2,canvas.height2),ctx.scale(simulation.zoom/simulation.edgeZoomOutSmooth,simulation.zoom/simulation.edgeZoomOutSmooth),ctx.translate(-canvas.width2+m.transX,-canvas.height2+m.transY);for(let o=1;o<e;o++)t=m.history[(m.cycle-o)%600],m.pos.x=t.position.x,m.pos.y=t.position.y+m.yPosDifference-t.yOff,m.yOff=t.yOff,m.draw();ctx.restore(),m.resetHistory()}};if(m.defaultFPSCycle<m.cycle&&requestAnimationFrame(i),simulation.fpsCap=3,simulation.fpsInterval=1e3/simulation.fpsCap,m.defaultFPSCycle=m.cycle,tech.isRewindBot){const t=.07*e*tech.isRewindBot,o=Math.floor(e/t);for(let e=0;e<t;e++){const t=m.history[Math.abs(m.cycle-e*o)%600].position;b.randomBot({x:t.x+20*(Math.random()-.5),y:t.y+20*(Math.random()-.5)},!1,!1),bullet[bullet.length-1].endCycle=simulation.cycle+480+Math.floor(120*Math.random())}}},damage(e){if(tech.isRewindAvoidDeath&&m.energy>.6){const e=Math.floor(Math.min(299,150*m.energy));return simulation.makeTextLog(`<span class='color-var'>m</span>.rewind(${e})`),void m.rewind(e)}if(m.lastHarmCycle=m.cycle,tech.isDroneOnDamage&&bullet.length<150){const t=Math.min(40*(e-.06*Math.random()),40)/tech.droneEnergyReduction;for(let e=0;e<t;e++)Math.random()<.5&&b.drone({x:m.pos.x+30*Math.cos(m.angle)+100*(Math.random()-.5),y:m.pos.y+30*Math.sin(m.angle)+100*(Math.random()-.5)})}if(tech.isEnergyHealth){if(m.energy-=e,m.energy<0||isNaN(m.energy)){if(tech.isDeathAvoid&&powerUps.research.count&&!tech.isDeathAvoidedThisLevel){tech.isDeathAvoidedThisLevel=!0,powerUps.research.changeRerolls(-1),simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span><br>${powerUps.research.count}`);for(let e=0;e<5;e++)powerUps.spawn(m.pos.x+100*(Math.random()-.5),m.pos.y+100*(Math.random()-.5),"heal",!1);m.energy=m.maxEnergy,m.immuneCycle<m.cycle+300&&(m.immuneCycle=m.cycle+300),simulation.wipe=function(){ctx.fillStyle="rgba(255,255,255,0.03)",ctx.fillRect(0,0,canvas.width,canvas.height)},setTimeout((function(){tech.maxDuplicationEvent(),simulation.wipe=function(){ctx.clearRect(0,0,canvas.width,canvas.height)}}),3e3)}else m.health=0,m.energy=0,m.death();return}}else{if(e*=m.harmReduction(),m.health-=e,m.health<0||isNaN(m.health)){if(!(tech.isDeathAvoid&&powerUps.research.count>0)||tech.isDeathAvoidedThisLevel)return m.health=0,m.displayHealth(),void m.death();tech.isDeathAvoidedThisLevel=!0,m.health=.05,powerUps.research.changeRerolls(-1),simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span>\n <br>${powerUps.research.count}`);for(let e=0;e<5;e++)powerUps.spawn(m.pos.x+100*(Math.random()-.5),m.pos.y+100*(Math.random()-.5),"heal",!1);m.immuneCycle<m.cycle+300&&(m.immuneCycle=m.cycle+300),simulation.wipe=function(){ctx.fillStyle="rgba(255,255,255,0.03)",ctx.fillRect(0,0,canvas.width,canvas.height)},setTimeout((function(){tech.maxDuplicationEvent(),simulation.wipe=function(){ctx.clearRect(0,0,canvas.width,canvas.height)}}),3e3)}m.displayHealth(),document.getElementById("dmg").style.transition="opacity 0s",document.getElementById("dmg").style.opacity=.1+Math.min(.6,4*e)}e>.06/m.holdingMassScale&&m.drop();const t=function(){m.defaultFPSCycle<m.cycle?(simulation.fpsCap=simulation.fpsCapDefault,simulation.fpsInterval=1e3/simulation.fpsCap,document.getElementById("dmg").style.transition="opacity 1s",document.getElementById("dmg").style.opacity="0"):requestAnimationFrame(t)};if(m.defaultFPSCycle<m.cycle&&requestAnimationFrame(t),tech.isSlowFPS){if(simulation.fpsCap=30,simulation.fpsInterval=1e3/simulation.fpsCap,m.defaultFPSCycle=m.cycle+20+Math.min(90,Math.floor(200*e)),tech.isHarmFreeze)for(let e=0,t=mob.length;e<t;e++)mobs.statusSlow(mob[e],450)}else e>.05?(simulation.fpsCap=4,simulation.fpsInterval=1e3/simulation.fpsCap):(simulation.fpsCap=simulation.fpsCapDefault,simulation.fpsInterval=1e3/simulation.fpsCap),m.defaultFPSCycle=m.cycle},buttonCD:0,drawLeg(e){m.angle>-Math.PI/2&&m.angle<Math.PI/2?m.flipLegs=1:m.flipLegs=-1,ctx.save(),ctx.scale(m.flipLegs,1),ctx.beginPath(),ctx.moveTo(m.hip.x,m.hip.y),ctx.lineTo(m.knee.x,m.knee.y),ctx.lineTo(m.foot.x,m.foot.y),ctx.strokeStyle=e,ctx.lineWidth=7,ctx.stroke(),ctx.beginPath(),ctx.moveTo(m.foot.x,m.foot.y),ctx.lineTo(m.foot.x-15,m.foot.y+5),ctx.moveTo(m.foot.x,m.foot.y),ctx.lineTo(m.foot.x+15,m.foot.y+5),ctx.lineWidth=4,ctx.stroke(),ctx.beginPath(),ctx.arc(m.hip.x,m.hip.y,11,0,2*Math.PI),ctx.moveTo(m.knee.x+7,m.knee.y),ctx.arc(m.knee.x,m.knee.y,7,0,2*Math.PI),ctx.moveTo(m.foot.x+6,m.foot.y),ctx.arc(m.foot.x,m.foot.y,6,0,2*Math.PI),ctx.fillStyle=m.fillColor,ctx.fill(),ctx.lineWidth=2,ctx.stroke(),ctx.restore()},calcLeg(e,t){m.hip.x=12+t,m.hip.y=24+t,m.stepSize=.8*m.stepSize+7*Math.sqrt(Math.min(9,Math.abs(m.Vx)))*m.onGround*.2;const o=.034*m.walk_cycle+e;m.foot.x=2.2*m.stepSize*Math.cos(o)+t,m.foot.y=t+1.2*m.stepSize*Math.sin(o)+m.yOff+m.height;const i=m.yOff+m.height;m.foot.y>i&&(m.foot.y=i);const l=Math.sqrt((m.hip.x-m.foot.x)*(m.hip.x-m.foot.x)+(m.hip.y-m.foot.y)*(m.hip.y-m.foot.y)),a=(m.legLength1*m.legLength1-m.legLength2*m.legLength2+l*l)/(2*l),s=Math.sqrt(m.legLength1*m.legLength1-a*a);m.knee.x=a/l*(m.foot.x-m.hip.x)-s/l*(m.foot.y-m.hip.y)+m.hip.x+t,m.knee.y=a/l*(m.foot.y-m.hip.y)+s/l*(m.foot.x-m.hip.x)+m.hip.y},draw(){},drawFlipFlop(){ctx.fillStyle=m.fillColor,m.walk_cycle+=m.flipLegs*m.Vx,ctx.save(),ctx.globalAlpha=m.immuneCycle<m.cycle?1:.5,ctx.translate(m.pos.x,m.pos.y),m.calcLeg(Math.PI,-3),m.drawLeg("#4a4a4a"),m.calcLeg(0,0),m.drawLeg("#333"),ctx.rotate(m.angle),ctx.beginPath(),ctx.arc(0,0,30,0,2*Math.PI),ctx.fillStyle=this.bodyGradient,ctx.fill(),ctx.arc(15,0,4,0,2*Math.PI),ctx.strokeStyle="#333",ctx.lineWidth=2,ctx.stroke(),ctx.beginPath(),ctx.arc(15,0,3.5,0,2*Math.PI),ctx.fillStyle=m.eyeFillColor,ctx.fill(),ctx.restore(),m.yOff=.85*m.yOff+.15*m.yOffGoal},drawDefault(){ctx.fillStyle=m.fillColor,m.walk_cycle+=m.flipLegs*m.Vx,ctx.save(),ctx.globalAlpha=m.immuneCycle<m.cycle?1:.5,ctx.translate(m.pos.x,m.pos.y),m.calcLeg(Math.PI,-3),m.drawLeg("#4a4a4a"),m.calcLeg(0,0),m.drawLeg("#333"),ctx.rotate(m.angle),ctx.beginPath(),ctx.arc(0,0,30,0,2*Math.PI),ctx.fillStyle=this.bodyGradient,ctx.fill(),ctx.arc(15,0,4,0,2*Math.PI),ctx.strokeStyle="#333",ctx.lineWidth=2,ctx.stroke(),ctx.restore(),m.yOff=.85*m.yOff+.15*m.yOffGoal},closest:{dist:1e3,index:0},isHolding:!1,isCloak:!1,throwCharge:0,fireCDcycle:0,fieldCDcycle:0,fieldMode:0,maxEnergy:1,holdingTarget:null,timeSkipLastCycle:0,blockingRecoil:4,grabPowerUpRange2:0,isFieldActive:!1,fieldRange:155,fieldShieldingScale:1,isSneakAttack:!1,duplicateChance:0,energy:0,fieldRegen:0,fieldMode:0,fieldFire:!1,fieldHarmReduction:1,holdingMassScale:0,hole:{isOn:!1,isReady:!1,pos1:{x:0,y:0},pos2:{x:0,y:0}},fieldArc:0,fieldThreshold:0,calculateFieldThreshold(){m.fieldThreshold=Math.cos(m.fieldArc*Math.PI)},setHoldDefaults(){if(tech.isFreeWormHole&&"wormhole"!==m.fieldUpgrades[m.fieldMode].name){tech.removeTech("charmed baryon")&&powerUps.directSpawn(m.pos.x,m.pos.y,"tech")}if(tech.isNeutronium&&"negative mass"!==m.fieldUpgrades[m.fieldMode].name){tech.removeTech("neutronium")&&powerUps.directSpawn(m.pos.x,m.pos.y,"tech")}m.energy<m.maxEnergy&&(m.energy=m.maxEnergy),m.fieldRegen=tech.energyRegen,m.fieldMeterColor="#0cf",m.eyeFillColor=m.fieldMeterColor,m.fieldShieldingScale=1,m.fieldBlockCD=10,m.fieldHarmReduction=1,m.isSneakAttack=!1,m.duplicateChance=0,powerUps.setDupChance(),m.grabPowerUpRange2=156e3,m.blockingRecoil=4,m.fieldRange=155,m.fieldFire=!1,m.fieldCDcycle=0,m.isCloak=!1,player.collisionFilter.mask=cat.body|cat.map|cat.mob|cat.mobBullet|cat.mobShield,m.airSpeedLimit=125,m.drop(),m.holdingMassScale=.5,m.fieldArc=.2,m.calculateFieldThreshold(),m.isBodiesAsleep=!0,m.wakeCheck(),m.hole={isOn:!1,isReady:!1,pos1:{x:0,y:0},pos2:{x:0,y:0}}},setMaxEnergy(){m.maxEnergy=(tech.isMaxEnergyTech?.5:1)+tech.bonusEnergy+tech.healMaxEnergyBonus+tech.harmonicEnergy,simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-f'>maxEnergy</span> <span class='color-symbol'>=</span> ${m.maxEnergy.toFixed(2)}`)},fieldMeterColor:"#0cf",drawFieldMeter(e="rgba(0, 0, 0, 0.4)",t=60){if(m.energy<m.maxEnergy){m.regenEnergy(),ctx.fillStyle=e;const o=m.pos.x-m.radius*m.maxEnergy,i=m.pos.y-50;ctx.fillRect(o,i,t*m.maxEnergy,10),ctx.fillStyle=m.fieldMeterColor,ctx.fillRect(o,i,t*m.energy,10)}else if(m.energy>m.maxEnergy+.05){ctx.fillStyle=e;const o=m.pos.x-m.radius*m.energy,i=m.pos.y-50;ctx.fillStyle=m.fieldMeterColor,ctx.fillRect(o,i,t*m.energy,10)}},drawFieldMeterCloaking:function(){if(m.energy<m.maxEnergy){m.regenEnergy();const e=m.pos.x-m.radius*m.maxEnergy,t=m.pos.y-50;ctx.fillStyle="rgba(0, 0, 0, 0.3)",ctx.fillRect(e,t,60*m.maxEnergy,10),ctx.fillStyle="#fff",ctx.fillRect(e,t,60*m.energy,10),ctx.beginPath(),ctx.rect(e,t,60*m.maxEnergy,10),ctx.strokeStyle=m.fieldMeterColor,ctx.lineWidth=1,ctx.stroke()}},regenEnergy:function(){m.immuneCycle<m.cycle&&(m.energy+=m.fieldRegen),m.energy<0&&(m.energy=0)},regenEnergyDefault:function(){m.immuneCycle<m.cycle&&(m.energy+=m.fieldRegen),m.energy<0&&(m.energy=0)},lookingAt(e){const t=Vector.normalise(Vector.sub(e.position,m.pos)),o={x:Math.cos(m.angle),y:Math.sin(m.angle)};return Vector.dot(o,t)>m.fieldThreshold},drop(){m.isHolding&&(m.fieldCDcycle=m.cycle+15,m.isHolding=!1,m.throwCharge=0,m.definePlayerMass()),m.holdingTarget&&(m.holdingTarget.collisionFilter.category=cat.body,m.holdingTarget.collisionFilter.mask=cat.player|cat.map|cat.body|cat.bullet|cat.mob|cat.mobBullet,m.holdingTarget=null)},definePlayerMass(e=m.defaultMass){Matter.Body.setMass(player,e),m.setMovement(),m.yOffWhen.stand=Math.max(m.yOffWhen.crouch,Math.min(49,49-6*(e-5))),m.onGround&&!m.crouch&&(m.yOffGoal=m.yOffWhen.stand)},drawHold(e,t=!0){if(e){const o=15,i=e.vertices.length-1;ctx.fillStyle="rgba(110,170,200,"+(.2+.4*Math.random())+")",ctx.lineWidth=1,ctx.strokeStyle="#000",ctx.beginPath(),ctx.moveTo(m.pos.x+o*Math.cos(m.angle),m.pos.y+o*Math.sin(m.angle)),ctx.lineTo(e.vertices[i].x,e.vertices[i].y),ctx.lineTo(e.vertices[0].x,e.vertices[0].y),ctx.fill(),t&&ctx.stroke();for(let l=0;l<i;l++)ctx.beginPath(),ctx.moveTo(m.pos.x+o*Math.cos(m.angle),m.pos.y+o*Math.sin(m.angle)),ctx.lineTo(e.vertices[l].x,e.vertices[l].y),ctx.lineTo(e.vertices[l+1].x,e.vertices[l+1].y),ctx.fill(),t&&ctx.stroke()}},holding(){m.fireCDcycle<m.cycle&&(m.fireCDcycle=m.cycle-1),m.holdingTarget?(m.energy-=m.fieldRegen,m.energy<0&&(m.energy=0),Matter.Body.setPosition(m.holdingTarget,{x:m.pos.x+70*Math.cos(m.angle),y:m.pos.y+70*Math.sin(m.angle)}),Matter.Body.setVelocity(m.holdingTarget,player.velocity),Matter.Body.rotate(m.holdingTarget,.01/m.holdingTarget.mass)):m.isHolding=!1},throwBlock(){if(m.holdingTarget){if(input.field)if(m.energy>.001)if(m.fireCDcycle<m.cycle&&(m.fireCDcycle=m.cycle),tech.isCapacitor&&m.throwCharge<4&&(m.throwCharge=4),m.throwCharge+=.5/m.holdingTarget.mass,m.throwCharge<6&&(m.energy-=.001),tech.isTokamak){const e=m.pos.x+15*Math.cos(m.angle),t=m.pos.y+15*Math.sin(m.angle),o=m.holdingTarget.vertices.length-1,i=m.throwCharge>4?.65:.06*m.throwCharge;ctx.fillStyle=`rgba(255,0,255,${i})`,ctx.beginPath(),ctx.moveTo(e,t),ctx.lineTo(m.holdingTarget.vertices[o].x,m.holdingTarget.vertices[o].y),ctx.lineTo(m.holdingTarget.vertices[0].x,m.holdingTarget.vertices[0].y),ctx.fill();for(let i=0;i<o;i++)ctx.beginPath(),ctx.moveTo(e,t),ctx.lineTo(m.holdingTarget.vertices[i].x,m.holdingTarget.vertices[i].y),ctx.lineTo(m.holdingTarget.vertices[i+1].x,m.holdingTarget.vertices[i+1].y),ctx.fill()}else{const e=m.pos.x+15*Math.cos(m.angle),t=m.pos.y+15*Math.sin(m.angle),o=m.holdingTarget.vertices.length-1,i=m.throwCharge*m.throwCharge*m.throwCharge,l=ctx.createRadialGradient(e,t,i,e,t,i+5);l.addColorStop(0,"rgba(255,50,150,0.3)"),l.addColorStop(1,"transparent"),ctx.fillStyle=l,ctx.beginPath(),ctx.moveTo(e,t),ctx.lineTo(m.holdingTarget.vertices[o].x,m.holdingTarget.vertices[o].y),ctx.lineTo(m.holdingTarget.vertices[0].x,m.holdingTarget.vertices[0].y),ctx.fill();for(let i=0;i<o;i++)ctx.beginPath(),ctx.moveTo(e,t),ctx.lineTo(m.holdingTarget.vertices[i].x,m.holdingTarget.vertices[i].y),ctx.lineTo(m.holdingTarget.vertices[i+1].x,m.holdingTarget.vertices[i+1].y),ctx.fill();const a=30,s=80*Math.min(m.throwCharge/5,1)*Math.min(.85,.8/Math.pow(m.holdingTarget.mass,.25)),r={x:s*Math.cos(m.angle),y:s*Math.sin(m.angle)};ctx.beginPath();for(let e=1,t=10;e<t+1;e++){const o=a*e/t;ctx.lineTo(m.pos.x+o*r.x,m.pos.y+o*r.y+.34*o*o)}ctx.strokeStyle="rgba(68, 68, 68, 0.15)",ctx.lineWidth=2,ctx.stroke()}else m.drop();else if(m.throwCharge>0)if(m.fieldCDcycle=m.cycle+15,m.isHolding=!1,tech.isTokamak&&m.throwCharge>4){m.throwCycle=m.cycle+180,m.immuneCycle<m.cycle&&(m.energy+=.25*Math.sqrt(m.holdingTarget.mass)*Math.min(5,m.throwCharge)),m.throwCharge=0,m.definePlayerMass();for(let e=0;e<body.length;e++)body[e]===m.holdingTarget&&(Matter.Composite.remove(engine.world,body[e]),body.splice(e,1));b.pulse(60*Math.pow(m.holdingTarget.mass,.25),m.angle)}else{m.holdingTarget.collisionFilter.category=cat.bullet,m.holdingTarget.collisionFilter.mask=cat.map|cat.body|cat.bullet|cat.mob|cat.mobBullet|cat.mobShield,tech.isBlockRestitution&&(m.holdingTarget.restitution=.999,m.holdingTarget.friction=m.holdingTarget.frictionStatic=m.holdingTarget.frictionAir=.001);const e=function(t){const o=t.position.x-player.position.x,i=t.position.y-player.position.y;t.speed<3&&o*o+i*i>1e4&&t!==m.holdingTarget?(t.collisionFilter.category=cat.body,t.collisionFilter.mask=cat.player|cat.map|cat.body|cat.bullet|cat.mob|cat.mobBullet):setTimeout(e,40,t)};setTimeout(e,200,m.holdingTarget);let t=80*Math.min(m.throwCharge/5,1)*Math.min(.85,.8/Math.pow(m.holdingTarget.mass,.25));if(0!==Matter.Query.collides(m.holdingTarget,map).length&&(t*=.7,0!==Matter.Query.ray(map,m.holdingTarget.position,m.pos).length&&(t=0)),m.throwCharge=0,m.throwCycle=m.cycle+180,Matter.Body.setVelocity(m.holdingTarget,{x:.5*player.velocity.x+Math.cos(m.angle)*t,y:.5*player.velocity.y+Math.sin(m.angle)*t}),Matter.Body.setVelocity(player,{x:player.velocity.x-Math.cos(m.angle)*t/(m.crouch?30:10)*Math.sqrt(m.holdingTarget.mass),y:player.velocity.y-Math.sin(m.angle)*t/30*Math.sqrt(m.holdingTarget.mass)}),m.definePlayerMass(),tech.isAddBlockMass){const e=function(t,o){if(t.mass<o){const i=1.05;Matter.Body.scale(t,i,i),setTimeout(e,20,t,o)}};e(m.holdingTarget,Math.min(20,3*m.holdingTarget.mass))}}}else m.isHolding=!1},drawField(){m.holdingTarget?(ctx.fillStyle="rgba(110,170,200,"+m.energy*(.05+.05*Math.random())+")",ctx.strokeStyle="rgba(110, 200, 235, "+(.3+.08*Math.random())+")"):(ctx.fillStyle="rgba(110,170,200,"+(.02+m.energy*(.15+.15*Math.random()))+")",ctx.strokeStyle="rgba(110, 200, 235, "+(.6+.2*Math.random())+")");const e=m.fieldRange;ctx.beginPath(),ctx.arc(m.pos.x,m.pos.y,e,m.angle-Math.PI*m.fieldArc,m.angle+Math.PI*m.fieldArc,!1),ctx.lineWidth=2,ctx.stroke();let t=13,o=.75*Math.PI*m.fieldArc,i=m.angle+o,l=m.pos.x+.6*e*Math.cos(i),a=m.pos.y+.6*e*Math.sin(i);ctx.quadraticCurveTo(l,a,m.pos.x+t*Math.cos(m.angle),m.pos.y+t*Math.sin(m.angle)),i=m.angle-o,l=m.pos.x+.6*e*Math.cos(i),a=m.pos.y+.6*e*Math.sin(i),ctx.quadraticCurveTo(l,a,m.pos.x+1*e*Math.cos(m.angle-Math.PI*m.fieldArc),m.pos.y+1*e*Math.sin(m.angle-Math.PI*m.fieldArc)),ctx.fill();let s=m.angle+1.7*Math.PI*m.fieldArc*(Math.random()-.5);ctx.beginPath(),t=15,ctx.moveTo(m.pos.x+t*Math.cos(m.angle),m.pos.y+t*Math.sin(m.angle)),ctx.lineTo(m.pos.x+e*Math.cos(s),m.pos.y+e*Math.sin(s)),ctx.strokeStyle="rgba(120,170,255,0.6)",ctx.lineWidth=1,ctx.stroke()},grabPowerUp(){m.fireCDcycle<m.cycle&&(m.fireCDcycle=m.cycle-1);for(let e=0,t=powerUp.length;e<t;++e){const t=m.pos.x-powerUp[e].position.x,o=m.pos.y-powerUp[e].position.y,i=t*t+o*o+10;if(i<m.grabPowerUpRange2&&(m.lookingAt(powerUp[e])||i<16e3)&&0===Matter.Query.ray(map,powerUp[e].position,m.pos).length&&(powerUp[e].force.x+=t/Math.sqrt(i)*.05*powerUp[e].mass,powerUp[e].force.y+=o/Math.sqrt(i)*.05*powerUp[e].mass-powerUp[e].mass*simulation.g,Matter.Body.setVelocity(powerUp[e],{x:.11*powerUp[e].velocity.x,y:.11*powerUp[e].velocity.y}),i<5e3&&!simulation.isChoosing&&("heal"!==powerUp[e].name||m.health!==m.maxHealth||tech.isOverHeal)))return powerUps.onPickUp(powerUp[e]),Matter.Body.setVelocity(player,{x:player.velocity.x+powerUp[e].velocity.x/player.mass*5,y:player.velocity.y+powerUp[e].velocity.y/player.mass*5}),powerUp[e].effect(),Matter.Composite.remove(engine.world,powerUp[e]),void powerUp.splice(e,1)}},pushMass(e,t=(.025+Math.sqrt(e.mass)*Vector.magnitude(Vector.sub(e.velocity,player.velocity))*.002)*m.fieldShieldingScale){if(m.energy>.2*t){if(m.energy-=t,m.energy<0&&(m.energy=0),m.fieldCDcycle=m.cycle+m.fieldBlockCD,tech.blockingIce)for(let e=0;e<60*t*tech.blockingIce;e++)b.iceIX(3,2*Math.PI*Math.random(),m.pos);const o=Vector.normalise(Vector.sub(player.position,e.position));if(tech.blockDmg){e.damage(tech.blockDmg*b.dmgScale,!0);const t=40;ctx.beginPath();for(let e=0,i=1.5*tech.blockDmg;e<i;e++){let e=m.pos.x-20*o.x,i=m.pos.y-20*o.y;ctx.moveTo(e,i);for(let l=0;l<8;l++)e+=t*(-o.x+1.5*(Math.random()-.5)),i+=t*(-o.y+1.5*(Math.random()-.5)),ctx.lineTo(e,i)}ctx.lineWidth=3,ctx.strokeStyle="#f0f",ctx.stroke()}else m.drawHold(e);tech.isStunField&&mobs.statusStun(e,tech.isStunField);const i=Math.sqrt(Math.min(12,Math.max(.15,e.mass)));Matter.Body.setVelocity(e,{x:player.velocity.x-15*o.x/i,y:player.velocity.y-15*o.y/i}),e.isOrbital&&Matter.Body.setVelocity(e,{x:0,y:0}),m.crouch?Matter.Body.setVelocity(player,{x:player.velocity.x+.1*m.blockingRecoil*o.x*i,y:player.velocity.y+.1*m.blockingRecoil*o.y*i}):Matter.Body.setVelocity(player,{x:player.velocity.x+m.blockingRecoil*o.x*i,y:player.velocity.y+m.blockingRecoil*o.y*i})}},pushMobsFacing(){for(let e=0,t=mob.length;e<t;++e)Vector.magnitude(Vector.sub(mob[e].position,m.pos))-mob[e].radius<m.fieldRange&&m.lookingAt(mob[e])&&!mob[e].isUnblockable&&0===Matter.Query.ray(map,mob[e].position,m.pos).length&&(mob[e].locatePlayer(),m.pushMass(mob[e]),mob[e].isShielded&&(m.fieldCDcycle=m.cycle+60))},lookForPickUp(){m.energy>m.fieldRegen&&(m.energy-=m.fieldRegen);const e={targetIndex:null,targetRange:150};for(let t=0,o=body.length;t<o;++t)if(0===Matter.Query.ray(map,body[t].position,m.pos).length){const o=Vector.magnitude(Vector.sub(body[t].position,m.pos)),i=m.lookingAt(body[t]);o<e.targetRange&&i&&!body[t].isNotHoldable&&(e.targetRange=o,e.targetIndex=t)}if(body[e.targetIndex]){m.holdingTarget=body[e.targetIndex],ctx.beginPath();let t=m.holdingTarget.vertices;ctx.moveTo(t[0].x,t[0].y);for(let e=1;e<t.length;e+=1)ctx.lineTo(t[e].x,t[e].y);ctx.lineTo(t[0].x,t[0].y),ctx.fillStyle="rgba(190,215,230,"+(.3+.7*Math.random())+")",ctx.fill(),ctx.globalAlpha=.2,m.drawHold(m.holdingTarget),ctx.globalAlpha=1}else m.holdingTarget=null},pickUp(){m.isHolding=!0,totalMomentum=Vector.add(Vector.mult(player.velocity,player.mass),Vector.mult(m.holdingTarget.velocity,m.holdingTarget.mass)),Matter.Body.setVelocity(player,Vector.mult(totalMomentum,1/(m.defaultMass+m.holdingTarget.mass))),m.definePlayerMass(m.defaultMass+m.holdingTarget.mass*m.holdingMassScale),m.holdingTarget.collisionFilter.category=0,m.holdingTarget.collisionFilter.mask=0},wakeCheck(){if(m.isBodiesAsleep){function e(e){for(let t=0,o=e.length;t<o;++t)Matter.Sleeping.set(e[t],!1),e[t].storeVelocity&&(Matter.Body.setVelocity(e[t],{x:e[t].storeVelocity.x,y:e[t].storeVelocity.y}),Matter.Body.setAngularVelocity(e[t],e[t].storeAngularVelocity))}m.isBodiesAsleep=!1,e(mob),e(body),e(bullet);for(let e=0,t=cons.length;e<t;e++)0===cons[e].stiffness&&(cons[e].stiffness=cons[e].storeStiffness)}},hold(){},setField(e){if(isNaN(e)){let t=!1;for(let o=0;o<m.fieldUpgrades.length;o++)if(e===m.fieldUpgrades[o].name){e=o,t=!0;break}if(!t)return}m.fieldMode=e,document.getElementById("field").innerHTML=m.fieldUpgrades[e].name,m.setHoldDefaults(),m.fieldUpgrades[e].effect(),simulation.makeTextLog(`<span class='color-var'>m</span>.setField("<span class='color-text'>${m.fieldUpgrades[m.fieldMode].name}</span>")`)},fieldUpgrades:[{name:"field emitter",description:"regen <strong>6</strong> <strong class='color-f'>energy</strong> per second<br>use it to <strong>deflect</strong> mobs and <strong>throw</strong> <strong class='color-block'>blocks</strong><br><strong class='color-f'>energy</strong> regen disabled if immune to <strong class='color-harm'>harm</strong>",effect:()=>{m.hold=function(){m.isHolding?(m.drawHold(m.holdingTarget),m.holding(),m.throwBlock()):input.field&&m.fieldCDcycle<m.cycle?(m.grabPowerUp(),m.lookForPickUp(),m.energy>.05&&(m.drawField(),m.pushMobsFacing())):m.holdingTarget&&m.fieldCDcycle<m.cycle?m.pickUp():m.holdingTarget=null,m.drawFieldMeter()}}},{name:"standing wave",description:"<strong>3</strong> oscillating <strong>shields</strong> are permanently active<br><strong>deflecting</strong> protects you in every <strong>direction</strong><br><strong>deflecting</strong> has <strong>50%</strong> less <strong>recoil</strong>",drainCD:0,effect:()=>{m.fieldBlockCD=0,m.blockingRecoil=2,m.fieldRange=175,m.fieldShieldingScale=1.3*Math.pow(.6,tech.harmonics-2),m.harmonic3Phase=()=>{const e=(.7+.3*Math.sin(m.cycle/23))*m.fieldRange*m.harmonicRadius,t=(.63+.37*Math.sin(m.cycle/37))*m.fieldRange*m.harmonicRadius,o=(.65+.35*Math.sin(m.cycle/47))*m.fieldRange*m.harmonicRadius,i=Math.max(e,t,o);ctx.fillStyle="rgba(110,170,200,"+Math.min(.73,.04+m.energy*(.11+.13*Math.random()))+")",ctx.beginPath(),ctx.arc(m.pos.x,m.pos.y,e,0,2*Math.PI),ctx.fill(),ctx.beginPath(),ctx.arc(m.pos.x,m.pos.y,t,0,2*Math.PI),ctx.fill(),ctx.beginPath(),ctx.arc(m.pos.x,m.pos.y,o,0,2*Math.PI),ctx.fill();for(let e=0,t=mob.length;e<t;++e)Vector.magnitude(Vector.sub(mob[e].position,m.pos))-mob[e].radius<i&&!mob[e].isUnblockable&&(mob[e].locatePlayer(),this.drainCD>m.cycle?m.pushMass(mob[e],0):(m.pushMass(mob[e]),this.drainCD=m.cycle+10),mob[e].isShielded&&(m.fieldCDcycle=m.cycle+45))},m.harmonicRadius=1,m.harmonicAtomic=()=>{const e=.0031*simulation.cycle,t=.023*simulation.cycle,o=m.fieldRange*m.harmonicRadius;ctx.lineWidth=1,ctx.strokeStyle="rgba(110,170,200,0.8)",ctx.fillStyle="rgba(110,170,200,"+Math.min(.7,m.energy*(.13+.1*Math.random())*(3/tech.harmonics))+")";for(let i=0;i<tech.harmonics;i++)ctx.beginPath(),ctx.ellipse(m.pos.x,m.pos.y,o*Math.abs(Math.sin(t+i/tech.harmonics*Math.PI)),o,e+i/tech.harmonics*Math.PI,0,2*Math.PI),ctx.fill(),ctx.stroke();for(let e=0,t=mob.length;e<t;++e)Vector.magnitude(Vector.sub(mob[e].position,m.pos))-mob[e].radius<o&&!mob[e].isUnblockable&&(mob[e].locatePlayer(),this.drainCD>m.cycle?m.pushMass(mob[e],0):(m.pushMass(mob[e]),this.drainCD=m.cycle+10),mob[e].isShielded&&(m.fieldCDcycle=m.cycle+45))},2===tech.harmonics?m.harmonicShield=m.harmonic3Phase:m.harmonicShield=m.harmonicAtomic,m.hold=function(){m.isHolding?(m.drawHold(m.holdingTarget),m.holding(),m.throwBlock()):input.field&&m.fieldCDcycle<m.cycle?(m.grabPowerUp(),m.lookForPickUp()):m.holdingTarget&&m.fieldCDcycle<m.cycle?m.pickUp():m.holdingTarget=null,m.energy>.1&&m.fieldCDcycle<m.cycle&&(tech.isStandingWaveExpand&&(input.field?m.harmonicRadius=.985*m.harmonicRadius+.0375:m.harmonicRadius=.995*m.harmonicRadius+.005),m.harmonicShield()),m.drawFieldMeter()}}},{name:"perfect diamagnetism",description:"<strong>attract</strong> power ups from <strong>far away</strong><br><strong>deflecting</strong> does not drain <strong class='color-f'>energy</strong><br>maintains <strong>functionality</strong> while <strong>inactive</strong>",effect:()=>{m.fieldShieldingScale=0,m.fieldBlockCD=3,m.grabPowerUpRange2=1e7,m.fieldPosition={x:m.pos.x,y:m.pos.y},m.fieldAngle=m.angle,m.perfectPush=(e=!1)=>{if(m.fieldCDcycle<m.cycle)for(let t=0,o=mob.length;t<o;++t)if(Vector.magnitude(Vector.sub(mob[t].position,m.fieldPosition))-mob[t].radius<m.fieldRange&&!mob[t].isUnblockable&&Vector.dot({x:Math.cos(m.fieldAngle),y:Math.sin(m.fieldAngle)},Vector.normalise(Vector.sub(mob[t].position,m.fieldPosition)))>m.fieldThreshold&&0===Matter.Query.ray(map,mob[t].position,m.fieldPosition).length){mob[t].locatePlayer();const o=Vector.normalise(Vector.sub(m.fieldPosition,mob[t].position));if(m.fieldCDcycle=m.cycle+m.fieldBlockCD+(mob[t].isShielded?15:0),tech.blockingIce)for(let e=0;e<2*tech.blockingIce;e++){const e=m.fieldAngle+1.55*(Math.random()-.5);b.iceIX(10,e,Vector.add(m.fieldPosition,{x:m.fieldRange*Math.cos(e),y:m.fieldRange*Math.sin(e)}))}if(tech.blockDmg){mob[t].damage(tech.blockDmg*b.dmgScale);const e=40;ctx.beginPath();for(let t=0,i=1.5*tech.blockDmg;t<i;t++){let t=m.fieldPosition.x-20*o.x,i=m.fieldPosition.y-20*o.y;ctx.moveTo(t,i);for(let l=0;l<8;l++)t+=e*(-o.x+1.5*(Math.random()-.5)),i+=e*(-o.y+1.5*(Math.random()-.5)),ctx.lineTo(t,i)}ctx.lineWidth=3,ctx.strokeStyle="#f0f",ctx.stroke()}else if(e){ctx.fillStyle="rgba(110,170,200,"+(.2+.4*Math.random())+")",ctx.lineWidth=2,ctx.strokeStyle="#000";const e=mob[t].vertices.length-1,o=mob[t].radius;ctx.beginPath(),ctx.moveTo(mob[t].vertices[e].x+o*(Math.random()-.5),mob[t].vertices[e].y+o*(Math.random()-.5));for(let i=0;i<e;i++)ctx.lineTo(mob[t].vertices[i].x+o*(Math.random()-.5),mob[t].vertices[i].y+o*(Math.random()-.5));ctx.lineTo(mob[t].vertices[e].x+o*(Math.random()-.5),mob[t].vertices[e].y+o*(Math.random()-.5)),ctx.fill(),ctx.stroke()}else{const e=15,o=mob[t].vertices.length-1;ctx.fillStyle="rgba(110,170,200,"+(.2+.4*Math.random())+")",ctx.lineWidth=1,ctx.strokeStyle="#000",ctx.beginPath(),ctx.moveTo(m.fieldPosition.x+e*Math.cos(m.fieldAngle),m.fieldPosition.y+e*Math.sin(m.fieldAngle)),ctx.lineTo(mob[t].vertices[o].x,mob[t].vertices[o].y),ctx.lineTo(mob[t].vertices[0].x,mob[t].vertices[0].y),ctx.fill(),ctx.stroke();for(let i=0;i<o;i++)ctx.beginPath(),ctx.moveTo(m.fieldPosition.x+e*Math.cos(m.fieldAngle),m.fieldPosition.y+e*Math.sin(m.fieldAngle)),ctx.lineTo(mob[t].vertices[i].x,mob[t].vertices[i].y),ctx.lineTo(mob[t].vertices[i+1].x,mob[t].vertices[i+1].y),ctx.fill(),ctx.stroke()}tech.isStunField&&mobs.statusStun(mob[t],tech.isStunField);const i=Math.sqrt(Math.max(1,mob[t].mass));if(Matter.Body.setVelocity(mob[t],{x:player.velocity.x-30*o.x/i,y:player.velocity.y-30*o.y/i}),mob[t].isOrbital&&Matter.Body.setVelocity(mob[t],{x:0,y:0}),!e&&mob[t].isDropPowerUp&&player.speed<12){const e=Math.sqrt(Math.min(10,Math.max(.2,mob[t].mass)));Matter.Body.setVelocity(player,{x:.9*player.velocity.x+.6*o.x*e,y:.9*player.velocity.y+.6*o.y*e})}}},m.hold=function(){const e=Math.sin(.022*m.cycle);if(m.fieldRange=160+12*e+100*tech.isBigField,m.fieldArc=.34+.04*e+.065*tech.isBigField,m.calculateFieldThreshold(),m.isHolding)m.drawHold(m.holdingTarget),m.holding(),m.throwBlock();else if(input.field){m.grabPowerUp(),m.lookForPickUp(),m.fieldPosition={x:m.pos.x,y:m.pos.y},m.fieldAngle=m.angle,m.holdingTarget?(ctx.fillStyle="rgba(110,170,200,"+(.06+.03*Math.random())+")",ctx.strokeStyle="rgba(110, 200, 235, "+(.35+.05*Math.random())+")"):(ctx.fillStyle="rgba(110,170,200,"+(.27+.2*Math.random()-.1*e)+")",ctx.strokeStyle="rgba(110, 200, 235, "+(.4+.5*Math.random())+")"),ctx.beginPath(),ctx.arc(m.pos.x,m.pos.y,m.fieldRange,m.angle-Math.PI*m.fieldArc,m.angle+Math.PI*m.fieldArc,!1),ctx.lineWidth=2.5-1.5*e,ctx.stroke();const t=.57+.04*e,o=(1-1.2*t)*Math.PI*m.fieldArc;let i=m.angle+o,l=m.pos.x+t*m.fieldRange*Math.cos(i),a=m.pos.y+t*m.fieldRange*Math.sin(i);ctx.quadraticCurveTo(l,a,m.pos.x+30*Math.cos(m.angle),m.pos.y+30*Math.sin(m.angle)),i=m.angle-o,l=m.pos.x+t*m.fieldRange*Math.cos(i),a=m.pos.y+t*m.fieldRange*Math.sin(i),ctx.quadraticCurveTo(l,a,m.pos.x+1*m.fieldRange*Math.cos(m.angle-Math.PI*m.fieldArc),m.pos.y+1*m.fieldRange*Math.sin(m.angle-Math.PI*m.fieldArc)),ctx.fill(),m.perfectPush()}else if(m.holdingTarget&&m.fieldCDcycle<m.cycle)m.pickUp();else if(m.holdingTarget=null,!input.field){ctx.fillStyle="rgba(110,170,200,"+(.27+.2*Math.random()-.1*e)+")",ctx.strokeStyle="rgba(110, 200, 235, "+(.4+.5*Math.random())+")",ctx.beginPath(),ctx.arc(m.fieldPosition.x,m.fieldPosition.y,m.fieldRange,m.fieldAngle-Math.PI*m.fieldArc,m.fieldAngle+Math.PI*m.fieldArc,!1),ctx.lineWidth=2.5-1.5*e,ctx.stroke();const t=.8+.06*e,o=(1-1.2*t)*Math.PI*m.fieldArc;let i=m.fieldAngle+o;ctx.quadraticCurveTo(m.fieldPosition.x+t*m.fieldRange*Math.cos(i),m.fieldPosition.y+t*m.fieldRange*Math.sin(i),m.fieldPosition.x+1*m.fieldRange*Math.cos(m.fieldAngle-Math.PI*m.fieldArc),m.fieldPosition.y+1*m.fieldRange*Math.sin(m.fieldAngle-Math.PI*m.fieldArc)),ctx.fill(),m.perfectPush(!0)}if(m.drawFieldMeter(),tech.isPerfectBrake){const t=200+140*e+150*m.energy;for(let e=0;e<mob.length;e++){if(Vector.magnitude(Vector.sub(m.pos,mob[e].position))<t){const t=mob[e].isShielded?8:4;mob[e].speed>t&&Vector.dot(mob[e].velocity,Vector.sub(m.pos,mob[e].position))>0&&Matter.Body.setVelocity(mob[e],Vector.mult(Vector.normalise(mob[e].velocity),t))}}ctx.beginPath(),ctx.arc(m.pos.x,m.pos.y,t,0,2*Math.PI),ctx.fillStyle="hsla(200,50%,61%,0.08)",ctx.fill()}}}},{name:"negative mass",description:"use <strong class='color-f'>energy</strong> to nullify <strong style='letter-spacing: 7px;'>gravity</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>55%</strong><br>hold <strong class='color-block'>blocks</strong> as if they have a lower <strong>mass</strong>",fieldDrawRadius:0,effect:()=>{m.fieldFire=!0,m.holdingMassScale=.01,m.fieldMeterColor="#333",m.eyeFillColor=m.fieldMeterColor,m.fieldHarmReduction=.45,m.fieldDrawRadius=0,m.hold=function(){if(m.airSpeedLimit=125,m.FxAir=.016,m.isHolding)m.drawHold(m.holdingTarget),m.holding(),m.throwBlock();else if(input.field&&m.fieldCDcycle<m.cycle){m.grabPowerUp(),m.lookForPickUp();const o=35e-5;if(m.energy>o){if(tech.isFlyFaster){function e(e,t,o=1.06){for(let i=0,l=e.length;i<l;++i)sub=Vector.sub(e[i].position,m.pos),dist=Vector.magnitude(sub),dist<t&&(e[i].force.y-=e[i].mass*(simulation.g*o),input.left?e[i].force.x-=m.FxAir*e[i].mass/10:input.right&&(e[i].force.x+=m.FxAir*e[i].mass/10))}m.airSpeedLimit=1e3,m.FxAir=.01,input.down?(player.force.y+=.5*player.mass*simulation.g,this.fieldDrawRadius=.97*this.fieldDrawRadius+15,e(powerUp,this.fieldDrawRadius,0),e(body,this.fieldDrawRadius,0)):input.up?(m.energy-=5*o,this.fieldDrawRadius=.97*this.fieldDrawRadius+33,player.force.y-=2.25*player.mass*simulation.g,e(powerUp,this.fieldDrawRadius,1.8),e(body,this.fieldDrawRadius,1.8)):(m.energy-=o,this.fieldDrawRadius=.97*this.fieldDrawRadius+24,player.force.y-=1.07*player.mass*simulation.g,e(powerUp,this.fieldDrawRadius),e(body,this.fieldDrawRadius))}else{function t(e,t,o=1.06){for(let i=0,l=e.length;i<l;++i)sub=Vector.sub(e[i].position,m.pos),dist=Vector.magnitude(sub),dist<t&&(e[i].force.y-=e[i].mass*(simulation.g*o))}m.airSpeedLimit=400,m.FxAir=.005,input.down?(player.force.y-=.5*player.mass*simulation.g,this.fieldDrawRadius=.97*this.fieldDrawRadius+12,t(powerUp,this.fieldDrawRadius,.7),t(body,this.fieldDrawRadius,.7)):input.up?(m.energy-=5*o,this.fieldDrawRadius=.97*this.fieldDrawRadius+25.5,player.force.y-=1.45*player.mass*simulation.g,t(powerUp,this.fieldDrawRadius,1.38),t(body,this.fieldDrawRadius,1.38)):(m.energy-=o,this.fieldDrawRadius=.97*this.fieldDrawRadius+19.5,player.force.y-=1.07*player.mass*simulation.g,t(powerUp,this.fieldDrawRadius),t(body,this.fieldDrawRadius))}m.energy<.001&&(m.fieldCDcycle=m.cycle+120,m.energy=0),input.down||input.up||input.left||input.right,Matter.Body.setVelocity(player,{x:.99*player.velocity.x,y:.98*player.velocity.y}),ctx.beginPath(),ctx.arc(m.pos.x,m.pos.y,this.fieldDrawRadius,0,2*Math.PI),ctx.fillStyle="#f5f5ff",ctx.globalCompositeOperation="difference",ctx.fill(),ctx.globalCompositeOperation="source-over"}}else m.holdingTarget&&m.fieldCDcycle<m.cycle?(m.pickUp(),this.fieldDrawRadius=0):(m.holdingTarget=null,this.fieldDrawRadius=0);m.drawFieldMeter("rgba(0,0,0,0.2)")}}},{name:"molecular assembler",description:"excess <strong class='color-f'>energy</strong> used to build <strong>drones</strong><br>use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs<br><strong>double</strong> your default <strong class='color-f'>energy</strong> regeneration",effect:()=>{m.hold=function(){if(m.energy>m.maxEnergy-.02&&m.fieldCDcycle<m.cycle&&!input.field&&bullet.length<200&&m.cycle%2)if(tech.isSporeField)if(tech.isSporeWorm){if(m.energy>.16){m.energy-=.16,b.worm({x:m.pos.x+35*Math.cos(m.angle),y:m.pos.y+35*Math.sin(m.angle)});const e=2+1*Math.random();Matter.Body.setVelocity(bullet[bullet.length-1],{x:e*Math.cos(m.angle),y:e*Math.sin(m.angle)})}}else for(let e=0,t=20*Math.random();e<t;e++){if(m.energy-=.08,!(m.energy>0)){m.energy=.001;break}b.spore(m.pos)}else tech.isMissileField?(m.energy-=.3,b.missile({x:m.pos.x,y:m.pos.y-40},-Math.PI/2+.5*(Math.random()-.5),0,1)):tech.isIceField?(m.energy-=.04,b.iceIX(1)):tech.isDroneRadioactive?(m.energy-=.8,b.droneRadioactive({x:m.pos.x+30*Math.cos(m.angle)+10*(Math.random()-.5),y:m.pos.y+30*Math.sin(m.angle)+10*(Math.random()-.5)},25)):(m.energy-=.45*tech.droneEnergyReduction,b.drone());m.isHolding?(m.drawHold(m.holdingTarget),m.holding(),m.throwBlock()):input.field&&m.fieldCDcycle<m.cycle?(m.grabPowerUp(),m.lookForPickUp(),m.energy>.05&&(m.drawField(),m.pushMobsFacing())):m.holdingTarget&&m.fieldCDcycle<m.cycle?m.pickUp():m.holdingTarget=null,m.regenEnergy(),m.drawFieldMeter()}}},{name:"plasma torch",description:"use <strong class='color-f'>energy</strong> to emit short range <strong class='color-plasma'>plasma</strong><br><strong class='color-d'>damages</strong> and <strong>pushes</strong> mobs away",set(){b.isExtruderOn=!1,tech.isExtruder?m.hold=function(){b.isExtruderOn=!1,m.isHolding?(m.drawHold(m.holdingTarget),m.holding(),m.throwBlock()):input.field&&m.fieldCDcycle<m.cycle?(m.grabPowerUp(),m.lookForPickUp(),b.extruder()):m.holdingTarget&&m.fieldCDcycle<m.cycle?m.pickUp():m.holdingTarget=null,m.drawFieldMeter("rgba(0, 0, 0, 0.2)"),input.field?b.wasExtruderOn=!0:(b.wasExtruderOn=!1,b.canExtruderFire=!0),ctx.beginPath();for(let e=1,t=bullet.length;e<t;e++)bullet[e].isWave&&(bullet[e].isBranch||bullet[e-1].isBranch?ctx.moveTo(bullet[e].position.x,bullet[e].position.y):ctx.lineTo(bullet[e].position.x,bullet[e].position.y));b.wasExtruderOn&&b.isExtruderOn&&ctx.lineTo(m.pos.x+15*Math.cos(m.angle),m.pos.y+15*Math.sin(m.angle)),ctx.lineWidth=4,ctx.strokeStyle="#f07",ctx.stroke(),ctx.lineWidth=tech.extruderRange,ctx.strokeStyle="rgba(255,0,110,0.06)",ctx.stroke()}:m.hold=function(){m.isHolding?(m.drawHold(m.holdingTarget),m.holding(),m.throwBlock()):input.field&&m.fieldCDcycle<m.cycle?(m.grabPowerUp(),m.lookForPickUp(),b.plasma()):m.holdingTarget&&m.fieldCDcycle<m.cycle?m.pickUp():m.holdingTarget=null,m.drawFieldMeter("rgba(0, 0, 0, 0.2)")}},effect(){m.fieldMeterColor="#f0f",m.eyeFillColor=m.fieldMeterColor,this.set()}},{name:"time dilation",description:"use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 1px;'>stop time</strong><br><strong>move</strong> and <strong>fire</strong> while time is stopped<br>but, <strong>collisions</strong> still do <strong class='color-harm'>harm</strong>",set(){tech.isRewindField?(this.rewindCount=0,m.grabPowerUpRange2=3e5,m.hold=function(){if(m.isHolding)m.drawHold(m.holdingTarget),m.holding(),m.throwBlock();else if(input.field&&m.fieldCDcycle<m.cycle){if(m.grabPowerUp(),0===this.rewindCount&&m.lookForPickUp(),!m.holdingTarget){this.rewindCount+=6;const e=.001;let t=m.history[(m.cycle-this.rewindCount)%600];if(this.rewindCount>599||m.energy<e)this.rewindCount=0,m.resetHistory(),m.fireCDcycle<m.cycle+60&&(m.fieldCDcycle=m.cycle+60),m.immuneCycle=m.cycle;else{ctx.globalCompositeOperation="saturation",ctx.fillStyle="#ccc",ctx.fillRect(-1e5,-1e5,2e5,2e5),ctx.globalCompositeOperation="source-over",m.energy-=e,m.immuneCycle<m.cycle+60&&(m.immuneCycle=m.cycle+60),Matter.Body.setPosition(player,t.position),Matter.Body.setVelocity(player,{x:t.velocity.x,y:t.velocity.y}),m.health<t.health&&(m.health=t.health,m.health>m.maxHealth&&(m.health=m.maxHealth),m.displayHealth()),m.yOff=t.yOff,m.yOff<48?m.doCrouch():m.undoCrouch();for(let e=0,t=powerUp.length;e<t;++e)if(Vector.magnitudeSquared(Vector.sub(m.pos,powerUp[e].position))<1e5&&!simulation.isChoosing&&("heal"!==powerUp[e].name||m.health!==m.maxHealth||tech.isOverHeal)){powerUps.onPickUp(powerUp[e]),powerUp[e].effect(),Matter.Composite.remove(engine.world,powerUp[e]),powerUp.splice(e,1);break}if(!(this.rewindCount%30)){if(tech.isRewindBot)for(let e=0;e<tech.isRewindBot;e++)b.randomBot(m.pos,!1,!1),bullet[bullet.length-1].endCycle=simulation.cycle+480+Math.floor(120*Math.random());if(tech.isRewindGrenade){b.grenade(m.pos,this.rewindCount);bullet[bullet.length-1].endCycle=simulation.cycle+60}}}}}else m.holdingTarget&&m.fieldCDcycle<m.cycle?(m.pickUp(),this.rewindCount=0):(m.holdingTarget=null,this.rewindCount=0);m.drawFieldMeter()}):(m.fieldFire=!0,m.isBodiesAsleep=!1,m.drain=5e-4,m.hold=function(){if(m.isHolding)m.wakeCheck(),m.drawHold(m.holdingTarget),m.holding(),m.throwBlock();else if(input.field&&m.fieldCDcycle<m.cycle)if(m.grabPowerUp(),m.lookForPickUp(),m.drain+=25e-7,m.energy>m.drain){function e(e){for(let t=0,o=e.length;t<o;++t)e[t].isSleeping||(e[t].storeVelocity=e[t].velocity,e[t].storeAngularVelocity=e[t].angularVelocity),Matter.Sleeping.set(e[t],!0)}m.energy-=m.drain,m.energy<m.drain&&(m.fieldCDcycle=m.cycle+120,m.energy=0,m.wakeCheck()),ctx.globalCompositeOperation="saturation",ctx.fillStyle="#ccc",ctx.fillRect(-1e5,-1e5,2e5,2e5),ctx.globalCompositeOperation="source-over",m.isBodiesAsleep=!0,e(mob),e(body),e(bullet),simulation.cycle--,tech.isTimeSkip&&(m.immuneCycle=0,m.drain+=25e-7,m.regenEnergy(),m.immuneCycle=m.cycle+10,simulation.isTimeSkipping=!0,m.cycle++,simulation.gravity(),tech.isFireMoveLock&&input.fire&&(player.force.x=0,player.force.y=0),Engine.update(engine,simulation.delta),m.move(),simulation.checks(),m.walk_cycle+=m.flipLegs*m.Vx,b.fire(),b.bulletDo(),simulation.isTimeSkipping=!1)}else m.wakeCheck();else m.holdingTarget&&m.fieldCDcycle<m.cycle?(m.wakeCheck(),m.pickUp()):(m.drain>5e-4&&(m.drain-=5e-6),m.wakeCheck(),m.holdingTarget=null);m.drawFieldMeter()})},effect(){this.set()}},{name:"metamaterial cloaking",description:"when not firing activate a <strong class='color-cloaked'>cloaking</strong> effect<br><strong>+333%</strong> <strong class='color-d'>damage</strong> if a mob hasn't recently <strong>died</strong><br><strong>collisions</strong> do <strong>50%</strong> less <strong class='color-harm'>harm</strong> when <strong class='color-cloaked'>cloaked</strong>",effect:()=>{m.fieldFire=!0,m.fieldMeterColor="#333",m.eyeFillColor=m.fieldMeterColor,m.fieldPhase=0,m.isCloak=!1,m.fieldDrawRadius=0,m.isSneakAttack=!0;m.hold=function(){if(m.isHolding?(m.drawHold(m.holdingTarget),m.holding(),m.throwBlock()):input.field&&m.fieldCDcycle<m.cycle?(m.grabPowerUp(),m.lookForPickUp()):m.holdingTarget&&m.fieldCDcycle<m.cycle?m.pickUp():m.holdingTarget=null,m.energy<.05&&m.fireCDcycle<m.cycle&&!input.fire&&(m.fireCDcycle=m.cycle),m.fireCDcycle+30<m.cycle&&!input.fire){if(!m.isCloak&&(m.isCloak=!0,tech.isIntangible))for(let e=0;e<bullet.length;e++)bullet[e].botType&&"orbit"!==bullet[e].botType&&(bullet[e].collisionFilter.mask=cat.map|cat.bullet|cat.mobBullet|cat.mobShield)}else if(m.isCloak){if(m.isCloak=!1,tech.isIntangible)for(let e=0;e<bullet.length;e++)bullet[e].botType&&"orbit"!==bullet[e].botType&&(bullet[e].collisionFilter.mask=cat.map|cat.body|cat.bullet|cat.mob|cat.mobBullet|cat.mobShield);if(tech.isCloakStun){let e=!1;const t=1.5*m.fieldDrawRadius,o=.15,i=240;if(m.energy>o){for(let o=0,l=mob.length;o<l;++o)Vector.magnitude(Vector.sub(mob[o].position,m.pos))<t&&0===Matter.Query.ray(map,mob[o].position,m.pos).length&&!mob[o].isBadTarget&&(e=!0,mobs.statusStun(mob[o],i));e&&(m.energy-=o,simulation.drawList.push({x:m.pos.x,y:m.pos.y,radius:t,color:"hsla(0,50%,100%,0.7)",time:7}))}}}function e(){m.fieldPhase+=.007;const e=.15*Math.sin(.5*m.fieldPhase);ctx.beginPath(),ctx.ellipse(m.pos.x,m.pos.y,m.fieldDrawRadius*(1-e),m.fieldDrawRadius*(1+e),m.fieldPhase,0,2*Math.PI),ctx.fillStyle="#fff",ctx.lineWidth=2,ctx.strokeStyle="#000",ctx.stroke(),ctx.globalCompositeOperation="destination-in",ctx.fill(),ctx.globalCompositeOperation="source-over",ctx.clip()}if(m.isCloak?(this.fieldRange=.9*this.fieldRange+90,m.fieldDrawRadius=.88*this.fieldRange,e()):this.fieldRange<3e3&&(this.fieldRange+=50,m.fieldDrawRadius=this.fieldRange,e()),tech.isIntangible)if(m.isCloak){player.collisionFilter.mask=cat.map;let e=Matter.Query.region(mob,player.bounds);if(e.length>0)for(let t=0;t<e.length;t++)m.energy>0&&e[t].shield&&(m.energy-=.014)}else player.collisionFilter.mask=cat.body|cat.map|cat.mob|cat.mobBullet|cat.mobShield;this.drawFieldMeterCloaking(),m.cycle>m.lastKillCycle+240&&(ctx.strokeStyle="rgba(0,0,0,0.4)",ctx.beginPath(),ctx.arc(m.pos.x,m.pos.y,28,0,2*Math.PI),ctx.lineWidth=2,ctx.stroke())}}},{name:"pilot wave",description:"use <strong class='color-f'>energy</strong> to push <strong class='color-block'>blocks</strong> with your mouse<br><strong class='color-block'>blocks</strong> can't <strong>collide</strong> with <strong>intangible</strong> mobs<br>field <strong>radius</strong> decreases out of <strong>line of sight</strong>",effect:()=>{m.fieldPhase=0,m.fieldPosition={x:simulation.mouseInGame.x,y:simulation.mouseInGame.y},m.lastFieldPosition={x:simulation.mouseInGame.x,y:simulation.mouseInGame.y},m.fieldOn=!1,m.fieldRadius=0,m.drop(),m.hold=function(){if(input.field)if(m.fieldCDcycle<m.cycle){const e=25,t={min:{x:m.fieldPosition.x-e,y:m.fieldPosition.y-e},max:{x:m.fieldPosition.x+e,y:m.fieldPosition.y+e}},o=Matter.Query.region(map,t).length;if(m.fieldOn){m.lastFieldPosition={x:m.fieldPosition.x,y:m.fieldPosition.y};const e=o?.985:.96;m.fieldPosition={x:m.fieldPosition.x*e+simulation.mouseInGame.x*(1-e),y:m.fieldPosition.y*e+simulation.mouseInGame.y*(1-e)}}else m.fieldOn=!0,m.fieldPosition={x:simulation.mouseInGame.x,y:simulation.mouseInGame.y},m.lastFieldPosition={x:m.fieldPosition.x,y:m.fieldPosition.y};for(let e=0,t=powerUp.length;e<t;++e){const t=m.fieldPosition.x-powerUp[e].position.x,o=m.fieldPosition.y-powerUp[e].position.y,i=t*t+o*o+200;if(i<m.fieldRadius*m.fieldRadius&&(m.lookingAt(powerUp[e])||i<16e3)&&(powerUp[e].force.x+=t/Math.sqrt(i)*.05*powerUp[e].mass,powerUp[e].force.y+=o/Math.sqrt(i)*.05*powerUp[e].mass-powerUp[e].mass*simulation.g,Matter.Body.setVelocity(powerUp[e],{x:.11*powerUp[e].velocity.x,y:.11*powerUp[e].velocity.y}),i<5e3&&!simulation.isChoosing&&("heal"!==powerUp[e].name||m.health!==m.maxHealth||tech.isOverHeal))){powerUps.onPickUp(powerUp[e]),powerUp[e].effect(),Matter.Composite.remove(engine.world,powerUp[e]),powerUp.splice(e,1);break}}if(m.grabPowerUp(),m.energy>.01){const e=Vector.sub(m.fieldPosition,m.lastFieldPosition),t=Vector.magnitude(e),i=Vector.mult(Vector.normalise(e),Math.min(t,60));let l,a;Matter.Query.ray(map,m.fieldPosition,player.position).length?(l=0,a=Math.max(0,o?.96-.02*t:.995)):(l=Math.max(50,250-2*t),a=.97),m.fieldRadius=m.fieldRadius*a+l*(1-a);for(let e=0,o=body.length;e<o;++e)if(Vector.magnitude(Vector.sub(body[e].position,m.fieldPosition))<m.fieldRadius&&!body[e].isNotHoldable){const o=t*body[e].mass*6e-6;if(!(m.energy>o)){m.fieldCDcycle=m.cycle+120,m.fieldOn=!1,m.fieldRadius=0;break}{m.energy-=o,Matter.Body.setVelocity(body[e],i),Matter.Body.setAngularVelocity(body[e],.8*body[e].angularVelocity);const t=Vector.sub(m.fieldPosition,body[e].position),l=Vector.mult(Vector.normalise(t),1e-4*body[e].mass*Vector.magnitude(t));body[e].force.x+=l.x,body[e].force.y+=l.y-body[e].mass*simulation.g}}ctx.beginPath();const s=.008*m.cycle;m.fieldPhase+=.2;const r=1+.06*Math.sin(m.fieldPhase),n=1-.06*Math.sin(m.fieldPhase);ctx.beginPath(),ctx.ellipse(m.fieldPosition.x,m.fieldPosition.y,1.2*m.fieldRadius*r,1.2*m.fieldRadius*n,s,0,2*Math.PI),ctx.globalCompositeOperation="exclusion",ctx.fillStyle="#fff",ctx.fill(),ctx.globalCompositeOperation="source-over",ctx.beginPath(),ctx.ellipse(m.fieldPosition.x,m.fieldPosition.y,1.2*m.fieldRadius*r,1.2*m.fieldRadius*n,s,0,2*Math.PI*m.energy/m.maxEnergy),ctx.strokeStyle="#000",ctx.lineWidth=4,ctx.stroke()}else m.fieldCDcycle=m.cycle+120,m.fieldOn=!1,m.fieldRadius=0}else m.grabPowerUp();else m.fieldOn=!1,m.fieldRadius=0;m.drawFieldMeter()}}},{name:"wormhole",description:"use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract <strong class='color-block'>blocks</strong> and power ups<br><strong>7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>",drain:0,effect:function(){m.duplicateChance=.07,m.fieldRange=0,powerUps.setDupChance(),m.hold=function(){if(m.hole.isOn){m.fieldRange=.97*m.fieldRange+.03*(50+10*Math.sin(.025*simulation.cycle));const e=m.fieldRange+30,t=Vector.add(Vector.mult(m.hole.unit,e),m.hole.pos1),o=Vector.add(Vector.mult(m.hole.unit,-e),m.hole.pos1),i=Vector.add(Vector.mult(m.hole.unit,e),m.hole.pos2),l=Vector.add(Vector.mult(m.hole.unit,-e),m.hole.pos2);ctx.beginPath(),ctx.moveTo(t.x,t.y),ctx.bezierCurveTo(m.hole.pos1.x,m.hole.pos1.y,m.hole.pos2.x,m.hole.pos2.y,i.x,i.y),ctx.lineTo(l.x,l.y),ctx.bezierCurveTo(m.hole.pos2.x,m.hole.pos2.y,m.hole.pos1.x,m.hole.pos1.y,o.x,o.y),ctx.fillStyle=`rgba(255,255,255,${200/m.fieldRange/m.fieldRange})`,ctx.fill(),ctx.beginPath(),ctx.ellipse(m.hole.pos1.x,m.hole.pos1.y,m.fieldRange,e,m.hole.angle,0,2*Math.PI),ctx.ellipse(m.hole.pos2.x,m.hole.pos2.y,m.fieldRange,e,m.hole.angle,0,2*Math.PI),ctx.fillStyle=`rgba(255,255,255,${32/m.fieldRange})`,ctx.fill();for(let e=0,t=powerUp.length;e<t;++e){const t=m.hole.pos1.x-powerUp[e].position.x,o=m.hole.pos1.y-powerUp[e].position.y,i=m.hole.pos2.x-powerUp[e].position.x,l=m.hole.pos2.y-powerUp[e].position.y;let a,s,r;if(t*t+o*o<i*i+l*l?(a=t,s=o):(a=i,s=l),r=a*a+s*s,r<6e5&&(powerUp[e].force.x+=a/r*4*powerUp[e].mass,powerUp[e].force.y+=s/r*4*powerUp[e].mass-powerUp[e].mass*simulation.g,Matter.Body.setVelocity(powerUp[e],{x:.05*powerUp[e].velocity.x,y:.05*powerUp[e].velocity.y}),r<1e3&&!simulation.isChoosing)){m.fieldRange*=.8,powerUps.onPickUp(powerUp[e]),powerUp[e].effect(),Matter.Composite.remove(engine.world,powerUp[e]),powerUp.splice(e,1);break}}const a=500,s=100,r=.97,n=.9;for(let e=0,t=body.length;e<t;e++)if(!body[e].isNotHoldable){const t=Vector.magnitude(Vector.sub(m.hole.pos1,body[e].position)),o=Vector.magnitude(Vector.sub(m.hole.pos2,body[e].position));if(t<o){if(t<a){const t=Vector.mult(Vector.normalise(Vector.sub(m.hole.pos1,body[e].position)),1),o=Vector.mult(body[e].velocity,n);if(Matter.Body.setVelocity(body[e],Vector.add(o,t)),Vector.magnitude(Vector.sub(m.hole.pos1,body[e].position))<s&&(Matter.Body.scale(body[e],r,r),body[e].mass<.05)){if(Matter.Composite.remove(engine.world,body[e]),body.splice(e,1),m.fieldRange*=.8,tech.isWormholeEnergy&&(m.energy+=.63),tech.isWormholeSpores)for(let e=0,t=Math.ceil(3*(tech.isSporeWorm?.5:1)*Math.random());e<t;e++)tech.isSporeWorm?(b.worm(Vector.add(m.hole.pos2,Vector.rotate({x:.4*m.fieldRange,y:0},2*Math.PI*Math.random()))),Matter.Body.setVelocity(bullet[bullet.length-1],Vector.mult(Vector.rotate(m.hole.unit,Math.PI/2),-5))):(b.spore(Vector.add(m.hole.pos2,Vector.rotate({x:.4*m.fieldRange,y:0},2*Math.PI*Math.random()))),Matter.Body.setVelocity(bullet[bullet.length-1],Vector.mult(Vector.rotate(m.hole.unit,Math.PI/2),-15)));break}}}else if(o<a){const t=Vector.mult(Vector.normalise(Vector.sub(m.hole.pos2,body[e].position)),1),o=Vector.mult(body[e].velocity,n);if(Matter.Body.setVelocity(body[e],Vector.add(o,t)),Vector.magnitude(Vector.sub(m.hole.pos2,body[e].position))<s&&(Matter.Body.scale(body[e],r,r),body[e].mass<.05)){if(Matter.Composite.remove(engine.world,body[e]),body.splice(e,1),m.fieldRange*=.8,tech.isWormholeEnergy&&m.immuneCycle<m.cycle&&(m.energy+=.63),tech.isWormholeSpores)for(let e=0,t=Math.ceil(3*(tech.isSporeWorm?.5:1)*Math.random());e<t;e++)tech.isSporeWorm?(b.worm(Vector.add(m.hole.pos1,Vector.rotate({x:.4*m.fieldRange,y:0},2*Math.PI*Math.random()))),Matter.Body.setVelocity(bullet[bullet.length-1],Vector.mult(Vector.rotate(m.hole.unit,Math.PI/2),5))):(b.spore(Vector.add(m.hole.pos1,Vector.rotate({x:.4*m.fieldRange,y:0},2*Math.PI*Math.random()))),Matter.Body.setVelocity(bullet[bullet.length-1],Vector.mult(Vector.rotate(m.hole.unit,Math.PI/2),15)));break}}}if(tech.isWormBullets){for(let e=0,t=bullet.length;e<t;++e)bullet[e].botType||bullet[e].isInHole||(Vector.magnitude(Vector.sub(m.hole.pos1,bullet[e].position))<m.fieldRange?(Matter.Body.setPosition(bullet[e],Vector.add(m.hole.pos2,Vector.sub(m.hole.pos1,bullet[e].position))),m.fieldRange+=5,bullet[e].isInHole=!0):Vector.magnitude(Vector.sub(m.hole.pos2,bullet[e].position))<m.fieldRange&&(Matter.Body.setPosition(bullet[e],Vector.add(m.hole.pos1,Vector.sub(m.hole.pos2,bullet[e].position))),m.fieldRange+=5,bullet[e].isInHole=!0));for(let e=0,t=mob.length;e<t;e++){if(Vector.magnitude(Vector.sub(m.hole.pos1,mob[e].position))<200){const t=Vector.mult(Vector.normalise(Vector.sub(m.hole.pos1,mob[e].position)),-.07);Matter.Body.setVelocity(mob[e],Vector.add(mob[e].velocity,t))}if(Vector.magnitude(Vector.sub(m.hole.pos2,mob[e].position))<200){const t=Vector.mult(Vector.normalise(Vector.sub(m.hole.pos2,mob[e].position)),-.07);Matter.Body.setVelocity(mob[e],Vector.add(mob[e].velocity,t))}}}}if(m.fieldCDcycle<m.cycle){const e=60,t=Vector.add(Vector.mult(Vector.normalise(Vector.sub(simulation.mouseInGame,m.pos)),50),simulation.mouseInGame),o=Vector.sub(simulation.mouseInGame,m.pos),i=Vector.magnitude(o);if(input.field){m.grabPowerUp(),tech.isWormholeMapIgnore&&0!==Matter.Query.ray(map,m.pos,t).length?this.drain=2*(.06+.006*Math.sqrt(i)):this.drain=tech.isFreeWormHole?0:.06+.006*Math.sqrt(i);const l=Vector.perp(Vector.normalise(o)),a={x:m.pos.x+30*Math.cos(m.angle),y:m.pos.y+30*Math.sin(m.angle)};m.fieldRange=.97*m.fieldRange+.03*(50+10*Math.sin(.025*simulation.cycle));const s=Vector.add(Vector.mult(l,1.5*m.fieldRange),simulation.mouseInGame),r=Vector.add(Vector.mult(l,-1.5*m.fieldRange),simulation.mouseInGame);ctx.beginPath(),ctx.moveTo(a.x,a.y),ctx.bezierCurveTo(a.x,a.y,simulation.mouseInGame.x,simulation.mouseInGame.y,s.x,s.y),ctx.moveTo(a.x,a.y),ctx.bezierCurveTo(a.x,a.y,simulation.mouseInGame.x,simulation.mouseInGame.y,r.x,r.y),i>250&&m.energy>this.drain&&(tech.isWormholeMapIgnore||0===Matter.Query.ray(map,m.pos,t).length)&&0===Matter.Query.region(map,{min:{x:simulation.mouseInGame.x-e,y:simulation.mouseInGame.y-e},max:{x:simulation.mouseInGame.x+e,y:simulation.mouseInGame.y+e}}).length?(m.hole.isReady=!0,ctx.lineWidth=1,ctx.strokeStyle="#000",ctx.stroke()):(m.hole.isReady=!1,ctx.lineWidth=1,ctx.strokeStyle="#000",ctx.lineDashOffset=30*Math.random(),ctx.setLineDash([20,40]),ctx.stroke(),ctx.setLineDash([]))}else if(m.hole.isReady&&i>250&&m.energy>this.drain&&(tech.isWormholeMapIgnore||0===Matter.Query.ray(map,m.pos,t).length)&&0===Matter.Query.region(map,{min:{x:simulation.mouseInGame.x-e,y:simulation.mouseInGame.y-e},max:{x:simulation.mouseInGame.x+e,y:simulation.mouseInGame.y+e}}).length){m.energy-=this.drain,m.hole.isReady=!1,m.fieldRange=0,Matter.Body.setPosition(player,simulation.mouseInGame),m.buttonCD_jump=0;const e=Vector.mult(Vector.normalise(o),20);Matter.Body.setVelocity(player,{x:e.x,y:e.y-4}),m.immuneCycle<m.cycle+15&&(m.immuneCycle=m.cycle+15);for(let e=0;e<bullet.length;e++)bullet[e].botType&&(Matter.Body.setPosition(bullet[e],Vector.add(player.position,{x:250*(Math.random()-.5),y:250*(Math.random()-.5)})),Matter.Body.setVelocity(bullet[e],{x:0,y:0}));if(m.hole.isOn=!0,m.hole.pos1.x=m.pos.x,m.hole.pos1.y=m.pos.y,m.hole.pos2.x=player.position.x,m.hole.pos2.y=player.position.y,m.hole.angle=Math.atan2(o.y,o.x),m.hole.unit=Vector.perp(Vector.normalise(o)),tech.isWormholeDamage){who=Matter.Query.ray(mob,m.pos,simulation.mouseInGame,100);for(let e=0;e<who.length;e++)who[e].body.alive&&(mobs.statusDoT(who[e].body,1,420),mobs.statusStun(who[e].body,360))}}}m.drawFieldMeter()}}}],isShipMode:!1,shipMode(e=.03,t=.99,o=1.15,i=.92){if(!m.isShipMode){for(let e=0;e<mob.length;e++)mob[e].freeOfWires||(mob[e].freeOfWires=!0);m.isShipMode=!0;const l=[{x:29.979168754143455,y:4.748337243898336},{x:27.04503734408824,y:13.7801138209198},{x:21.462582474874278,y:21.462582475257523},{x:13.780113820536943,y:27.045037344471485},{x:4.74833724351507,y:29.979168754526473},{x:-4.748337245049098,y:29.979168754526473},{x:-13.780113822071026,y:27.045037344471485},{x:-21.46258247640829,y:21.462582475257523},{x:-27.045037345621797,y:13.7801138209198},{x:-29.979168755677012,y:4.748337243898336},{x:-29.979168755677012,y:-4.7483372446656045},{x:-27.045037345621797,y:-13.78011382168726},{x:-21.46258247640829,y:-21.462582476024817},{x:-13.780113822071026,y:-27.045037345239006},{x:-4.748337245049098,y:-29.97916875529422},{x:4.74833724351507,y:-29.97916875529422},{x:13.780113820536943,y:-27.045037345239006},{x:21.462582474874278,y:-21.462582476024817},{x:27.04503734408824,y:-13.78011382168726},{x:29.979168754143455,y:-4.7483372446656045}];Matter.Body.setVertices(player,Matter.Vertices.create(l,player)),player.parts.pop(),player.parts.pop(),player.parts.pop(),player.parts.pop(),m.defaultMass=30,Matter.Body.setMass(player,m.defaultMass),player.friction=.01,player.restitution=.2,m.spin=0,m.onGround=!1,m.airControl=()=>{player.force.y-=player.mass*simulation.g,Matter.Body.setVelocity(player,{x:t*player.velocity.x,y:t*player.velocity.y}),input.up?(player.force.x+=e*Math.cos(m.angle)*tech.squirrelJump,player.force.y+=e*Math.sin(m.angle)*tech.squirrelJump):input.down&&(player.force.x-=.6*e*Math.cos(m.angle),player.force.y-=.6*e*Math.sin(m.angle)),Matter.Body.setAngularVelocity(player,player.angularVelocity*i),input.right?player.torque+=o:input.left&&(player.torque-=o),m.angle+=m.spin,m.angle=player.angle},level.playerExitCheck=()=>{player.position.x>level.exit.x&&player.position.x<level.exit.x+100&&player.position.y>level.exit.y-150&&player.position.y<level.exit.y+40&&level.nextLevel()},m.move=()=>{m.pos.x=player.position.x,m.pos.y=player.position.y,m.Vx=player.velocity.x,m.Vy=player.velocity.y,m.history.splice(m.cycle%600,1,{position:{x:player.position.x,y:player.position.y},velocity:{x:player.velocity.x,y:player.velocity.y},yOff:m.yOff,angle:m.angle,health:m.health,energy:m.energy,activeGun:b.activeGun})},m.look=()=>{m.transSmoothX=canvas.width2-m.pos.x-.8*(simulation.mouse.x-canvas.width2),m.transSmoothY=canvas.height2-m.pos.y-.8*(simulation.mouse.y-canvas.height2),m.transX+=.07*(m.transSmoothX-m.transX),m.transY+=.07*(m.transSmoothY-m.transY)},simulation.camera=()=>{const e=simulation.mouse.x/window.innerWidth-.5,t=simulation.mouse.y/window.innerHeight-.5,o=Math.max(e*e,t*t);simulation.edgeZoomOutSmooth=.04*(1+4*o*o)+.96*simulation.edgeZoomOutSmooth,ctx.save(),ctx.translate(canvas.width2,canvas.height2),ctx.scale(simulation.zoom/simulation.edgeZoomOutSmooth,simulation.zoom/simulation.edgeZoomOutSmooth),ctx.translate(-canvas.width2+m.transX,-canvas.height2+m.transY),simulation.mouseInGame.x=(simulation.mouse.x-canvas.width2)/simulation.zoom*simulation.edgeZoomOutSmooth+canvas.width2-m.transX,simulation.mouseInGame.y=(simulation.mouse.y-canvas.height2)/simulation.zoom*simulation.edgeZoomOutSmooth+canvas.height2-m.transY},m.draw=()=>{if(ctx.save(),ctx.globalAlpha=m.immuneCycle<m.cycle?1:.5,ctx.translate(player.position.x,player.position.y),ctx.rotate(player.angle),input.up)(e=ctx.createLinearGradient(0,0,-150,0)).addColorStop(0,"rgba(150, 200, 255, 0.7)"),e.addColorStop(1,"rgba(150, 200, 255, 0)"),ctx.fillStyle=e,ctx.beginPath(),ctx.moveTo(-18,-25),ctx.lineTo(-18,25),ctx.lineTo(-50-100*Math.random(),0),ctx.fill();else if(input.down){var e;(e=ctx.createLinearGradient(0,0,80,0)).addColorStop(0,"rgba(150, 200, 255, 0.7)"),e.addColorStop(1,"rgba(150, 200, 255, 0)"),ctx.fillStyle=e,ctx.beginPath(),ctx.moveTo(20,-16),ctx.lineTo(20,16),ctx.lineTo(35+43*Math.random(),0),ctx.fill()}ctx.beginPath(),ctx.arc(0,0,30,0,2*Math.PI),ctx.fillStyle=this.bodyGradient,ctx.fill(),ctx.arc(15,0,4,0,2*Math.PI),ctx.strokeStyle="#333",ctx.lineWidth=2,ctx.stroke(),ctx.restore()},collisionChecks=e=>{const t=e.pairs;for(let e=0,i=t.length;e!=i;e++)for(let i=0;i<mob.length;i++)if(mob[i].alive&&m.alive){if(t[e].bodyA===mob[i]){o(t[e].bodyB);break}if(t[e].bodyB===mob[i]){o(t[e].bodyA);break}function o(o){if(m.immuneCycle<m.cycle&&o===player&&!mob[i].isSlowed&&!mob[i].isStunned){mob[i].foundPlayer();let o=Math.min(Math.max(.025*Math.sqrt(mob[i].mass),.05),.3)*simulation.dmgScale;if(tech.isRewindAvoidDeath&&m.energy>.66)return void m.damage(o);m.damage(o),tech.isPiezo&&(m.energy+=20.48),tech.isStimulatedEmission&&powerUps.ejectTech(),mob[i].onHit&&mob[i].onHit(i),m.immuneCycle<m.cycle+tech.collisionImmuneCycles&&(m.immuneCycle=m.cycle+tech.collisionImmuneCycles);let l=Math.atan2(player.position.y-mob[i].position.y,player.position.x-mob[i].position.x);return Matter.Body.setVelocity(player,{x:player.velocity.x+8*Math.cos(l),y:player.velocity.y+8*Math.sin(l)}),Matter.Body.setVelocity(mob[i],{x:mob[i].velocity.x-8*Math.cos(l),y:mob[i].velocity.y-8*Math.sin(l)}),void(tech.isAnnihilation&&!mob[i].shield&&!mob[i].isShielded&&!mob[i].isBoss&&mob[i].isDropPowerUp&&m.energy>.34*m.maxEnergy?(m.energy-=.33*Math.max(m.maxEnergy,m.energy),m.immuneCycle=0,mob[i].death(),simulation.drawList.push({x:t[e].activeContacts[0].vertex.x,y:t[e].activeContacts[0].vertex.y,radius:2e3*o,color:"rgba(255,0,255,0.2)",time:simulation.drawTime})):simulation.drawList.push({x:t[e].activeContacts[0].vertex.x,y:t[e].activeContacts[0].vertex.y,radius:500*o,color:simulation.mobDmgColor,time:simulation.drawTime}))}if("bullet"===o.classType&&o.speed>o.minDmgSpeed){o.beforeDmg(mob[i]);let l=b.dmgScale*(o.dmg+.15*o.mass*Vector.magnitude(Vector.sub(mob[i].velocity,o.velocity)));return tech.isCrit&&mob[i].isStunned&&(l*=4),mob[i].damage(l),mob[i].alive&&mob[i].foundPlayer(),void(mob[i].damageReduction&&simulation.drawList.push({x:t[e].activeContacts[0].vertex.x,y:t[e].activeContacts[0].vertex.y,radius:40*Math.log(l+1.1)*mob[i].damageReduction+3,color:simulation.playerDmgColor,time:simulation.drawTime}))}if("body"===o.classType&&o.speed>6){const l=Vector.magnitude(Vector.sub(mob[i].velocity,o.velocity));if(l>9){let a=tech.blockDamage*b.dmgScale*l*o.mass*(tech.isMobBlockFling?2:1);if(mob[i].isShielded&&(a*=.7),mob[i].damage(a,!0),tech.isBlockPowerUps&&!mob[i].alive&&mob[i].isDropPowerUp&&m.throwCycle>m.cycle){let e=tech.isEnergyNoAmmo?"heal":"ammo";Math.random()<.4?e="heal":Math.random()<.4&&!tech.isSuperDeterminism&&(e="research"),powerUps.spawn(mob[i].position.x,mob[i].position.y,e)}const s=a/Math.sqrt(o.mass);return s>.5&&mobs.statusStun(mob[i],30+60*Math.sqrt(s)),mob[i].alive&&mob[i].distanceToPlayer2()<1e6&&!m.isCloak&&mob[i].foundPlayer(),tech.fragments&&o.speed>10&&!o.hasFragmented&&(o.hasFragmented=!0,b.targetedNail(o.position,4*tech.fragments)),void(mob[i].damageReduction&&simulation.drawList.push({x:t[e].activeContacts[0].vertex.x,y:t[e].activeContacts[0].vertex.y,radius:40*Math.log(a+1.1)*mob[i].damageReduction+3,color:simulation.playerDmgColor,time:simulation.drawTime}))}}}}}}}};