钢琴Boss重设计:6种激光模式乱序随机、小攻击改动、大炮塔惩罚激光

- 激光攻击改为6种模式全部乱序随机,局间无间隔:
  顺扫/反扫/顺滑奏/反滑奏(快速逐键),乱序(同时4/8键),齐射(P1:4连不射其余全射;P2保持原随机多键)
- topRain: 同时随机3个炮塔发射绿色弹
- pedal: 两边子弹统一为紫色orbP
- 新增大炮塔惩罚激光:玩家站在炮塔正下方蓄力1秒后发射99999伤害大激光
- drawPiano: 支持多炮塔同时发光
This commit is contained in:
JOJO 2026-08-06 14:31:53 +08:00
parent 1c6f15dca5
commit f830edd0c6
2 changed files with 37 additions and 20 deletions

View File

@ -38,7 +38,7 @@ function drawPiano(b,t,fl,split){
{const off2=split*28;
for(let ti=0;ti<6;ti++){const sd2=ti<3?-1:1,tx=-75+ti*30+sd2*off2;
circ(tx,-4,3.5,"#33436a");circ(tx-1,-5,1.5,"#55648a");
px(tx-1,-2,2,5,b.turrT>0&&b.turrI===ti?"#e8fbff":"#1b2434");}}
px(tx-1,-2,2,5,b.turrT>0&&((b.turrIs&&b.turrIs.includes(ti))||b.turrI===ti)?"#e8fbff":"#1b2434");}}
// —— 左右大炮塔踏板重音炮位左紫右蓝P2随最外环带滑开16 ——
{const off0=split*16;
for(const sd of[-1,1]){const px2=sd*(112+off0);

View File

@ -349,6 +349,19 @@ function updateBoss(){
else if(tn.rec>0){tn.rec--;if(tn.rec<=0)b.tent=null;}
}
}
// 钢琴大炮塔惩罚激光——玩家站在炮塔正下方蓄力1秒后发射99999伤害大激光
if(b.idx===2&&!lck){
const off0=b.phase>=1?16:0,p=G.p,warnW=14;
const leftX=b.x-(112+off0),rightX=b.x+(112+off0);
if(p.dead<=0&&Math.abs(p.x-leftX)<warnW&&p.y>b.y){
b.pedLasL=(b.pedLasL||0)+1;
if(b.pedLasL>=60){bossBeam(leftX,b.y+10,leftX,H+8,6,"#ff3355",10,40,99999,{b,ox:-(112+off0),oy:10,followX2:true});b.pedLasL=0;SFX.warn();}
}else b.pedLasL=0;
if(p.dead<=0&&Math.abs(p.x-rightX)<warnW&&p.y>b.y){
b.pedLasR=(b.pedLasR||0)+1;
if(b.pedLasR>=60){bossBeam(rightX,b.y+10,rightX,H+8,6,"#ff3355",10,40,99999,{b,ox:(112+off0),oy:10,followX2:true});b.pedLasR=0;SFX.warn();}
}else b.pedLasR=0;
}
const lck=(b.laserT||0)>0; // 巨宽核心激光期间压制其他攻击
// —— 主攻击 ——
b.mainT--;
@ -390,7 +403,7 @@ function bossMain(b,def,fm){
b.mainT=Math.round(10/fm);break;}
case "assault": // 暗黑突击:启动冲撞(锚点记当前位置,冲撞归来后正弦从此继续)
b.dashSt={ph:"tele",t:52};b.ax=b.x;b.ay=b.y;b.mainT=9999;break;
case "piano": { // 激光钢琴21键四种模式轮换——顺扫(逼走位)/反扫/乱序/齐射
case "piano": { // 激光钢琴21键六种模式全部乱序随机,局间无间隔
if(!b.keys)b.keys={n:21,seq:[],i:0,t:2,hot:-1,hotT:0,hotList:null,mode:3};
const ks=b.keys,n=ks.n;
if(ks.hotT>0){ks.hotT--;
@ -400,18 +413,21 @@ function bossMain(b,def,fm){
ks.hotList=null;ks.hot=-1;SFX.eshoot();}}
ks.t--;
if(ks.t<=0&&ks.hotT<=0){
if(ks.i>=ks.seq.length){ // 布下一局轮换模式5种
ks.mode=(ks.mode+1)%5;
if(ks.mode===0){ks.seq=[];for(let i=0;i<n-3;i++)ks.seq.push(i);} // 顺扫止于18号最右3键永远安全
else if(ks.mode===1){ks.seq=[];for(let i=n-1;i>=3;i--)ks.seq.push(i);} // 反扫止于3号最左3键永远安全
else if(ks.mode===2){ks.seq=shuffled(n);}
else if(ks.mode===3){ks.seq=[];for(let i=0;i<6+ph*2;i++)ks.seq.push(-1);} // -1=齐射标记
else{ks.seq=[];for(let i=0;i<n-3;i++)ks.seq.push(i);for(let i=n-4;i>=0;i--)ks.seq.push(i);} // 滑奏:顺扫到尾立刻反扫回来
ks.i=0;ks.t=Math.round((ph?14:22)/fm);
if(ks.i>=ks.seq.length){ // 布下一局完全随机选模式6种局间无间隔
ks.mode=rndi(0,6);
if(ks.mode===0){ks.seq=[];for(let i=0;i<n;i++)ks.seq.push(i);} // 顺扫全21键
else if(ks.mode===1){ks.seq=[];for(let i=n-1;i>=0;i--)ks.seq.push(i);} // 反扫全21键
else if(ks.mode===2){ks.seq=[];for(let i=0;i<n;i++)ks.seq.push(i);for(let i=n-2;i>=0;i--)ks.seq.push(i);} // 顺滑奏0→20→041键
else if(ks.mode===3){ks.seq=[];for(let i=n-1;i>=0;i--)ks.seq.push(i);for(let i=1;i<n;i++)ks.seq.push(i);} // 反滑奏20→0→2041键
else if(ks.mode===4){ks.seq=[];for(let i=0;i<5+ph*2;i++)ks.seq.push(-2);} // 乱序每次同时随机4/8键发射5+ph*2次
else if(ph>=1){ks.seq=[];for(let i=0;i<6+ph*2;i++)ks.seq.push(-1);} // 齐射P2保持原逻辑随机6键多次
else{ks.seq=[-3];} // 齐射P14连不射其余全射只发射一次
ks.i=0;ks.t=0; // 局间无间隔
}else{const cur=ks.seq[ks.i++];
if(cur===-1){const pool=shuffled(n);ks.hotList=pool.slice(0,4+ph*2);ks.hotT=9;ks.hotT0=9;ks.t=Math.round((ph?21:30)/fm);} // 齐射慢50%
else if(ks.mode<=1||ks.mode===4){ks.hot=cur;ks.hotT=1;ks.hotT0=1;ks.t=Math.round((ph?2:3)/fm);} // 顺/反扫/滑奏前摇快50%
else{if(ph>=1){ks.hotList=[cur,ks.i<ks.seq.length?ks.seq[ks.i++]:cur];ks.hot=-1;}else{ks.hot=cur;}ks.hotT=3;ks.hotT0=3;ks.t=Math.round((ph?3:5)/fm);} // 乱序P2一次点2键和音
if(cur===-1){const pool=shuffled(n);ks.hotList=pool.slice(0,4+ph*2);ks.hotT=9;ks.hotT0=9;ks.t=Math.round((ph?21:30)/fm);} // 齐射P2
else if(cur===-2){const pool=shuffled(n);ks.hotList=pool.slice(0,4+ph*4);ks.hotT=9;ks.hotT0=9;ks.t=Math.round((ph?7:10)/fm);} // 乱序P1同时4键P2同时8键
else if(cur===-3){const safeStart=rndi(0,n-4);const all=[];for(let i=0;i<n;i++)if(i<safeStart||i>=safeStart+4)all.push(i);ks.hotList=all;ks.hotT=9;ks.hotT0=9;ks.t=Math.round((ph?10:15)/fm);} // 齐射P14连不射
else{ks.hot=cur;ks.hotT=1;ks.hotT0=1;ks.t=Math.max(1,Math.round((ph?1:2)/fm));} // 顺/反扫/滑奏:快速
}
}
b.mainT=4;break;}
@ -485,14 +501,15 @@ function bossMinor(b,mk,fm){
case "spawnMine": spawnEnemy("mine",b.x,b.y+10,false);b.minorT=Math.round(280/fm);break;
case "aimSpread": for(let i=-2;i<=2;i++)ebul(b.x,b.y+12,a0+i*0.19,2.5,"orbO",15);b.minorT=Math.round(140/fm);break;
case "rain": for(let i=0;i<5;i++)ebul(rnd(20,W-20),-6,Math.PI/2+rnd(-0.1,0.1),2.2,"orbO",14);b.minorT=Math.round(125/fm);break;
case "topRain": { // 钢琴6座穹顶小炮塔轮流开火炮位与drawPiano同源P2随环带滑开28
const off2=b.phase>=1?28:0,ti=rndi(0,5),tx=b.x+(-75+ti*30)+(ti<3?-1:1)*off2;
b.turrI=ti;b.turrT=8;
for(let i=0;i<3;i++)ebul(tx+rnd(-3,3),b.y-2,Math.PI/2+rnd(-0.12,0.12),2.0,"orbG",13);
b.minorT=Math.round(150/fm);break;}
case "pedal": { // 钢琴踏板重音——左右大炮塔慢速大弹左紫右蓝P2随外环滑开16炮位与drawPiano同源
case "topRain": { // 钢琴同时随机3个穹顶小炮塔发射炮位与drawPiano同源P2随环带滑开28
const off2=b.phase>=1?28:0,idxs=shuffled(6).slice(0,3);
b.turrIs=idxs;b.turrT=8;
for(const ti of idxs){const tx=b.x+(-75+ti*30)+(ti<3?-1:1)*off2;
ebul(tx+rnd(-3,3),b.y-2,Math.PI/2+rnd(-0.12,0.12),2.0,"orbG",13);}
b.minorT=Math.round(50/fm);break;} // 绿色子弹攻击频率翻三倍
case "pedal": { // 钢琴踏板重音——左右大炮塔慢速大弹统一紫色P2随外环滑开16炮位与drawPiano同源
const off0=b.phase>=1?16:0;
for(const sd of[-1,1]){const bb=ebul(b.x+sd*(112+off0),b.y+10,Math.PI/2+sd*0.08,1.1,sd<0?"orbP":"dartB",18);
for(const sd of[-1,1]){const bb=ebul(b.x+sd*(112+off0),b.y+10,Math.PI/2+sd*0.08,1.1,"orbP",18);
bb.scale=2.4;bb.r=6;}
b.pedT=8;b.minorT=Math.round(280/fm);break;}
case "chain": for(let arm=0;arm<2;arm++)for(let i=0;i<4;i++)ebul(b.x,b.y+8,b.t*0.09+arm*Math.PI+i*0.11,1.7,"orbO",14);b.minorT=Math.round(44/fm);break;