const Quat = new Box3Quaternion(0,0,0,1); const PI2 = Math.PI * 2; const ITEM ={ 0: { name: '剑星耀月', type: 0, effect: { 'action0'({entity}){ if(world.currentTick - entity.lastAttack < 4)return; entity.sound({ sample: 'audio/sword1.mp3', position: entity.position, gain: 0.5, }) entity.lastAttack = world.currentTick; const d = entity.raycast.direction; const sword = world.createEntity({ mesh: 'mesh/剑气主体.vb', position: entity.position.add({x: 0,y: 0.1,z: 0}), meshScale: [0.03,0.03,0.03], collides: false, meshOrientation: Quat.rotateX(Math.atan2(d.y,Math.sqrt(d.x ** 2 + d.z ** 2))).rotateY(Math.atan2(d.z,d.x)), velocity: d.scale(2), gravity: false, friction: 10, }) sword.addTag('entity'); sword.addTag('bullet'); sword.shooter = entity; sword.attacker = entity; sword.update = ITEM[0].update; }, async'action1'({entity}){ if(world.currentTick - entity.lastSkill < 70)return; entity.lastSkill = Infinity; entity.lastAttack = Infinity; entity.player.enableJump = false; entity.isHurtable = false; entity.velocity.y = 2; await sleep(1000); entity.addTag('entity'); entity.mesh = 'mesh/下落攻击.vb'; entity.update = ITEM[0].falling; entity.meshEmissive = 1; entity.player.invisible = true; entity.velocity.y = -3; initParticle(entity); Object.assign(entity,{ particleRate: 200, particleLifetime: 2, particleSize: [8,6,4,2,0.5], particleColor: [ new Box3RGBColor(100,100,100), new Box3RGBColor(100,100,100), new Box3RGBColor(100,100,100), new Box3RGBColor(100,100,100), new Box3RGBColor(100,100,100), ], }) entity.attacked = false; entity.event = entity.onVoxelContact(ITEM[0].boom); } }, falling: function(){ if(this.player.moveState === Box3PlayerMoveState.GROUND){ ITEM[0].boom({entity: this,axis:{x: 0,y: 1,z: 0}}); } }, boom({entity,axis}){ if(axis.y === 1 && !entity.attacked){ entity.removeTag('entity'); entity.lastSkill = world.currentTick; entity.lastAttack = world.currentTick - 5; entity.event.cancel(); entity.mesh = ''; entity.particleRate = 0; entity.player.invisible = false; entity.isHurtable = true; entity.player.enableJump = true; ITEM[0].explode(entity,new Box3Vector3(entity.position.x,entity.position.y - entity.bounds.y,entity.position.z)); } }, update: function(){ if(voxels.getVoxel(this.position.x,this.position.y,this.position.z)){ this.destroy(); } for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter && (e.position.distance(this.position) < 3 || getBounds(e).contains(this.position)) && !e.hasTag('unhurtable') && isHurtable(this.shooter,e)){ e.hurt(20,{attacker: this.shooter,damageType: '剑'}); this.destroy(); } } this.meshScale.x *= 0.99; this.meshScale.y *= 0.99; this.meshScale.z *= 0.99; if(this.meshScale.x < 0.005){ this.destroy(); } }, explode: function(entity,position){ entity.sound('audio/地动.mp3'); for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(entity.position) < 10 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(entity.position,e.position)){ e.hurt(95,{attacker: entity,damageType: '星殒下落击'}); const direction = e.position.sub(entity.position).add({x: 0,y: 2,z: 0}); e.velocity.addEq(direction.scale(5 / direction.mag()** 2 / e.mass * 1.75)); } } const ring = world.createEntity({ mesh: 'mesh/石阵.vb', meshScale: [0.005,0.005,0.005], position, collides: false, gravity: false, }) ring.state = 0; ring.scale = 0.005; ring.addTag('entity'); ring.update = ITEM[0].explodeUpdate; }, explodeUpdate: function(){ switch(this.state){ case 0: this.scale += 0.003; this.meshScale.x = this.scale; this.meshScale.z = this.scale; if(this.scale > 0.05){ this.state = 1; } break; case 1: this.meshScale.x *= 0.8; this.meshScale.z *= 0.8; if(this.meshScale.x < 0.005){ this.destroy(); } break; } }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/坚岩剑.vb', scale: [0.4,0.4,0.4], orientation: Quat.rotateZ(Math.PI * 0.8), offset: [0,-0.5,0.6], } ], }, 1: { name: '陨铁炽矛', type: 0, effect: { async'action0'({entity}){ if(world.currentTick - entity.lastAttack < 15)return; entity.lastAttack = world.currentTick; entity.addTag('entity'); const angle = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); const direction = new Box3Vector3(Math.cos(angle),0,Math.sin(angle)); Object.assign(entity,{ particleRate: 50, particleLifetime: 1, particleSize: [8,6,4,2,0.5], particleColor: [ new Box3RGBColor(100,100,100), new Box3RGBColor(100,100,100), new Box3RGBColor(100,100,100), new Box3RGBColor(100,100,100), new Box3RGBColor(100,100,100), ], }) entity.update = ITEM[1].update; entity.velocity.x = direction.x * 5; entity.velocity.z = direction.z * 5; await sleep(800); entity.particleRate = 0; }, async'action1'({entity}){ if(world.currentTick - entity.lastSkill < 70)return; entity.lastSkill = Infinity; entity.lastAttack = Infinity; entity.isHurtable = false; const bullet = world.createEntity({ mesh: 'mesh/单元方块.vb', position: entity.position, gravity: false, meshScale: [0.0625,0.0625,0.0625], meshColor: [0,0,0,0], particleRate: 50, particleLifetime: 2, particleSize: [8,6,4,2,0.5], friction: 10, particleColor: [ new Box3RGBColor(100,100,100), new Box3RGBColor(100,100,100), new Box3RGBColor(100,100,100), new Box3RGBColor(100,100,100), new Box3RGBColor(100,100,100), ], }) const show = world.createEntity({ mesh: 'mesh/破魂枪.vb', position: entity.position, gravity: false, meshScale: [0.01,0.01,0.01], meshEmissive: 1, collides: false, }) entity.player.cameraEntity = bullet; for(const e of entity.watchers){ e.player.cameraEntity = bullet; } bullet.addTag(entity.player.userKey); entity.angle = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); entity.sound('audio/起飞.mp3'); entity.up = 1; show.meshOrientation = Quat.rotateX(entity.up - Math.PI * 0.5).rotateY(entity.angle); entity.bullet = bullet; entity.show = show; bullet.shooter = entity; bullet.addTag('bullet'); entity.addTag('entity'); entity.update = ITEM[1].flying; entity.player.invisible = true; entity.player.showName = false; entity.enableDamage = false; bullet.onVoxelContact(bullet.destroy); bullet.onEntityContact(bullet.destroy); setTimeout(bullet.destroy,20000); bullet.onDestroy(()=>{ ITEM[1].end_fly(entity); }) } }, end_fly: function(entity){ entity.lastSkill = world.currentTick; entity.lastAttack = world.currentTick - 10; entity.show.destroy(); entity.position.copy(entity.bullet.position); entity.player.cameraEntity = entity; entity.isHurtable = true; entity.player.invisible = false; entity.player.showName = true; entity.enableDamage = true; for(const e of entity.watchers){ e.player.cameraEntity = entity; } if(entity.hp){ entity.sound('audio/explode.mp3'); for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(entity.position) < 10 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(entity.position,e.position)){ e.hurt(60,{attacker: entity,damageType: '巡航陨落矛'}); const direction = e.position.sub(entity.position).add({x: 0,y: 1,z: 0}); e.velocity.addEq(direction.scale(5 / direction.mag()** 2 / e.mass * 1.75)); } } const ball = world.createEntity({ mesh: 'mesh/光球.vb', position: entity.position, gravity: false, collides: false, meshScale: [0.005,0.005,0.005], }) ball.addTag('entity'); ball.update = ITEM[1].explodeUpdate; } }, explodeUpdate: function(){ this.meshScale.x += 0.01; this.meshScale.y += 0.01; this.meshScale.z += 0.01; if(this.meshScale.x > 0.07){ this.destroy(); } }, flying: function(){ this.direction = Math.atan2(this.player.facingDirection.z,this.player.facingDirection.x); rotate(this); const up = -this.player.cameraPitch; if(this.up > up){ this.up -= 0.1; } this.show.meshOrientation = Quat.rotateX(this.up - Math.PI * 0.5).rotateY(this.angle); if(this.show.position.distance(this.bullet.position) > 0.1){ this.show.position.copy(this.bullet.position); } this.bullet.velocity.set(Math.cos(this.angle)* Math.cos(this.up),Math.sin(this.up),Math.sin(this.angle)* Math.cos(this.up)); this.show.velocity.copy(this.bullet.velocity); }, update: function(){ if(world.currentTick - this.lastAttack > 6){ this.removeTag('entity'); } for(const e of world.querySelectorAll`.target`){ if(e !== this && e.position.distance(this.position) < 4 && !e.hasTag('unhurtable') && isHurtable(this,e) && spread(this.position,e.position)){ e.hurt(20,{attacker: this,damageType: '炽陨矛冲击'}); e.velocity.addEq(this.velocity.scale(1.75 / e.mass)); } } }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/破魂枪.vb', scale: [0.2,0.2,0.2], orientation: Quat.rotateX(Math.PI * 0.5).rotateY(Math.PI * 0.5).rotateZ(Math.PI * 0.8), offset: [0,-0.5,0.6], } ], }, 2: { name: '蓄能激光炮', type: 1, effect: { 'action0'({entity}){ if(world.currentTick - entity.lastAttack < 10 ||(entity.bullet && !entity.bullet.destroyed && entity.bullet instanceof Box3Entity))return; entity.lastAttack = Infinity; entity.addTag('entity'); entity.power = 0; entity.update = ITEM[2].update; entity.bullet = entity.player.addWearable({ bodyPart: Box3BodyPart.TORSO, mesh: 'mesh/光球.vb', offset: [0,0.3,2], scale: [0,0,0], }) entity.event = entity.player.onRelease(({button,raycast })=>{ if(button === Box3ButtonType.ACTION0){ entity.raycast = raycast; ITEM[2].shoot(entity); } }) }, 'action1'({entity }){ if(world.currentTick - entity.lastSkill > 200){ entity.lastSkill = world.currentTick; entity.superPower = world.currentTick; } } }, update: function(){ if(this.weapon !== 2){ ITEM[2].shoot(this); } this.power++; if(this.power > 20){ this.power = 20; } if(world.currentTick - this.superPower < 100){ this.bullet.color.set(1,0.01,1); }else{ this.bullet.color.set(1,1,1); } this.bullet.scale = [this.power * 0.01,this.power * 0.01,this.power * 0.01]; }, shoot(entity){ if(entity.lastAttack !== Infinity || entity.weapon !== 2)return; entity.removeTag('entity'); if(!(entity.bullet instanceof Box3Entity)){ entity.bullet.remove(); } entity.lastAttack = world.currentTick; if(entity.power < 5)return; const superPower =(world.currentTick - entity.superPower < 100); const bullet = world.createEntity({ mesh: 'mesh/光球.vb', position: entity.position, gravity: false, meshScale: [entity.power * 0.0003125,entity.power * 0.0003125,entity.power * 0.0003125], velocity: entity.raycast.direction.scale(3), friction: 10, meshColor: superPower? [1,0.01,1,1]:[1,1,1,1], }) if(superPower){ Object.assign(bullet,{ particleRate: 50, particleLifetime: 2, particleColor: [ new Box3RGBColor(0.033,1,10), new Box3RGBColor(10,0.025,10), new Box3RGBColor(0.05,1,10), new Box3RGBColor(10,0.5,10), new Box3RGBColor(0.2,1,10), ], }) } bullet.addTag(entity.player.userKey); bullet.shooter = entity; bullet.addTag('bullet'); bullet.onVoxelContact(bullet.destroy); bullet.onEntityContact(bullet.destroy); setTimeout(bullet.destroy,20000); bullet.onDestroy(()=>{ if(entity.power > 12){ const ball = world.createEntity({ mesh: 'mesh/光球.vb', position: bullet.position, gravity: false, collides: false, meshScale: [0.005,0.005,0.005], meshColor: superPower ? [1,0.01,1,1] : [1,1,1,1], }) ball.addTag('entity'); ball.update = ITEM[1].explodeUpdate; } for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(bullet.position) < 10 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(bullet.position,e.position)){ e.hurt((superPower ? 4.5 : 2.25)* entity.power,{attacker: entity,damageType: superPower? '光之神力风暴':'光之能量风暴'}); const direction = e.position.sub(bullet.position).add({x: 0,y: 1,z: 0}); e.velocity.addEq(direction.scale(3 / direction.mag()** 2 / e.mass * 1.75)); } } }) }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/枪-9.vb', scale: [0.4,0.4,0.4], orientation: Quat.rotateX(Math.PI).rotateZ(Math.PI * 0.8), offset: [0,-0.6,0.7], } ], }, 3: { name: '急冻法杖', type: 2, effect: { 'action0'({entity}){ if(world.currentTick - entity.lastAttack < 30)return; entity.lastAttack = world.currentTick; const up = Math.atan2(entity.raycast.direction.y,Math.sqrt(entity.raycast.direction.x ** 2 + entity.raycast.direction.z ** 2)); const angle = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); entity.sound('audio/冰杖.mp3'); for(let i = 0; i < 5; i++){ const a = angle + 0.1 *(i - 2); const direction = new Box3Vector3(Math.cos(a)* Math.cos(up),Math.sin(up),Math.sin(a)* Math.cos(up)); const bullet = world.createEntity({ mesh: 'mesh/冰锥.vb', position: entity.position, gravity: false, meshScale: [0.03,0.03,0.03], velocity: direction.scale(3), meshOrientation: Quat.rotateX(up).rotateY(a), friction: 10, meshEmissive: 0.1, particleRate: 20, particleLifetime: 0.75, particleSize: [2,0.65,0.23], particleColor: [ new Box3RGBColor(0,0,10), new Box3RGBColor(0,10,10), new Box3RGBColor(10,10,10), ], }) bullet.addTag(entity.player.userKey); bullet.shooter = entity; bullet.addTag('bullet'); bullet.onVoxelContact(bullet.destroy); bullet.onEntityContact(({other})=>{ if(isHurtable(entity,other)){ other.hurt(30,{attacker: entity,damageType: '严寒冰锥雨'}); if(other.isPlayer){ other.lastBloodDamage = world.currentTick; other.bloodDamagetime += 50; if(other.bloodDamagetime > 200){ other.bloodDamagetime = 200; } } } bullet.destroy(); }) bullet.onDestroy(()=>{ ITEM[3].sputtering(entity,bullet.position); }) setTimeout(bullet.destroy,20000); } }, async'action1'({entity}){ if(world.currentTick - entity.lastSkill < 50)return; entity.lastSkill = world.currentTick; const angle = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); const center = entity.position.add({x: Math.cos(angle)* 20,y: 0,z: Math.sin(angle)* 20}); for(let i = 0; i < 5; i++){ const position = center.add({x: Math.random()* 10 - 5,y: 5 + Math.random()* 2,z: Math.random()* 10 - 5}); const bullet = world.createEntity({ mesh: 'mesh/下落冰锥.vb', position, meshScale: [0.0625,0.0625,0.0625], meshOrientation: Quat.rotateY(Math.random()* Math.PI * 2), friction: 10, meshEmissive: 0.1, particleRate: 30, particleLifetime: 0.75, particleSize: [2,0.65,0.23], particleColor: [ new Box3RGBColor(0,0,10), new Box3RGBColor(0,10,10), new Box3RGBColor(10,10,10), ], }) bullet.shooter = entity; bullet.addTag(entity.player.userKey); bullet.addTag('bullet'); bullet.onVoxelContact(bullet.destroy); bullet.onEntityContact(bullet.destroy); bullet.onDestroy(ITEM[3].boom); setTimeout(bullet.destroy,20000); await sleep(100); } } }, sputtering(entity,position){ for(const e of world.querySelectorAll`.target`){ if(entity !== e && e.position.distance(position) < 5 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(position,e.position)){ e.hurt(15,{attacker: entity,damageType: '破碎冰晶'}); if(e.isPlayer){ e.lastBloodDamage = world.currentTick; e.bloodDamagetime += 20; if(e.bloodDamagetime > 200){ e.bloodDamagetime = 200; } } } } }, boom({entity}){ const snowflake = world.createEntity({ mesh: 'mesh/雪花.vb', position: entity.position.sub({x: 0,y: entity.bounds.y,z: 0}), gravity: false, collides: false, meshScale: [0.2,0.005,0.2], }) world.sound({ sample: 'audio/冰杖.mp3', position: snowflake.position, radius: 320, }) for(const e of world.querySelectorAll`.target`){ if(e !== entity.shooter && !e.hasTag('unhurtable') && e.position.distance(snowflake.position) < 10 && isHurtable(entity.shooter,e)){ e.hurt(45,{attacker: entity.shooter,damageType: '冰封领域'}); if(e.isPlayer){ e.lastBloodDamage = world.currentTick; e.bloodDamagetime += 100; if(e.bloodDamagetime > 200){ e.bloodDamagetime = 200; } } } } setTimeout(snowflake.destroy,500); }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/急冻法杖.vb', scale: [0.4,0.4,0.4], orientation: Quat.rotateX(Math.PI).rotateZ(Math.PI * 0.8), offset: [0,-0.4,0.4], } ], }, 4: { name: '烈焰法杖', type: 2, effect: { 'action0'({entity}){ if(entity.player.crouchButton){ if(world.currentTick - entity.lastSkill < 100)return; entity.lastSkill = world.currentTick; entity.sound('audio/火球.mp3'); const up = Math.atan2(entity.raycast.direction.y,Math.sqrt(entity.raycast.direction.x ** 2 + entity.raycast.direction.z ** 2)); const a = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); const velocity = new Box3Vector3(Math.cos(a)* Math.cos(up),Math.sin(up),Math.sin(a)* Math.cos(up)).scale(3.5); const fireball = world.createEntity({ mesh: 'mesh/火球.vb', position: entity.position, meshScale: [0.05,0.05,0.05], velocity, collides: false, gravity: false, fixed: true, meshEmissive: 0.2, particleRate: 70, particleSize: [2,4,8,4,10], particleColor: [ new Box3RGBColor(10,9,2), new Box3RGBColor(5,0.25,0.1), new Box3RGBColor(3,0.05,0.05), new Box3RGBColor(0,0,0), new Box3RGBColor(0,0,0), ], particleLifetime: 1.5, particleVelocitySpread: new Box3Vector3(0.7,0.7,0.7), }) fireball.addTag(entity.player.userKey); fireball.addTag('bullet'); fireball.addTag('entity'); fireball.update = ITEM[4].quickFly; fireball.vel = velocity; fireball.shooter = entity; setTimeout(fireball.destroy,20000); }else{ if(world.currentTick - entity.lastAttack < 20)return; entity.lastAttack = world.currentTick; entity.sound('audio/火球.mp3'); const up = Math.atan2(entity.raycast.direction.y,Math.sqrt(entity.raycast.direction.x ** 2 + entity.raycast.direction.z ** 2)); const a = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); const velocity = new Box3Vector3(Math.cos(a)* Math.cos(up),Math.sin(up),Math.sin(a)* Math.cos(up)).scale(3.5); const fireball = world.createEntity({ mesh: 'mesh/火球.vb', position: entity.position, meshScale: [0.03,0.03,0.03], velocity, collides: false, gravity: false, fixed: true, meshEmissive: 0.2, particleRate: 30, particleSize: [2,4,8,4,10], particleColor: [ new Box3RGBColor(10,9,2), new Box3RGBColor(5,0.25,0.1), new Box3RGBColor(3,0.05,0.05), new Box3RGBColor(0,0,0), new Box3RGBColor(0,0,0), ], particleLifetime: 0.4, particleVelocitySpread: new Box3Vector3(0.7,0.7,0.7), }) fireball.addTag(entity.player.userKey); fireball.addTag('bullet'); fireball.addTag('entity'); fireball.update = ITEM[4].update; fireball.vel = velocity; fireball.shooter = entity; setTimeout(fireball.destroy,20000); } }, 'action1'({entity }){ if(world.currentTick - entity.lastSkill < 200)return; entity.lastSkill = world.currentTick; entity.phase = 0; entity.addTag('entity'); entity.update = ITEM[4].burn; entity.radius = 0; entity.fireballs = []; const fireballs = []; for(let i = 0; i < 5; i++){ const ball = world.createEntity({ mesh: 'mesh/火球.vb', position: entity.position, meshScale: [0.03,0.03,0.03], gravity: false, collides: false, meshEmissive: 0.2, particleRate: 10, particleSize: [2,4,8,4,10], particleColor: [ new Box3RGBColor(10,9,2), new Box3RGBColor(5,0.25,0.1), new Box3RGBColor(3,0.05,0.05), new Box3RGBColor(0,0,0), new Box3RGBColor(0,0,0), ], particleLifetime: 0.4, particleVelocitySpread: new Box3Vector3(0.7,0.7,0.7), }) ball.angle = Math.PI * 0.4 * i; entity.fireballs.push(ball); fireballs.push(ball); } setTimeout(()=>{ for(const e of fireballs){ e.destroy(); } },10000); }, }, burn: function(){ if(this.phase < 10){ this.radius += 0.7; }else if(this.phase > 100){ for(const e of this.fireballs){ e.destroy(); } this.removeTag('entity'); }else if(this.phase > 90){ this.radius -= 0.7; } for(const e of this.fireballs){ const angle = e.angle + world.currentTick * 0.2; e.position = this.position.add({x: Math.cos(angle)* this.radius,y: 0,z: Math.sin(angle)* this.radius}); e.velocity.copy(this.velocity); e.velocity.y *= 0.1; } for(const e of world.querySelectorAll`.target`){ if(e !== this && e.position.distance(this.position) < this.radius && !e.hasTag('unhurtable')&& isHurtable(this,e)){ e.hurt(5,{attacker: this,damageType: '焚烧领域'}); } } if(world.currentTick % 5 === 0){ this.sound('audio/火环.mp3'); } this.phase++; }, update: function(){ this.velocity.copy(this.vel); this.meshOrientation.set(Math.random()* 10,Math.random()* 10,Math.random()* 10,Math.random()* 10); for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter &&(e.position.distance(this.position) < 1.5 || getBounds(e).contains(this.position))&& !e.hasTag('unhurtable')&& isHurtable(this.shooter,e)){ e.hurt(100,{attacker: this.shooter,damageType: '烈焰法术'}); this.destroy(); } } if(voxels.getVoxelId(this.position.x,this.position.y,this.position.z)){ this.destroy(); } }, quickFly: function(){ this.velocity.copy(this.vel); this.meshOrientation.set(Math.random() * 10,Math.random() * 10,Math.random() * 10,Math.random() * 10); for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter &&(e.position.distance(this.position) < 3 || getBounds(e).contains(this.position)) && !e.hasTag('unhurtable') && isHurtable(this.shooter,e)){ e.hurt(200,{attacker: this.shooter,damageType: '烈焰禁术'}); this.destroy(); } } if(voxels.getVoxelId(this.position.x,this.position.y,this.position.z)){ this.destroy(); } }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/烈焰法杖.vb', scale: [0.4,0.4,0.4], orientation: Quat.rotateX(Math.PI).rotateZ(Math.PI * 0.8), offset: [0,-0.4,0.4], } ], }, 5: { name: '熔岩战斧', type: 0, effect: { async'action0'({entity}){ if(world.currentTick - entity.lastAttack < 50)return; if(entity.player.crouchButton){ const d = entity.raycast.direction; const angle = Math.atan2(d.z,d.x); const up = Math.atan2(d.y,Math.sqrt(d.x ** 2 + d.z ** 2)); entity.lastAttack = world.currentTick; const bullet = world.createEntity({ mesh: 'mesh/剑气主体_01.vb', position: entity.position, meshScale: [0.0625,0.0625,0.0625], gravity: false, collides: false, velocity: d.scale(2), meshOrientation: Quat.rotateX(up).rotateY(angle), particleRate: 50, particleLifetime: 0.5, particleSize: [8,6,4,2,0.5], particleColor: [ new Box3RGBColor(10,10,0), new Box3RGBColor(10,0.5,0), new Box3RGBColor(10,0,0), new Box3RGBColor(0.5,0,0), new Box3RGBColor(0,0,0), ], }) bullet.addTag('entity'); bullet.shooter = entity; bullet.damageType = '地狱月牙斩'; bullet.damage = 30; bullet.update = ITEM[5].update; setTimeout(bullet.destroy,2000); }else{ entity.lastAttack = Infinity; entity.lastSkill = Infinity; entity.player.enableJump = false; entity.velocity.set(entity.player.facingDirection.x * 3,1.4,entity.player.facingDirection.z * 3); const event = entity.onVoxelContact(({axis })=>{ if(axis.y === 1){ entity.lastAttack = world.currentTick; entity.lastSkill = world.currentTick; event.cancel(); entity.player.enableJump = true; const bullet = world.createEntity({ mesh: 'mesh/剑气分身.vb', position: entity.position, meshScale: [0.2,0.2,0.2], gravity: false, collides: false, velocity: entity.player.facingDirection.scale(3), meshOrientation: Quat.rotateY(Math.atan2(entity.player.facingDirection.z,entity.player.facingDirection.x)), particleRate: 50, particleLifetime: 0.5, particleSize: [8,6,4,2,0.5], particleColor: [ new Box3RGBColor(10,10,0), new Box3RGBColor(10,0.5,0), new Box3RGBColor(10,0,0), new Box3RGBColor(0.5,0,0), new Box3RGBColor(0,0,0), ], }) bullet.addTag('entity'); bullet.shooter = entity; bullet.damageType = '烈焰霹雳斩'; bullet.damage = 50; bullet.update = ITEM[5].update; setTimeout(bullet.destroy,2000); } }) } }, 'action1'({entity }){ if(world.currentTick - entity.lastSkill < 100)return; entity.lastSkill = Infinity; entity.lastAttack = Infinity; entity.isHurtable = false; entity.player.cameraFovY = 0.4; const bullet = world.createEntity({ mesh: 'mesh/单元方块.vb', position: entity.position, gravity: false, friction: 10, meshScale: [0.0625,0.0625,0.0625], meshColor: [0,0,0,0], particleRate: 50, particleLifetime: 0.5, particleSize: [8,6,4,2,0.5], particleColor: [ new Box3RGBColor(10,10,0), new Box3RGBColor(10,0.5,0), new Box3RGBColor(10,0,0), new Box3RGBColor(0.5,0,0), new Box3RGBColor(0,0,0), ], }) const show = world.createEntity({ mesh: 'mesh/地狱之斧.vb', position: entity.position, gravity: false, meshScale: [0.01,0.01,0.01], meshColor: [1,0,0,1], meshEmissive: 0.01, collides: false, }) entity.player.cameraEntity = bullet; for(const e of entity.watchers){ e.player.cameraEntity = bullet; } bullet.addTag(entity.player.userKey); entity.angle = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); entity.up = Math.min(0,-entity.player.cameraPitch); show.meshOrientation = Quat.rotateX(-world.currentTick * 0.8).rotateY(entity.angle); entity.bullet = bullet; entity.show = show; bullet.shooter = entity; bullet.addTag('bullet'); entity.addTag('entity'); entity.update = ITEM[5].flying; entity.player.invisible = true; entity.player.showName = false; entity.enableDamage = false; bullet.onVoxelContact(bullet.destroy); bullet.onEntityContact(bullet.destroy); setTimeout(bullet.destroy,20000); bullet.onDestroy(()=>{ ITEM[5].end_fly(entity); }) }, }, update: function(){ for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter && e.position.distance(this.position) < 3 && !e.hasTag('unhurtable')&& isHurtable(this.shooter,e)){ e.hurt(this.damage,{attacker: this.shooter,damageType: this.damageType}); } } if(voxels.getVoxelId(this.position.x,this.position.y,this.position.z)){ this.destroy(); } }, end_fly: function(entity){ entity.removeTag('entity'); entity.lastSkill = world.currentTick; entity.lastAttack = world.currentTick - 50; entity.player.cameraFovY = 0.25; entity.show.destroy(); entity.position.copy(entity.bullet.position); entity.player.cameraEntity = entity; entity.isHurtable = true; entity.player.invisible = false; entity.player.showName = true; entity.enableDamage = true; for(const e of entity.watchers){ e.player.cameraEntity = entity; } if(entity.hp){ world.sound({ sample: 'audio/重击.mp3', position: entity.position, radius: 320, }) for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(entity.position) < 10 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(entity.position,e.position)){ e.hurt(60,{attacker: entity,damageType: '熔岩轰炸'}); const direction = e.position.sub(entity.position).add({x: 0,y: 1,z: 0}); e.velocity.addEq(direction.scale(5 / direction.mag()** 2 / e.mass * 1.75)); } } const ball = world.createEntity({ mesh: 'mesh/光球.vb', position: entity.position, gravity: false, collides: false, meshScale: [0.005,0.005,0.005], meshColor: [1,0.01,0.01,1], }) ball.addTag('entity'); ball.update = ITEM[1].explodeUpdate; } }, flying: function(){ if(world.currentTick % 5 === 0){ this.bullet.sound('audio/挥动.mp3'); } this.show.meshOrientation = Quat.rotateX(-world.currentTick * 0.8).rotateY(this.angle); if(this.show.position.distance(this.bullet.position) > 0.1){ this.show.position.copy(this.bullet.position); } this.bullet.velocity.set(Math.cos(this.angle)* Math.cos(this.up)* 4,Math.sin(this.up)* 4,Math.sin(this.angle)* Math.cos(this.up)* 4); this.show.velocity.copy(this.bullet.velocity); for(const e of world.querySelectorAll`.target`){ if(e !== this && e.position.distance(this.bullet.position) < 5 && !e.hasTag('unhurtable') && isHurtable(this,e) && spread(this.position,e.position)){ e.hurt(20,{attacker: this,damageType: '地狱冲刺'}); } } }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/地狱之斧.vb', scale: [0.2,0.2,0.2], orientation: Quat.rotateX(Math.PI * 0.5).rotateY(Math.PI * 0.5).rotateZ(Math.PI * 0.8), offset: [0,-0.3,0.3], } ], }, 6: { name: '曙光轻机枪', type: 1, effect: { async'action1'({entity }){ if(world.currentTick - entity.lastSkill < 21 && entity.bullets[6] !== 30)return; entity.lastSkill = world.currentTick; entity.bullets[6] = 0; entity.sound('audio/换弹.mp3'); await sleep(2100); entity.bullets[6] = 30; entity.player.directMessage('换弹成功\n剩余子弹:30'); }, }, press({entity }){ if(world.currentTick - entity.lastAttack < 3)return; if(entity.bullets[6] === undefined){ entity.bullets[6] = 30; }else if(!entity.bullets[6]){ entity.sound('audio/空枪.mp3'); entity.lastAttack = world.currentTick + 5; return; } entity.player.directMessage('剩余子弹:' + --entity.bullets[6]); entity.lastAttack = world.currentTick; entity.sound('audio/射击.mp3'); const angle = Math.atan2(entity.player.facingDirection.z,entity.player.facingDirection.x); const up = -entity.player.cameraPitch; const direction = new Box3Vector3(Math.cos(angle)* Math.cos(up),Math.sin(up),Math.sin(angle)* Math.cos(up)); const velocity = direction.scale(7); const bullet = world.createEntity({ mesh: 'mesh/bullet.vb', position: entity.position, meshScale: [0.03,0.03,0.03], velocity, collides: false, gravity: false, meshOrientation: Quat.rotateX(up).rotateY(angle), particleRate: 5, particleLifetime: 0.75, particleSize: [2,0.65,0.23], particleColor: [ new Box3RGBColor(0,0,10), new Box3RGBColor(0,10,10), new Box3RGBColor(10,10,10), ], }) bullet.addTag(entity.player.userKey); bullet.addTag('bullet'); bullet.addTag('entity'); bullet.vel = velocity; bullet.shooter = entity; bullet.direction = direction; bullet.lastPosition = entity.position.clone(); bullet.update = ITEM[6].update; setTimeout(bullet.destroy,20000); }, update: function(){ this.velocity.copy(this.vel); for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter && this.position.distance(e.position) < this.position.distance(this.lastPosition)&& getBigBounds(e).contains(this.lastPosition.add(this.direction.scale(this.lastPosition.distance(e.position))))&& !e.hasTag('unhurtable')&& isHurtable(this.shooter,e)){ e.hurt(20,{attacker: this.shooter,damageType: '曙光轻机枪'}); } } this.lastPosition.copy(this.position); if(voxels.getVoxelId(this.position.x,this.position.y,this.position.z)){ this.destroy(); } }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/枪-3.vb', scale: [0.4,0.4,0.4], orientation: Quat.rotateX(Math.PI).rotateZ(Math.PI * 0.8), offset: [0,-0.2,0.4], } ], }, 7: { name: '黎明狙击枪', type: 1, effect: { 'action0'({entity }){ if(world.currentTick - entity.lastAttack < 20)return; entity.player.cameraMode = 'fps'; entity.player.cameraFovY = 0.1; }, async'action1'({entity }){ if(world.currentTick - entity.lastSkill < 21 && entity.bullets[7] !== 5)return; entity.lastSkill = world.currentTick; entity.bullets[7] = 0; entity.sound('audio/换弹.mp3'); await sleep(2100); entity.bullets[7] = 5; entity.player.directMessage('换弹成功\n剩余子弹:5'); }, }, effectOver: { 'action0'({entity }){ if(entity.player.cameraMode === 'follow')return; entity.lastAttack = world.currentTick; entity.player.cameraMode = 'follow'; entity.player.cameraFovY = 0.25; ITEM[7].shoot(entity); } }, shoot(entity){ if(entity.bullets[7] === undefined){ entity.bullets[7] = 5; }else if(!entity.bullets[7]){ entity.sound('audio/空枪.mp3'); entity.lastAttack = world.currentTick + 5; return; } entity.player.directMessage('剩余子弹:' + --entity.bullets[7]); entity.sound('audio/射击.mp3'); const direction = entity.raycast.direction.clone(); const up = Math.atan2(direction.y,Math.sqrt(direction.x ** 2 + direction.z ** 2)); const angle = Math.atan2(direction.z,direction.x); const velocity = direction.scale(7); const bullet = world.createEntity({ mesh: 'mesh/bullet.vb', position: entity.position, meshScale: [0.03,0.03,0.03], velocity, collides: false, gravity: false, meshOrientation: Quat.rotateX(up).rotateY(angle), particleRate: 10, particleLifetime: 0.75, particleSize: [2,0.65,0.23], particleColor: [ new Box3RGBColor(0,0,10), new Box3RGBColor(0,10,10), new Box3RGBColor(10,10,10), ], }) bullet.addTag(entity.player.userKey); bullet.addTag('bullet'); bullet.addTag('entity'); bullet.vel = velocity; bullet.shooter = entity; bullet.direction = direction; bullet.lastPosition = entity.position.clone(); bullet.update = ITEM[7].update; setTimeout(bullet.destroy,20000); }, update: function(){ this.velocity.copy(this.vel); for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter && this.position.distance(e.position) < this.position.distance(this.lastPosition)&& getBigBounds(e).contains(this.lastPosition.add(this.direction.scale(this.lastPosition.distance(e.position))))&& !e.hasTag('unhurtable')&& isHurtable(this.shooter,e)){ e.hurt(120,{attacker: this.shooter,damageType: '黎明狙击枪'}); } } this.lastPosition.copy(this.position); if(voxels.getVoxelId(this.position.x,this.position.y,this.position.z)){ this.destroy(); } }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/枪-18.vb', scale: [0.4,0.4,0.4], orientation: Quat.rotateY(Math.PI).rotateX(Math.PI).rotateZ(Math.PI * 0.8), offset: [0,-0.2,0.3], } ], }, 8: { name: '天空法杖', type: 2, effect: { 'action0'({entity}){ const angle = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); if(entity.player.crouchButton && !entity.hasTag('flying')){ if(world.currentTick - entity.lastAttack < 100)return; entity.lastAttack = world.currentTick; const cyclone = world.createEntity({ mesh: 'mesh/龙卷风.vb', position: entity.position.add({x: 0,y: 3,z: 0}), gravity: false, meshScale: [0.0625,0.0625,0.0625], meshColor: [0.01,1,1,1], velocity: [Math.cos(angle)* 0.5,-0.1,Math.sin(angle)* 0.5], mass: 256, }) cyclone.addTag('invisible'); cyclone.addTag('entity'); cyclone.update = ITEM[8].blow; cyclone.shooter = entity; setTimeout(cyclone.destroy,20000); }else{ if(world.currentTick - entity.lastAttack < 10)return; entity.lastAttack = world.currentTick; const up = Math.atan2(entity.raycast.direction.y,Math.sqrt(entity.raycast.direction.x ** 2 + entity.raycast.direction.z ** 2)); const a = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); const velocity = new Box3Vector3(Math.cos(a)* Math.cos(up),Math.sin(up),Math.sin(a)* Math.cos(up)).scale(2.5); const windball = world.createEntity({ mesh: 'mesh/光球.vb', position: entity.position, meshColor: [0.01,1,1,1], meshScale: [0.011,0.011,0.011], gravity: false, velocity, collides: false, particleRate: 50, particleLifetime: 0.6, particleSize: [2,4,8,4,10], particleColor: [ new Box3RGBColor(2,9,10), new Box3RGBColor(0.1,0.25,5), new Box3RGBColor(0.05,0.05,3), new Box3RGBColor(0,0,0), new Box3RGBColor(0,0,0), ], }) windball.addTag(entity.player.userKey); windball.addTag('bullet'); windball.addTag('entity'); windball.update = ITEM[8].update; windball.vel = velocity; windball.shooter = entity; windball.onDestroy(()=>{ for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(windball.position) < 7 && !e.hasTag('unhurtable') && isHurtable(entity,e)){ e.hurt(15,{attacker: entity,damageType: '混沌疾风'}); } } }) setTimeout(windball.destroy,20000); } }, async'action1'({entity }){ if(entity.hasTag('flying')){ ITEM[8].fall(entity,1); }else if(world.currentTick - entity.lastSkill > 100){ const falltimes = ++entity.falltimes; entity.lastSkill = world.currentTick; for(const e of world.querySelectorAll`.target`){ if(e.position.distance(entity.position) < 10 && e !== entity && !e.hasTag('unhurtable') && isHurtable(entity,e)){ e.hurt(20,{attacker: entity,damageType: '虚空之力'}); } } entity.sound('audio/起飞.mp3'); entity.addTag('flying'); entity.velocity.y = 0.1; await sleep(10000); if(falltimes === entity.falltimes){ ITEM[8].fall(entity,0); } } }, }, fall: function(entity,isBreak){ if(!entity.hp || !entity.hasTag('flying'))return; entity.removeTag('flying'); entity.isHurtable = false; entity.lastAttack = Infinity; entity.lastSkill = Infinity; removeEffect(entity); const bullet = world.createEntity({ mesh: 'mesh/单元方块.vb', position: entity.position, gravity: false, friction: 10, meshScale: [0.125,0.125,0.125], meshColor: [0,0,0,0], particleRate: 200, particleLifetime: 0.5, particleSize: [8,6,4,2,0.5], particleColor: [ new Box3RGBColor(0.5,10,10), new Box3RGBColor(0.55,10,10), new Box3RGBColor(0.6,10,10), new Box3RGBColor(0.65,10,10), new Box3RGBColor(0.7,10,10), ], }) const show = world.createEntity({ mesh: 'mesh/黑洞.vb', position: entity.position, gravity: false, meshScale: [0.01,0.01,0.01], meshColor: [1,0,0,1], meshEmissive: 0.01, collides: false, }) entity.player.cameraEntity = bullet; for(const e of entity.watchers){ e.player.cameraEntity = bullet; } bullet.addTag(entity.player.userKey); entity.angle = isBreak? Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x):Math.atan2(entity.player.facingDirection.z,entity.player.facingDirection.x); entity.up = Math.min(0,isBreak? Math.atan2(entity.raycast.direction.y,Math.sqrt(entity.raycast.direction.x ** 2 + entity.raycast.direction.z ** 2)):-entity.player.cameraPitch); entity.bullet = bullet; entity.show = show; bullet.shooter = entity; bullet.addTag('bullet'); entity.addTag('entity'); entity.update = ITEM[8].flying; entity.player.invisible = true; entity.player.showName = false; entity.enableDamage = false; entity.player.cameraFovY = 0.4; bullet.onVoxelContact(bullet.destroy); bullet.onEntityContact(bullet.destroy); setTimeout(bullet.destroy,20000); bullet.onDestroy(()=>{ ITEM[8].end_fly(entity); }) }, update: function(){ this.velocity.copy(this.vel); this.meshOrientation.set(Math.random()* 10,Math.random()* 10,Math.random()* 10,Math.random()* 10); for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter &&(e.position.distance(this.position) < 1.5 || getBounds(e).contains(this.position))&& !e.hasTag('unhurtable') && isHurtable(this.shooter,e)){ e.hurt(30,{attacker: this.shooter,damageType: '风暴之力'}); this.destroy(); } } if(voxels.getVoxelId(this.position.x,this.position.y,this.position.z)){ this.destroy(); } }, blow: function(){ this.meshOrientation = Quat.rotateY(world.currentTick * 0.2); for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter && !e.hasTag('unhurtable')){ const x = e.position.x - this.position.x; const y = e.position.y - this.position.y; const z = e.position.z - this.position.z; if(Math.sqrt(x ** 2 + z ** 2) < 5 && Math.abs(y) < 5 && isHurtable(this.shooter,e)){ e.hurt(5,{attacker: this.shooter,damageType: '天穹旋风'}); } } } }, end_fly: function(entity){ entity.removeTag('entity'); entity.lastSkill = world.currentTick; entity.lastAttack = world.currentTick - 100; entity.player.cameraFovY = 0.25; entity.show.destroy(); entity.position.copy(entity.bullet.position); entity.player.cameraEntity = entity; entity.isHurtable = true; entity.player.invisible = false; entity.player.showName = true; entity.enableDamage = true; for(const e of entity.watchers){ e.player.cameraEntity = entity; } if(entity.hp){ world.sound({ sample: 'audio/重击.mp3', position: entity.position, radius: 320, }) for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(entity.position) < 10 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(entity.position,e.position)){ e.hurt(25,{attacker: entity,damageType: '吞噬黑洞'}); const direction = e.position.sub(entity.position).add({x: 0,y: 1,z: 0}); e.velocity.addEq(direction.scale(5 / direction.mag()** 2 / e.mass * 1.75)); } } const ball = world.createEntity({ mesh: 'mesh/光球.vb', position: entity.position, gravity: false, collides: false, meshScale: [0.005,0.005,0.005], meshColor: [0.01,1,1,1], }) ball.addTag('entity'); ball.update = ITEM[1].explodeUpdate; } }, flying: function(){ this.show.meshOrientation.set(Math.random(),Math.random(),Math.random(),Math.random()); if(this.show.position.distance(this.bullet.position) > 0.1){ this.show.position.copy(this.bullet.position); } this.bullet.velocity.set(Math.cos(this.angle)* Math.cos(this.up)* 4,Math.sin(this.up)* 4,Math.sin(this.angle)* Math.cos(this.up)* 4); this.show.velocity.copy(this.bullet.velocity); for(const e of world.querySelectorAll`.target`){ if(e !== this && e.position.distance(this.bullet.position) < 5 && !e.hasTag('unhurtable') && isHurtable(this,e) && spread(this.position,e.position)){ e.hurt(5,{attacker: this,damageType: '虚无轨迹'}); } } }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/天空法杖.vb', scale: [0.5,0.5,0.5], offset: [0,-0.3,0.3], orientation: Quat.rotateZ(-Math.PI * 0.7), } ], }, 9: { name: '黄金三叉戟', type: 0, effect: { async'action0'({entity }){ if(entity.player.crouchButton){ if(world.currentTick - entity.lastAttack < 50)return; entity.lastSkill = Infinity; entity.lastAttack = Infinity; entity.player.enableJump = false; entity.isHurtable = false; entity.velocity.y = 2; await sleep(1000); entity.addTag('entity'); entity.mesh = 'mesh/下落三叉戟.vb'; entity.update = ITEM[9].falling; entity.meshEmissive = 1; entity.player.invisible = true; entity.velocity.y = -4; initParticle(entity); Object.assign(entity,{ particleRate: 100, particleLifetime: 5, particleSize: [5,2,1], particleColor: [ new Box3RGBColor(0,0,10), new Box3RGBColor(0,10,10), new Box3RGBColor(10,10,10), ], particleNoise: 5, particleNoiseFrequency: 2, }) entity.attacked = false; entity.event = entity.onVoxelContact(ITEM[9].boom); }else{ if(world.currentTick - entity.lastAttack < 80)return; entity.lastAttack = world.currentTick; const waterSwords = []; for(let i = 0; i < 8; i++){ const radius = i * 4 + 4; const waterSword = world.createEntity({ bounds: [4,4,4], meshScale: [0.25,0.25,0.25], meshColor: [0,0,0,0], collides: false, gravity: false, particleRate: 50, particleLifetime: 5, particleSize: [50,5,3,1,0], particleColor: [ new Box3RGBColor(0,0,10), new Box3RGBColor(0,10,10), new Box3RGBColor(10,10,10), new Box3RGBColor(10,10,10), new Box3RGBColor(10,10,10), ], particleNoise: 25, particleNoiseFrequency: 2, }) waterSword.radius = radius; waterSwords.push(waterSword); } entity.sound('audio/大水流.mp3'); waterSwords[0].addTag('entity'); waterSwords[0].startTick = world.currentTick; waterSwords[0].update = ITEM[9].strike; waterSwords[0].angle = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); waterSwords[0].waterSwords = waterSwords; waterSwords[0].origin = entity.position.clone(); waterSwords[0].shooter = entity; } }, async'action1'({entity}){ if(world.currentTick - entity.lastSkill > 100){ entity.velocity.y = 2; entity.lastSkill = Infinity; entity.lastAttack = Infinity; entity.lastSpoce = Infinity; entity.isHurtable = false; entity.sound('audio/起飞.mp3'); await sleep(300); const bullet = world.createEntity({ mesh: 'mesh/单元方块.vb', position: entity.position, gravity: false, meshScale: [0.0625,0.0625,0.0625], meshColor: [0,0,0,0], friction: 3, particleRate: 200, particleLifetime: 5, particleSize: [5,2,1], particleColor: [ new Box3RGBColor(0,0,10), new Box3RGBColor(0,10,10), new Box3RGBColor(10,10,10), ], particleNoise: 5, particleNoiseFrequency: 2, }) const show = world.createEntity({ mesh: 'mesh/三叉戟.vb', position: entity.position, gravity: false, meshScale: [0.01,0.01,0.01], meshEmissive: 1, collides: false, }) entity.player.cameraEntity = bullet; for(const e of entity.watchers){ e.player.cameraEntity = bullet; } bullet.addTag(entity.player.userKey); entity.angle = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); entity.up = 0; show.meshOrientation = Quat.rotateY(Math.PI * 0.5).rotateX(entity.up).rotateY(entity.angle); entity.bullet = bullet; entity.show = show; bullet.shooter = entity; bullet.addTag('bullet'); entity.addTag('entity'); entity.update = ITEM[9].flying; entity.player.invisible = true; entity.player.showName = false; entity.enableDamage = false; bullet.onVoxelContact(bullet.destroy); bullet.onEntityContact(bullet.destroy); setTimeout(bullet.destroy,20000); bullet.onDestroy(()=>{ ITEM[9].end_fly(entity); }) } }, }, falling: function(){ if(this.player.moveState === Box3PlayerMoveState.GROUND){ ITEM[9].boom({entity: this,axis: {x: 0,y: 1,z: 0}}); } }, boom({entity,axis }){ if(axis.y === 1 && !entity.attacked){ entity.removeTag('entity'); entity.lastSkill = world.currentTick; entity.lastAttack = world.currentTick - 5; entity.event.cancel(); entity.mesh = ''; entity.particleRate = 0; entity.player.invisible = false; entity.isHurtable = true; entity.player.enableJump = true; ITEM[9].explode(entity,new Box3Vector3(entity.position.x,entity.position.y - entity.bounds.y,entity.position.z)); } }, strike: function(){ const tick = world.currentTick - this.startTick; if(tick > 9){ const hurters = []; for(const e of this.waterSwords){ for(const a of world.querySelectorAll`.target`){ if(a !== this.shooter && a.position.distance(e.position) < 10 && !a.hasTag('unhurtable') && !hurters.includes(a) && isHurtable(this.shooter,a)){ hurters.push(a); } } e.destroy(); } for(const e of hurters){ e.hurt(45,{attacker: this.shooter,damageType: '深渊·巨浪怒刃'}); } } const angle = 1.6 - 0.2 * tick; for(const e of this.waterSwords){ e.position = this.origin.add({x: Math.cos(this.angle)* Math.cos(angle)* e.radius * 2,y: Math.sin(angle)* e.radius,z: Math.sin(this.angle) * Math.cos(angle) * e.radius * 2}); } }, end_fly: function(entity){ entity.lastSkill = world.currentTick; entity.lastAttack = world.currentTick - 10; entity.lastSpoce = world.currentTick - 200; entity.show.destroy(); entity.position.copy(entity.bullet.position); entity.player.cameraEntity = entity; entity.isHurtable = true; entity.player.invisible = false; entity.player.showName = true; entity.enableDamage = true; for(const e of entity.watchers){ e.player.cameraEntity = entity; } if(entity.hp){ entity.sound('audio/explode.mp3'); for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(entity.position) < 20 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(entity.position,e.position)){ e.hurt(40,{attacker: entity,damageType: '无尽·深海审判'}); const direction = e.position.sub(entity.position).add({x: 0,y: 1,z: 0}); e.velocity.addEq(direction.scale(5 / direction.mag()** 2 / e.mass * 1.75)); } } const ball = world.createEntity({ mesh: 'mesh/光球.vb', position: entity.position, gravity: false, collides: false, meshColor: [0.01,0.01,1,1], meshScale: [0.04,0.04,0.04], }) ball.addTag('entity'); ball.update = ITEM[9].explodeUpdate; } }, explodeUpdate: function(){ this.meshScale.x *= 1.2; this.meshScale.y *= 1.2; this.meshScale.z *= 1.2; if(this.meshScale.x > 0.1){ this.destroy(); } }, explode: function(entity,position){ entity.sound('audio/地动.mp3'); for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(entity.position) < 10 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(entity.position,e.position)){ e.hurt(35,{attacker: entity,damageType: '禁锢·波光闪耀'}); const direction = e.position.sub(entity.position).add({x: 0,y: 2,z: 0}); e.velocity.addEq(direction.scale(5 / direction.mag()** 2 / e.mass * 1.75)); } } const ring = world.createEntity({ mesh: 'mesh/水阵.vb', meshScale: [0.005,0.005,0.005], position, collides: false, gravity: false, }) ring.state = 0; ring.scale = 0.005; ring.addTag('entity'); ring.update = ITEM[0].explodeUpdate; }, flying: function(){ this.direction = Math.atan2(this.player.facingDirection.z,this.player.facingDirection.x); rotate(this); const up = -this.player.cameraPitch; if(this.up > up){ this.up -= 0.1; } this.show.meshOrientation = Quat.rotateY(Math.PI * 0.5).rotateX(this.up).rotateY(this.angle); if(this.show.position.distance(this.bullet.position) > 0.1){ this.show.position.copy(this.bullet.position); } this.bullet.velocity.set(Math.cos(this.angle) * Math.cos(this.up) * 1.5,Math.sin(this.up) * 1.5,Math.sin(this.angle) * Math.cos(this.up) * 1.5); this.show.velocity.copy(this.bullet.velocity); }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/三叉戟.vb', scale: [0.3,0.3,0.4], offset: [0,-0.45,0.5], emissive: 0.1, orientation: Quat.rotateZ(Math.PI * 0.8), } ], }, 10: { name: '电子三叉戟', type: 3, effect: { async'action0'({entity }){ //闪电连斩 if(world.currentTick - entity.lastAttack > 50){ entity.lastAttack = world.currentTick; const angle = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); const entity1 = world.createEntity({ mesh: 'mesh/剑气.vb', position: entity.position, collides: false, meshScale: [0.1,0.1,0.1], gravity: false, velocity: new Box3Vector3(Math.cos(angle)* 2,0,Math.sin(angle)* 2), meshOrientation: Quat.rotateY(angle), particleRate: 100, particleSize: [5,3,5,3,5], particleNoise: 2, particleNoiseFrequency: 5, particleColor: [ new Box3RGBColor(0.033,1,10), new Box3RGBColor(10,0.025,10), new Box3RGBColor(0.05,1,10), new Box3RGBColor(10,0.5,10), new Box3RGBColor(0.2,1,10) ] }) entity.sound('audio/electric.mp3'); const e1 = ITEM[10].thunder(),e2 = ITEM[10].thunder(); const p1 = entity.position.add({x: Math.cos(angle - 1.7) * 3,y: 0,z: Math.sin(angle - 1.7) * 3}); const p2 = entity.position.add({x: Math.cos(angle + 1.7) * 3,y: 0,z: Math.sin(angle + 1.7) * 3}); const t1 = entity.position.add({x: Math.cos(angle - 0.2) * 8,y: 0,z: Math.sin(angle - 0.2) * 8}); const t2 = entity.position.add({x: Math.cos(angle + 0.2) * 8,y: 0,z: Math.sin(angle + 0.2) * 8}); Object.assign(e1,{position: p1,velocity: t1.sub(p1).scale(0.2)}); Object.assign(e2,{position: p2,velocity: t2.sub(p2).scale(0.2)}); ITEM[10].strike(entity,entity.position.add({x: Math.cos(angle)* 10,y: 0,z: Math.sin(angle)* 10}),10); setTimeout(()=>{ entity1.destroy(); const d = entity1.position.sub(entity.position); const rip = world.createEntity({ mesh: 'mesh/时空裂缝.vb', position: entity.position.lerp(entity1.position,0.5), collides: false, gravity: false, meshScale: [entity.position.distance(entity1.position)* 0.03125,0.0625,0], meshOrientation: Quat.rotateX(Math.atan2(d.y,Math.sqrt(d.x ** 2 + d.z ** 2))).rotateY(Math.atan2(d.z,d.x)), }) rip.animate([ { meshScale: [entity.position.distance(entity1.position)* 0.03125,0.0625,0], }, { meshScale: [entity.position.distance(entity1.position)* 0.03125,0,0], }, ],{ duration: 32, delay: 32, }).onFinish(rip.destroy); },500); await sleep(500); const entity2 = world.createEntity({ mesh: 'mesh/剑气.vb', position: entity.position, collides: false, meshScale: [0.1,0.1,0.1], gravity: false, velocity: new Box3Vector3(Math.cos(angle)* 2,0,Math.sin(angle)* 2), meshOrientation: Quat.rotateY(angle), particleRate: 50, particleSize: [5,3,5,3,5], particleNoise: 2, particleNoiseFrequency: 5, particleColor: [ new Box3RGBColor(0.033,1,10), new Box3RGBColor(10,0.025,10), new Box3RGBColor(0.05,1,10), new Box3RGBColor(10,0.5,10), new Box3RGBColor(0.2,1,10) ] }) entity.sound('audio/explode.mp3'); const e3 = ITEM[10].thunder(),e4 = ITEM[10].thunder(),e5 = ITEM[10].thunder(); const p3 = entity.position.add({x: Math.cos(angle - 1.7)* 5,y: 3,z: Math.sin(angle - 1.7)* 5}); const p4 = entity.position.add({x: Math.cos(angle + 1.7)* 5,y: 3,z: Math.sin(angle + 1.7)* 5}); const p5 = entity.position.add({x: Math.cos(angle)* 7,y: -1,z: Math.sin(angle)* 7}); const t3 = entity.position.sub({x: Math.cos(angle - 1.7)* 8,y: 1,z: Math.sin(angle - 1.7)* 8}); const t4 = entity.position.sub({x: Math.cos(angle + 1.7)* 8,y: 1,z: Math.sin(angle + 1.7)* 8}); const t5 = entity.position.add({x: Math.cos(angle)* 6.9,y: 0,z: Math.sin(angle)* 6.9}); Object.assign(e3,{position: p3,velocity: t3.sub(p3).scale(0.05)}); Object.assign(e4,{position: p4,velocity: t4.sub(p4).scale(0.05)}); Object.assign(e5,{position: p5,velocity: t5.sub(p5).scale(0.6)}); ITEM[10].strike(entity,entity.position.add({x: Math.cos(angle)* 10,y: 0,z: Math.sin(angle)* 10}),8); setTimeout(()=>{ entity2.destroy(); const d = entity2.position.sub(entity.position); const rip = world.createEntity({ mesh: 'mesh/时空裂缝.vb', position: entity.position.lerp(entity2.position,0.5), collides: false, gravity: false, meshScale: [entity.position.distance(entity2.position)* 0.03125,0.0625,0], meshOrientation: Quat.rotateX(Math.atan2(d.y,Math.sqrt(d.x ** 2 + d.z ** 2))).rotateY(Math.atan2(d.z,d.x)), }) rip.animate([ { meshScale: [entity.position.distance(entity2.position) * 0.03125,0.0625,0], }, { meshScale: [entity.position.distance(entity2.position) * 0.03125,0,0], }, ],{ duration: 32, delay: 32, }).onFinish(rip.destroy); },500); } }, 'action1'({entity}){ if(world.currentTick - entity.lastSkill > 30){ entity.lastSkill = Infinity; entity.lastAttack = Infinity; entity.bagable = false; entity.weaponSight[0].remove(); const d = entity.raycast.direction.clone(); const trident = world.createEntity({ mesh: 'mesh/电子三叉戟飞行.vb', position: entity.position.add({x: 0,y: 2,z: 0}), meshScale: [0.01,0.01,0.01], velocity: d.scale(4), meshOrientation: Quat.rotateX(Math.atan2(d.y,Math.sqrt(d.x ** 2 + d.z ** 2))).rotateY(Math.atan2(d.z,d.x)), particleRate: 100, particleSize: [5,3,5,3,5], particleNoise: 2, particleNoiseFrequency: 5, particleColor: [ new Box3RGBColor(0.033,1,10), new Box3RGBColor(10,0.025,10), new Box3RGBColor(0.05,1,10), new Box3RGBColor(10,0.5,10), new Box3RGBColor(0.2,1,10) ] }) entity.trident = trident; entity.sound('audio/挥动.mp3'); trident.addTag(entity.player.userKey); trident.addTag('entity'); trident.addTag('bullet'); trident.state = 0; trident.floating = 0; trident.shooter = entity; trident.onDestroy(()=>{ entity.bagable = true; entity.weaponSight[0] = entity.player.addWearable(ITEM[10].style[0]); entity.lastSkill = world.currentTick; entity.lastAttack = world.currentTick - 50; }) trident.onEntityContact(({other })=>{ if(trident.state === 0 && isHurtable(entity,other)){ other.hurt(250,{attacker: entity,damageType: '电子三叉戟'}); trident.state++; trident.velocity.y = 1; trident.gravity = false; trident.collides = false; trident.particleLifetime = 1; ITEM[10].boom(entity,trident.position); } }) trident.onVoxelContact(()=>{ if(trident.state === 0){ trident.state++; trident.velocity.y = 1; trident.gravity = false; trident.collides = false; trident.particleLifetime = 1; ITEM[10].boom(entity,trident.position); } }) trident.update = ITEM[10].update; } }, }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/电子三叉戟.vb', scale: [0.3,0.3,0.3], offset: [0,-0.35,0.5], orientation: Quat.rotateZ(-Math.PI * 0.65), } ], strike(entity,center,radius){ for(const e of world.querySelectorAll`.target`){ if(e.position.distance(center) < radius && e !== entity && !e.hasTag('unhurtable') && isHurtable(entity,e)){ e.hurt(30,{attacker: entity,damageType: '寂无·时空深渊斩'}); } } }, thunder(){ const entity = world.createEntity({ mesh: 'mesh/单元方块.vb', gravity: false, collides: false, meshScale: [0.005,0.005,0.005], particleRate: 100, particleSize: [5,3,5,3,5], particleLifetime: 0.5, particleNoise: 2, particleNoiseFrequency: 5, friction: 10, particleColor: [ new Box3RGBColor(0.033,1,10), new Box3RGBColor(10,0.025,10), new Box3RGBColor(0.05,1,10), new Box3RGBColor(10,0.5,10), new Box3RGBColor(0.2,1,10) ] }) setTimeout(entity.destroy,500); return entity; }, boom(entity,position){ for(const e of world.querySelectorAll`.target`){ world.sound({ sample: 'audio/重击.mp3', position, radius: 320, }) if(e !== entity && e.position.distance(position) < 10 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(position,e.position)){ e.hurt(65,{attacker: entity,damageType: '九重天雷·星辰陨落'}); const direction = e.position.sub(position).add({x: 0,y: 1,z: 0}); e.velocity.addEq(direction.scale(5 / direction.mag() ** 2 / e.mass * 1.75)); } } const ball = world.createEntity({ mesh: 'mesh/光球.vb', position, gravity: false, collides: false, meshScale: [0.005,0.005,0.005], meshColor: [1,0.01,1,1], }) ball.addTag('entity'); ball.update = ITEM[1].explodeUpdate; }, update: function(){ switch(this.state){ case 0: const d = this.velocity; this.meshOrientation = Quat.rotateX(Math.atan2(d.y,Math.sqrt(d.x ** 2 + d.z ** 2))).rotateY(Math.atan2(d.z,d.x)); break; case 1: this.floating++; if(this.floating > 10){ this.state++; } break; case 2: const d2 = this.shooter.position.sub(this.position); this.meshOrientation = Quat.rotateY(Math.PI).rotateX(Math.atan2(d2.y,Math.sqrt(d2.x ** 2 + d2.z ** 2))).rotateY(Math.atan2(d2.z,d2.x)); this.velocity = d2.scale(2 / d2.mag()); if(this.position.distance(this.shooter.position) < 9){ this.destroy(); } break; } }, }, 11: { name: '鞭炮', type: 3, effect: { 'action0'({entity}){ if(entity.boom && !entity.boom.destroyed)return; entity.weaponSight[1].remove(); const boom = world.createEntity({ mesh: 'mesh/春节二十响.vb', position: entity.position, meshScale: [0.01,0.01,0.01], velocity: entity.raycast.direction.scale(2), meshOrientation: Quat.rotateY(Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x)), friction: 10, }) boom.addTag('bullet'); boom.shooter = entity; boom.addTag(entity.player.userKey); boom.enableDamage = true; boom.hp = boom.maxHp = 20; boom.addTag('target'); boom.onDie(boom.destroy); boom.onDestroy(()=>{ if(entity.weapon === 11){ entity.weaponSight[1] = entity.player.addWearable({ mesh: 'mesh/春节鞭炮1.vb', bodyPart: Box3BodyPart.TORSO, scale: [0.1,0.1,0.1], offset: [0,0,-0.3], orientation: Quat.rotateX(0.5), }) } }) entity.boom = boom; }, 'action1'({entity}){ if(entity.boom && !entity.boom.destroyed){ entity.boom.addTag('entity'); entity.boom.meshColor.set(1,0.5,0.5,1); entity.boom.update = ITEM[11].update; entity.boom.times = 0; entity.boom.sound('audio/鞭炮.mp3'); Object.assign(entity.boom,{ particleRate: 100, particleColor: [ [10,2,2], [10,2,2], [10,2,2], [10,2,2], [10,2,2], ], particleSize: [5,4.5,4,3.5,3], particleVelocity: [0,5,0], particleAcceleration: [0,-5,0], particleLifetime: 2, particleVelocitySpread: [5,5,5], }) } }, }, update: function(){ if(this.times++ > 20)this.destroy(); for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter && e !== this && e.position.distance(this.position) < 7 && !e.hasTag('unhurtable') && isHurtable(this.shooter,e) && spread(this.position,e.position)){ e.hurt(e.name === '年兽'? 30 + Math.random() * 30:3 + Math.random() * 3,{attacker: this.shooter,damageType: '春节十二响'}); } } }, onEquip(entity){ if(!entity.boom || entity.boom.destroyed){ entity.weaponSight[1] = entity.player.addWearable({ mesh: 'mesh/春节鞭炮1.vb', bodyPart: Box3BodyPart.TORSO, scale: [0.1,0.1,0.1], offset: [0,0,-0.3], orientation: Quat.rotateX(0.5), }) } }, style: [ { mesh: 'mesh/打火石.vb', bodyPart: Box3BodyPart.RIGHT_HAND, scale: [0.6,0.6,0.6], offset: [0,0,0.2], orientation: Quat, }, ], }, 12: { name: '合金钛刀', type: 3, effect: { async'action0'({entity}){ if(world.currentTick - entity.lastAttack > 20){ entity.lastAttack = world.currentTick; if(entity.player.moveState !== Box3PlayerMoveState.GROUND){ await new Promise((r)=>{ const event = entity.onVoxelContact(({axis })=>{ if(axis.y === 1){ event.cancel(); r(); } }) }) } const angle = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); const center = entity.position.add({x: Math.cos(angle)* 5,y: 0,z: Math.sin(angle)* 5}); const sword = world.createEntity({ mesh: 'mesh/机甲大刀_炽热.vb', position: center.add({x: Math.cos(angle)* 5,y: 0,z: Math.sin(angle)* 5}), meshScale: [0.1,0.1,0.1], gravity: false, collides: false, meshOrientation: Quat.rotateY(angle), meshEmissive: 0.1, velocity: entity.raycast.direction.scale(1.2), }) sword.up = 0; sword.center = center; sword.angle = angle; sword.shooter = entity; sword.addTag('entity'); sword.tick = world.currentTick; sword.update = ITEM[12].update; } }, 'action1'({entity}){ if(world.currentTick - entity.lastSkill < 200)return; entity.lastSkill = Infinity; entity.lastAttack = Infinity; entity.isHurtable = false; entity.player.cameraFovY = 0.4; const bullet = world.createEntity({ mesh: 'mesh/单元方块.vb', position: entity.position, friction: 10, meshScale: [0.0625,0.0625,0.0625], meshColor: [0,0,0,0], particleRate: 50, particleLifetime: 0.5, particleSize: [8,6,4,2,0.5], velocity: entity.raycast.direction.scale(3), particleColor: [ new Box3RGBColor(10,9,2), new Box3RGBColor(5,0.25,0.1), new Box3RGBColor(3,0.05,0.05), new Box3RGBColor(0,0,0), new Box3RGBColor(0,0,0), ], }) const show = world.createEntity({ mesh: 'mesh/机甲大刀_炽热.vb', position: entity.position, meshScale: [0.02,0.02,0.02], velocity: entity.raycast.direction.scale(3), meshEmissive: 0.01, collides: false, }) entity.player.cameraEntity = bullet; for(const e of entity.watchers){ e.player.cameraEntity = bullet; } bullet.addTag(entity.player.userKey); entity.angle = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); entity.up = Math.min(0,-entity.player.cameraPitch); show.meshOrientation = Quat.rotateX(Math.PI).rotateY(entity.angle); entity.bullet = bullet; entity.show = show; bullet.shooter = entity; bullet.addTag('bullet'); entity.addTag('entity'); entity.update = ITEM[12].flying; entity.player.invisible = true; entity.player.showName = false; entity.enableDamage = false; bullet.startTick = world.currentTick; bullet.onVoxelContact(bullet.destroy); bullet.onEntityContact(bullet.destroy); setTimeout(bullet.destroy,20000); bullet.onDestroy(()=>{ ITEM[12].end_fly(entity); }) } }, end_fly: function(entity){ entity.removeTag('entity'); entity.lastSkill = world.currentTick; entity.lastAttack = world.currentTick - 20; entity.player.cameraFovY = 0.25; entity.show.destroy(); entity.position.copy(entity.bullet.position); entity.player.cameraEntity = entity; entity.isHurtable = true; entity.player.invisible = false; entity.player.showName = true; entity.enableDamage = true; for(const e of entity.watchers){ e.player.cameraEntity = entity; } if(entity.hp){ world.sound({ sample: 'audio/重击.mp3', position: entity.position, radius: 320, }) for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(entity.position) < 10 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(entity.position,e.position)){ e.hurt((world.currentTick - entity.bullet.startTick)* 7,{attacker: entity,damageType: '修罗巨剑'}); const direction = e.position.sub(entity.position).add({x: 0,y: 1,z: 0}); e.velocity.addEq(direction.scale((world.currentTick - entity.bullet.startTick)* 0.4 / direction.mag()** 2 / e.mass * 1.75)); } } const ball = world.createEntity({ mesh: 'mesh/光球.vb', position: entity.position, gravity: false, collides: false, meshScale: [0.005,0.005,0.005], meshColor: [1,0.01,0.01,1], }) ball.addTag('entity'); ball.update = ITEM[1].explodeUpdate; } }, flying: function(){ this.show.meshOrientation = Quat.rotateX(Math.PI /((world.currentTick - this.bullet.startTick)* 0.2)).rotateY(this.angle); if(this.show.position.distance(this.bullet.position) > 0.1){ this.show.position.copy(this.bullet.position); } this.show.velocity.copy(this.bullet.velocity); for(const e of world.querySelectorAll`.target`){ if(e !== this && e.position.distance(this.bullet.position) < 5 && !e.hasTag('unhurtable') && isHurtable(this,e) && spread(this.bullet.position,e.position)){ e.hurt((world.currentTick - this.bullet.startTick)* 3,{attacker: this,damageType: '熔光业火斩'}); } } }, update: function(){ const tick = world.currentTick - this.tick; if(tick > 15){ for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter && e.position.distance(this.position) < 10 && !e.hasTag('unhurtable') && isHurtable(this.shooter,e) && spread(this.position,e.position)){ e.hurt(25,{attacker: this.shooter,damageType: '巨剑焚烧斩'}); } } if(tick > 18){ this.destroy(); } }else{ const up = tick > 11 ?(1 -(tick - 11)* 0.25):(tick * 0.1); this.meshOrientation = Quat.rotateX(up).rotateY(this.angle); this.position = this.center.add({x: Math.cos(this.angle)* Math.cos(up)* 5,y: Math.sin(up)* 5,z: Math.sin(this.angle)* Math.cos(up)* 5}); } }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/机甲大刀.vb', scale: [0.3,0.3,0.3], orientation: Quat.rotateX(Math.PI).rotateZ(Math.PI * 0.9), offset: [0,-0.4,0.7], } ], }, 13: { name: '烟花', type: 3, effect: { 'action0'({entity}){ if(world.currentTick - entity.lastAttack > 10){ entity.lastAttack = world.currentTick; const bullet = world.createEntity({ bounds: [0,0,0], gravity: false, position: entity.position, friction: 10, velocity: entity.raycast.direction.scale(3), particleRate: 200, particleColor: ColorList[3], particleLifetime: 2, particleSize: [0.3,0.3,0.3,0.3,0.3], }) entity.sound('audio/烟花.mp3'); bullet.addTag('bullet'); bullet.shooter = entity; bullet.addTag(entity.player.userKey); bullet.onEntityContact(bullet.destroy); bullet.onVoxelContact(bullet.destroy); setTimeout(bullet.destroy,2000); bullet.onDestroy(()=>{ for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(bullet.position) < 7 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(bullet.position,e.position)){ e.hurt(e.name === '年兽'? 85:25,{attacker: entity,damageType: '绽放礼祭'}); } } bombEffect(bullet.position); }) } }, 'action1'({entity}){ if(world.currentTick - entity.lastSkill > 100){ entity.lastSkill = world.currentTick; particleShoot(entity,entity.raycast.direction); } }, }, style: [ { mesh: 'mesh/烟花.vb', bodyPart: Box3BodyPart.RIGHT_HAND, scale: [0.15,0.15,0.15], offset: [0,-0.1,0.1], }, ], }, 14: { name: '破碎法杖', type: 2, effect: { 'action0'({entity}){ if(world.currentTick - entity.lastAttack > 30){ entity.lastAttack = world.currentTick; //确定攻击目标 const angle = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); const up = Math.atan2(entity.raycast.direction.y,Math.sqrt(entity.raycast.direction.x ** 2 + entity.raycast.direction.z ** 2)); const targets = []; for(const e of world.querySelectorAll`.target`){ const direction = e.position.sub(entity.position); const a = Math.atan2(direction.z,direction.x); const u = Math.atan2(direction.y,Math.sqrt(direction.x ** 2 + direction.z ** 2)); if(entity !== e && e.hp && Math.min(Math.abs(angle - a),Math.abs(PI2 - angle + a)) < 0.5 && Math.abs(up - u) < 0.5 && !e.hasTag('unhurtable') && isHurtable(entity,e)){ targets.push(e); } } var target = targets.sort((a,b)=>{ return entity.position.distance(a.position) - entity.position.distance(b.position); })[0]; if(!target){ target = entity.position.add(entity.raycast.direction.scale(500)); }else{ target = target.position; } //发射子弹 for(let i=0;i<3;i++){ const u = up + Math.random() * 0.7; const a = angle + Math.random() * 0.7 - 0.35; const arrow = world.createEntity({ mesh: 'mesh/能量箭前端.vb', position: entity.position, gravity: false, meshScale: [0.03,0.03,0.03], meshOrientation: Quat.rotateX(u).rotateY(a), friction: 10, velocity: new Box3Vector3(Math.cos(a) * Math.cos(u) * 3,Math.sin(u) * 3,Math.sin(a) * Math.cos(u) * 3), particleRate: 10, particleLifetime: 0.5, particleSize: [8,6,4,2,0.5], particleColor: [ new Box3RGBColor(10,10,0), new Box3RGBColor(10,0.5,0), new Box3RGBColor(10,0,0), new Box3RGBColor(0.5,0,0), new Box3RGBColor(0,0,0), ], }) arrow.addTag('bullet'); arrow.addTag('entity'); arrow.addTag(entity.player.userKey); arrow.shooter = entity; arrow.target = target; arrow.angle = a; arrow.up = u; arrow.update = ITEM[14].flying; arrow.onVoxelContact(arrow.destroy); arrow.onEntityContact(arrow.destroy); arrow.onDestroy(()=>{ for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(arrow.position) < 5 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(arrow.position,e.position)){ e.hurt(20,{attacker: entity,damageType: '晶体破碎'}); const direction = e.position.sub(arrow.position).add({x: 0,y: 1,z: 0}); e.velocity.addEq(direction.scale(1 / direction.mag() ** 2 / e.mass * 1.75)); } } world.sound({ sample: 'audio/破碎.mp3', position: arrow.position.position, radius: 320, }) const ball = world.createEntity({ mesh: 'mesh/光球.vb', position: arrow.position, gravity: false, collides: false, meshScale: [0.005,0.005,0.005], meshColor: [1,0.01,0.01,1], }) ball.addTag('entity'); ball.update = ITEM[1].explodeUpdate; }) setTimeout(arrow.destroy,20000); } } }, 'action1'({entity}){ if(entity.spoceEnergy > 20 && (!entity.shields || entity.shields[0].destroyed)){ entity.shields = []; for(let i=0;i<11;i++){ const y = i * 0.18 - 0.9; const scale = Math.cos(y); const direction = i % 2? 1:-1; const ring = world.createEntity({ mesh: 'mesh/雷阵.vb', gravity: false, collides: false, particleRate: 20, particleLifetime: 0.5, particleSize: [8,6,4,2,0.5], particleColor: [ new Box3RGBColor(10,10,0), new Box3RGBColor(10,0.5,0), new Box3RGBColor(10,0,0), new Box3RGBColor(0.5,0,0), new Box3RGBColor(0,0,0), ], }) ring.y = y; ring.scale = scale; ring.direction = direction; entity.shields.push(ring); const keyframes = []; for(let i=0;i<4;i++){ keyframes.push({ meshOrientation: Quat.rotateY(i * direction), }) } ring.animate(keyframes,{ direction: Box3AnimationDirection.WRAP, iterations: Infinity, duration: 496, }) } entity.shields[0].state = 1; entity.shields[0].startTick = world.currentTick; entity.shields[0].scale = 1; entity.shields[0].shooter = entity; entity.shields[0].addTag('entity'); entity.shields[0].addTag('diearea'); entity.shields[0].update = ITEM[14].update; entity.shields[0].shields = entity.shields; } } }, flying: function(){ const direction = this.target.sub(this.position); const angle = Math.atan2(direction.z,direction.x); const up = Math.atan2(direction.y,Math.sqrt(direction.x ** 2 + direction.z ** 2)); if(Math.abs(this.up - up) < 0.1){ this.up = up; }else if(up > this.up){ this.up += 0.1; }else if(up < this.up){ this.up -= 0.1; } this.direction = angle; rotate(this); this.meshOrientation = Quat.rotateX(this.up).rotateY(this.angle); this.velocity.set(Math.cos(this.angle) * Math.cos(this.up) * 3,Math.sin(this.up) * 3,Math.sin(this.angle) * Math.cos(this.up) * 3); }, update: function(){ const current = world.currentTick - this.startTick; this.shooter.spoceEnergy--; if(this.shooter.spoceEnergy < 0){ this.shooter.spoceEnergy = 0; } if(this.shooter.player.action1Button && this.shooter.spoceEnergy > 10){ this.state++; }else{ this.state--; } if(this.state === 0){ for(const e of this.shields){ e.destroy(); } return; } if(this.state > 10){ this.state = 10; } this.scale = 2 * this.state; const target = this.shooter.watcher? this.shooter:this.shooter.player.cameraEntity; for(const e of this.shields){ if(target){ e.velocity.x = target.velocity.x * 0.2; e.velocity.y = target.velocity.y * 0.1; e.velocity.z = target.velocity.z * 0.2; e.position = target.position.add({x: 0,y: e.y * this.scale,z: 0}); } e.meshScale.x = this.scale / 120.5 * e.scale; e.meshScale.z = this.scale / 120.5 * e.scale; e.meshOrientation = Quat.rotateY(current * 0.2 * e.direction); } if(target){ for(const e of world.querySelectorAll`.bullet`.concat(world.querySelectorAll`.enemybullet`)){ if(e.position.distance(target.position) < this.scale && e.shooter && e.shooter !== this.shooter && isHurtable(this.shooter,e.shooter)){ e.destroy(); } } } }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/碎片法杖.vb', scale: [0.4,0.4,0.4], offset: [0,-0.2,0.3], orientation: Quat.rotateY(Math.PI).rotateZ(-0.2), } ], }, 15: { name: '水神之弓', type: 0, effect: { 'action0'({entity}){ if(world.currentTick - entity.lastAttack > 20){ entity.lastAttack = world.currentTick; const d = entity.raycast.direction; entity.sound('audio/小水流.mp3'); const arrow = world.createEntity({ mesh: 'mesh/arrow.vb', meshScale: [0.01,0.01,0.01], meshOrientation: Quat.rotateY(Math.PI * 0.5).rotateX(Math.atan2(d.y,Math.sqrt(d.x ** 2 + d.z ** 2))).rotateY(Math.atan2(d.z,d.x)), position: entity.position, velocity: d.scale(5), friction: 10, }) const particle = world.createEntity({ position: entity.position, bounds: [0,0,0], collides: false, particleRate: 100, particleLifetime: 2, particleSize: [15,5,1], particleColor: [ new Box3RGBColor(0,0,10), new Box3RGBColor(0,0.5,10), new Box3RGBColor(0,10,10), new Box3RGBColor(0.5,10,10), new Box3RGBColor(10,10,10), ], particleNoise: 5, particleNoiseFrequency: 2, velocity: d.scale(5), }) arrow.shooter = entity; arrow.addTag('bullet'); arrow.addTag('entity'); arrow.update = ITEM[15].update; arrow.addTag(entity.player.userKey); arrow.onEntityContact(arrow.destroy); arrow.onVoxelContact(arrow.destroy); setTimeout(arrow.destroy,20000); arrow.onDestroy(()=>{ particle.destroy(); for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(arrow.position) < 10 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(arrow.position,e.position)){ e.hurt(15,{attacker: entity,damageType: '水穹箭雨'}); } } }) } }, 'action1'({entity}){ if(world.currentTick - entity.lastSkill > 40){ entity.lastSkill = world.currentTick; const d = entity.raycast.direction.scale(2); entity.sound('audio/大水流.mp3'); for(let i=0;i<2;i++){ const sword = world.createEntity({ mesh: 'mesh/水刃.vb', position: entity.position, meshScale: [0.03,0.03,0.03], gravity: false, collides: false, velocity: d, meshOrientation: Quat.rotateY(Math.PI * 0.5).rotateZ((i? 0.25:-0.25) * Math.PI).rotateX(Math.atan2(d.y,Math.sqrt(d.x ** 2 + d.z ** 2))).rotateY(Math.atan2(d.z,d.x)), particleRate: 20, particleLifetime: 2, particleSize: [15,5,1], particleColor: [ new Box3RGBColor(0,0,10), new Box3RGBColor(0,0.5,10), new Box3RGBColor(0,10,10), new Box3RGBColor(0.5,10,10), new Box3RGBColor(10,10,10), ], particleNoise: 5, particleNoiseFrequency: 2, }) sword.addTag('bullet'); sword.addTag('entity'); sword.shooter = entity; sword.direction = d; sword.update = ITEM[15].flying; setTimeout(sword.destroy,20000); } } } }, flying: function(){ for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter && e.position.distance(this.position) < 10 && !e.hasTag('unhurtable') && isHurtable(this.shooter,e) && spread(this.position,e.position)){ e.hurt(2.5,{attacker: this.shooter,damageType: '深海怒浪'}); } } this.velocity.copy(this.direction); if(voxels.getVoxel(this.position.x,this.position.y,this.position.z)){ this.destroy(); } }, update: function(){ if(!this.voxelContacts.length){ const d = this.velocity; this.meshOrientation = Quat.rotateY(Math.PI * 0.5).rotateX(Math.atan2(d.y,Math.sqrt(d.x ** 2 + d.z ** 2))).rotateY(Math.atan2(d.z,d.x)); for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter && e.position.distance(this.position) < 5 && !e.hasTag('unhurtable') && isHurtable(this.shooter,e) && spread(this.position,e.position)){ e.hurt(5,{attacker: this.shooter,damageType: '星水落箭'}); } } }else{ this.destroy(); } }, style: [ { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/水弓.vb', scale: [0.2,0.2,0.2], offset: [0,0,0], orientation: Quat.rotateY(-Math.PI * 0.5).rotateZ(Math.PI * 0.75), } ], }, 16: { name: '雷能双刃', type: 3, effect: { 'action0'({entity}){ if(world.currentTick - entity.lastAttack > 70){ entity.lastAttack = world.currentTick; const d = entity.raycast.direction.scale(2); for(let i=0;i<2;i++){ const sword = world.createEntity({ mesh: 'mesh/雷刃.vb', position: entity.position, meshScale: [0.03,0.03,0.03], gravity: false, collides: false, velocity: d, meshOrientation: Quat.rotateY(Math.PI * 0.5).rotateZ((i? 0.25:-0.25) * Math.PI).rotateX(Math.atan2(d.y,Math.sqrt(d.x ** 2 + d.z ** 2))).rotateY(Math.atan2(d.z,d.x)), particleRate: 20, particleLifetime: 2, particleSize: [15,5,1], particleColor: [ new Box3RGBColor(0.033,1,10), new Box3RGBColor(10,0.025,10), new Box3RGBColor(0.05,1,10), new Box3RGBColor(10,0.5,10), new Box3RGBColor(0.2,1,10) ], particleNoise: 5, particleNoiseFrequency: 2, }) sword.addTag('bullet'); sword.addTag('entity'); sword.shooter = entity; sword.direction = d; sword.update = ITEM[16].flying; setTimeout(sword.destroy,20000); } } }, 'action1'({entity}){ if(world.currentTick - entity.lastSkill > 120){ entity.player.invisible = true; entity.player.showName = false; entity.lastSkill = Infinity; entity.lastAttack = Infinity; entity.enableDamage = false; entity.isHurtable = false; initParticle(entity); Object.assign(entity,{ particleRate: 5, particleLifetime: 2, particleSize: [15,5,1], particleColor: [ new Box3RGBColor(0.033,1,10), new Box3RGBColor(10,0.025,10), new Box3RGBColor(0.05,1,10), new Box3RGBColor(10,0.5,10), new Box3RGBColor(0.2,1,10) ], particleNoise: 5, particleNoiseFrequency: 5, }) const time = world.currentTick; let attacked = false; const event = entity.player.onPress(({button})=>{ if(world.currentTick - time > 2){ if(attacked){ event.cancel(); return; } if(button === Box3ButtonType.ACTION1){ attacked = true; ITEM[16].show(entity); event.cancel(); } } }) setTimeout(()=>{ if(!attacked){ attacked = true; ITEM[16].show(entity); event.cancel(); } },7500); } } }, show: async function(entity){ entity.player.invisible = false; entity.player.showName = true; entity.lastSkill = world.currentTick; entity.lastAttack = world.currentTick - 70; entity.enableDamage = true; entity.isHurtable = true; entity.addTag('entity'); const angle = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); const direction = new Box3Vector3(Math.cos(angle),0,Math.sin(angle)); Object.assign(entity,{ particleRate: 100, particleLifetime: 1, particleSize: [15,5,1], particleColor: [ new Box3RGBColor(0.033,1,10), new Box3RGBColor(10,0.025,10), new Box3RGBColor(0.05,1,10), new Box3RGBColor(10,0.5,10), new Box3RGBColor(0.2,1,10), ], }) entity.update = ITEM[16].update; entity.velocity.x = direction.x * 8; entity.velocity.z = direction.z * 8; await sleep(800); entity.particleRate = 0; }, flying: function(){ for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter && e.position.distance(this.position) < 10 && !e.hasTag('unhurtable') && isHurtable(this.shooter,e) && spread(this.position,e.position)){ e.hurt(4,{attacker: this.shooter,damageType: '降雷神罚'}); } } this.velocity.copy(this.direction); if(voxels.getVoxel(this.position.x,this.position.y,this.position.z)){ this.destroy(); } }, update: function(){ if(world.currentTick - this.lastSkill > 6){ this.removeTag('entity'); } for(const e of world.querySelectorAll`.target`){ if(e !== this && e.position.distance(this.position) < 6 && !e.hasTag('unhurtable') && isHurtable(this,e) && spread(this.position,e.position)){ e.hurt(30,{attacker: this,damageType: '雷影突刺'}); e.velocity.addEq(this.velocity.scale(1.75 / e.mass)); } } }, style: [ { bodyPart: Box3BodyPart.LEFT_HAND, mesh: 'mesh/雷光之审判.vb', scale: [0.2,0.2,0.2], offset: [0,-0.25,0.6], orientation: Quat.rotateY(Math.PI * 0.5).rotateZ(-0.2), }, { bodyPart: Box3BodyPart.RIGHT_HAND, mesh: 'mesh/雷光之审判.vb', scale: [0.2,0.2,0.2], offset: [0,-0.25,0.6], orientation: Quat.rotateY(Math.PI * 0.5).rotateZ(-0.2), } ], }, 17: { name: '天空机甲', type: 3, effect: { 'action0'({entity}){ if(entity.player.crouchButton){ if(world.currentTick - entity.lastSkill < 150)return; entity.lastSkill = world.currentTick; const a = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); const u = Math.atan2(entity.raycast.direction.y,Math.sqrt(entity.raycast.direction.x ** 2 + entity.raycast.direction.z ** 2)); const d = entity.raycast.direction.clone(); const bullet = world.createEntity({ mesh: 'mesh/导弹.vb', position: entity.position, meshScale: [0.03,0.03,0.03], meshOrientation: Quat.rotateX(u).rotateY(a), velocity: d.scale(4), friction: 10, particleRate: 20, particleLifetime: 0.75, particleSize: [2,0.65,0.23], particleColor: [ new Box3RGBColor(10,10,10), new Box3RGBColor(0.5,0.5,0.5), new Box3RGBColor(0.2,0.2,0.2), ], }) bullet.addTag(entity.player.userKey); bullet.addTag('bullet'); bullet.addTag('entity'); bullet.shooter = entity; bullet.update = ITEM[17].falling; bullet.onVoxelContact(bullet.destroy); bullet.onEntityContact(bullet.destroy); setTimeout(bullet.destroy,20000); bullet.onDestroy(()=>{ world.sound({ sample: 'audio/explode.mp3', position: bullet.position, radius: 320, }) for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(bullet.position) < 15 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(bullet.position,e.position)){ var damage = 45; if(e.isPlayer){ if(e.hasTag('flying')){ damage = 30; } }else{ switch(e.name){ case '灭世飞船': damage = 30; break; case '冷光人偶': damage = 30; break; default: damage = 45; break; } } e.hurt(damage,{attacker: entity,damageType: '机甲陨灭炮'}); const direction = e.position.sub(bullet.position).add({x: 0,y: 1,z: 0}); e.velocity.addEq(direction.scale(5 / direction.mag()** 2 / e.mass * 1.75)); } } const ball = world.createEntity({ mesh: 'mesh/光球.vb', position: bullet.position, gravity: false, collides: false, meshScale: [0.005,0.005,0.005], meshColor: [1,1,1,1], }) ball.addTag('entity'); ball.update = ITEM[1].explodeUpdate; }) }else{ if(world.currentTick - entity.lastAttack < 15)return; entity.lastAttack = world.currentTick; const a = Math.atan2(entity.raycast.direction.z,entity.raycast.direction.x); const u = Math.atan2(entity.raycast.direction.y,Math.sqrt(entity.raycast.direction.x ** 2 + entity.raycast.direction.z ** 2)); const d = entity.raycast.direction.clone(); const p = [ entity.position.sub({x: Math.cos(a + Math.PI * 0.5) * 0.5,y: 0,z: Math.sin(a + Math.PI * 0.5) * 0.5}), entity.position.sub({x: Math.cos(a - Math.PI * 0.5) * 0.5,y: 0,z: Math.sin(a - Math.PI * 0.5) * 0.5}), ] for(const position of p){ const bullet = world.createEntity({ mesh: 'mesh/蓝色激光.vb', position, meshScale: [0.03,0.03,0.03], meshOrientation: Quat.rotateX(u).rotateY(a), velocity: d.scale(5), gravity: false, friction: 10, particleRate: 20, particleLifetime: 2, particleSize: [2,0.65,0.23], particleColor: [ new Box3RGBColor(0,0,10), new Box3RGBColor(0,10,10), new Box3RGBColor(10,10,10), ], }) bullet.vel = d.scale(5); bullet.addTag(entity.player.userKey); bullet.addTag('bullet'); bullet.addTag('entity'); bullet.shooter = entity; bullet.update = ITEM[17].update; bullet.onVoxelContact(bullet.destroy); bullet.onEntityContact(bullet.destroy); setTimeout(bullet.destroy,20000); bullet.onDestroy(()=>{ for(const e of world.querySelectorAll`.target`){ if(e !== entity && e.position.distance(bullet.position) < 10 && !e.hasTag('unhurtable') && isHurtable(entity,e) && spread(bullet.position,e.position)){ var damage = 5; if(e.isPlayer){ if(e.hasTag('flying')){ damage = 20; } }else{ switch(e.name){ case '灭世飞船': damage = 20; break; case '冷光人偶': damage = 20; break; default: damage = 5; break; } } e.hurt(damage,{attacker: entity,damageType: '机甲天基炮'}); } } const ball = world.createEntity({ mesh: 'mesh/光球.vb', position: bullet.position, gravity: false, collides: false, meshScale: [0.005,0.005,0.005], meshColor: [0.01,0.01,1,1], }) ball.addTag('entity'); ball.update = ITEM[1].explodeUpdate; }) } } }, 'action1'({entity}){ initParticle(entity); Object.assign(entity,{ particleLifetime: 0.5, particleSize: [3,1,0.2,0,0], particleVelocity: [0,-10,0], particleColor: [ new Box3RGBColor(10,10,0), new Box3RGBColor(10,0.5,0), new Box3RGBColor(10,0,0), new Box3RGBColor(0.5,0,0), new Box3RGBColor(0,0,0), ], }) } }, update: function(){ this.velocity.copy(this.vel); for(const e of world.querySelectorAll`.target`){ if(e !== this.shooter && e.position.distance(this.position) < 5 && !e.hasTag('unhurtable') && isHurtable(this.shooter,e) && spread(this.position,e.position)){ var damage = 2; if(e.isPlayer){ if(e.hasTag('flying')){ damage = 5; } }else{ switch(e.name){ case '灭世飞船': damage = 5; break; case '冷光人偶': damage = 5; break; default: damage = 2; break; } } e.hurt(damage,{attacker: this.shooter,damageType: '机甲镭射弹'}); } } }, falling: function(){ if(!this.voxelContacts.length){ const d = this.velocity; this.meshOrientation = Quat.rotateX(Math.atan2(d.y,Math.sqrt(d.x ** 2 + d.z ** 2))).rotateY(Math.atan2(d.z,d.x)); } }, style: [ { bodyPart: Box3BodyPart.TORSO, mesh: 'mesh/天空机甲身体.vb', scale: [0.4,0.4,0.4], offset: [0,0.1,-0.2], }, { bodyPart: Box3BodyPart.TORSO, mesh: 'mesh/天空机甲炮管.vb', scale: [0.4,0.4,0.4], offset: [0.5,0.2,0.2], orientation: Quat.rotateY(Math.PI - 0.2), }, { bodyPart: Box3BodyPart.TORSO, mesh: 'mesh/天空机甲炮管.vb', scale: [0.4,0.4,0.4], offset: [-0.5,0.2,0.2], orientation: Quat.rotateY(Math.PI + 0.2), }, ], }, } function initParticle(entity){ Object.assign(entity,{ particleRate: 0, particleLimit: 100, particleLifetime: 10, particleLifetimeSpread: 0, particleSize: [1,1,1,1,1], particleSizeSpread: 0, particleColor: [new Box3RGBColor(1,1,1),new Box3RGBColor(1,1,1),new Box3RGBColor(1,1,1),new Box3RGBColor(1,1,1),new Box3RGBColor(1,1,1)], particleVelocity: new Box3Vector3(0,0,0), particleVelocitySpread: new Box3Vector3(0,0,0), particleDamping: 0, particleAcceleration: new Box3Vector3(0,0,0), particleNoise: 0, particleNoiseFrequency: 1, }) } function bombEffect(position,time = 100,power = 10){ const entity = world.createEntity({ mesh: 'mesh/单元方块.vb', bounds: [0,0,0], position, collides: false, gravity: false, fixed: true, meshScale: [0.0625,0.0625,0.0625], meshColor: [0,0,0,0], }) Object.assign(entity,{ particleRate: 1000, particleColor: [ [10,2,2], [10,2,2], [10,2,2], [10,2,2], [10,2,2], ], particleSize: [5,4.5,4,3.5,3], particleLifetime: 2, particleVelocity: [0,5,0], particleAcceleration: [0,-5,0], particleVelocitySpread: [power,power,power], }) setTimeout(entity.destroy,time); } function particleSpread(entity,colorList,scale = 1,direction){ entity.particleRate = 200; entity.particleLifetime = 2; entity.particleColor = colorList; entity.particleSize = [15 * scale,10 * scale,5 * scale,2 * scale,scale]; entity.particleSizeSpread = 2 * scale; entity.particleVelocitySpread = [20 * scale,20 * scale,20 * scale]; entity.particleAcceleration = [direction.x * 10,direction.y * 10,direction.z * 10]; } const YELLOW = new Box3RGBColor(10,10,2); const CYAN = new Box3RGBColor(2,10,10); const MAGENTA = new Box3RGBColor(10,2,10); const RED = new Box3RGBColor(10,2,2); const GREEN = new Box3RGBColor(2,10,2); const BLUE = new Box3RGBColor(2,2,10); const ColorList = [ [YELLOW,YELLOW,YELLOW,YELLOW,YELLOW], [CYAN,CYAN,CYAN,CYAN,CYAN], [MAGENTA,MAGENTA,MAGENTA,MAGENTA,MAGENTA], [RED,RED,RED,RED,RED], [GREEN,GREEN,GREEN,GREEN,GREEN], [BLUE,BLUE,BLUE,BLUE,BLUE], ] function randomColor(){ return ColorList[Math.floor(ColorList.length * Math.random())]; } function particleShoot(entity,velocity){ const fireball = world.createEntity({ bounds: [0,0,0], gravity: false, position: entity.position, friction: 10, }) entity.sound('audio/烟花.mp3'); fireball.addTag('bullet'); fireball.addTag(entity.player.userKey); fireball.shooter = entity; const color = randomColor(); particleSpread(fireball,color,0.3,velocity.scale(-1)); fireball.velocity.copy(velocity.scale(2)); fireball.onVoxelContact(()=>{ explode(fireball,color,velocity); }) fireball.onEntityContact(()=>{ explode(fireball,color,velocity); }) setTimeout(()=>{ explode(fireball,color,velocity); },2000); } async function explode(fireball,color,velocity){ if(fireball.exploded)return; fireball.exploded = true; fireball.velocity.set(0,0,0); fireball.sound('audio/烟花_2.mp3'); particleSpread(fireball,color,1,velocity.scale(-1)); for(const e of world.querySelectorAll`.target`){ if(e !== fireball.shooter && e.position.distance(fireball.position) < 15 && !e.hasTag('unhurtable') && isHurtable(fireball.shooter,e) && spread(fireball.position,e.position)){ e.hurt(e.name === '年兽'? 350:50,{attacker: fireball.shooter,damageType: '新年大礼炮'}); } } await sleep(1500); fireball.destroy(); } function getBounds(entity){ return new Box3Bounds3(entity.position.sub(entity.bounds),entity.position.add(entity.bounds)); } function getBigBounds(entity){ return new Box3Bounds3(entity.position.sub(entity.bounds.scale(3)),entity.position.add(entity.bounds.scale(3))); } function spread(a,b){ return !world.raycast(a,b.sub(a),{ ignoreEntities: true, maxDistance: a.distance(b), }).hit; } function rotate(entity,speed = 0.1){ let angle1 = entity.direction; if(angle1 < 0){ angle1 = PI2 + angle1; } if(entity.angle < 0){ entity.angle = PI2 + entity.angle; } entity.angle %= PI2; const angle2 = entity.angle; if(Math.min(Math.abs(angle1 - angle2),Math.abs(PI2 - angle1 + angle2)) < speed){ entity.angle = entity.direction; return; }else{ if(angle1 > angle2){ if(angle1 - angle2 < Math.PI){ entity.angle += speed; return 0; }else{ entity.angle -= speed; return 1; } }else{ if(angle1 +(PI2 - angle2) < Math.PI){ entity.angle += speed; return 0; }else{ entity.angle -= speed; return 1; } } } } function getRoom(x){ for(const a of world.damageBounds){ if(a.contains(x.position)){ return a; } } } function isHurtable(a,b){ const roomA = getRoom(a); const roomB = getRoom(b); if(roomA && roomA === roomB){ return true; }else{ if((roomA && roomA !== roomB) || (roomB && roomA !== roomB)){ return false; }else if(world.peace && a.isPlayer && b.isPlayer){ return false; }else if(SingleFighting && (a !== Host || b !== Challenger) && (a !== Challenger || b !== Host)){ return false; }else if((a.position.y < 8) !== (b.position.y < 8)){ return false; }else{ return true; } } } global.spread = spread; global.getRoom = getRoom; global.isHurtable = isHurtable; module.exports = ITEM;