"use strict"; (function(global){ function mushroomImage(){ return global.getRenderableImage?.("mamekusaredake", "") || global.images?.get?.("mamekusaredake") || null; } function growthOf(t){ return Math.max(0,Math.min(1,Number(t?.mamekusaredakeGrowth||0)||0)); } const hostAlphaCache = typeof WeakMap !== "undefined" ? new WeakMap() : null; function unit(seed="",salt=""){ if(typeof global.stableUnit==="function") return global.stableUnit(String(seed||"mame"),String(salt||"")); const s=`${seed}|${salt}`; let h=2166136261; for(let i=0;i>>0)%1000003)/1000003; } function alphaPointsForImage(img){ if(!img)return null; if(hostAlphaCache?.has(img)) return hostAlphaCache.get(img); let out=null; try{ const c=document.createElement("canvas"); c.width=64; c.height=64; const cx=c.getContext("2d",{willReadFrequently:true}); cx.clearRect(0,0,64,64); cx.drawImage(img,0,0,64,64); const data=cx.getImageData(0,0,64,64).data, pts=[]; for(let y=3;y<61;y++) for(let x=3;x<61;x++) if(data[(y*64+x)*4+3]>=96) pts.push([x,y]); out=pts.length?pts:null; }catch(_){out=null;} hostAlphaCache?.set(img,out); return out; } function hostPoint(t,img,dw,dh,index=0){ const seed=t?.birthSeed||t?.familyKey||t?.id||"mame-host"; const pts=alphaPointsForImage(img); if(pts?.length){ const k=Math.min(pts.length-1,Math.floor(unit(seed,`mame-pos-${index}`)*pts.length)); const p=pts[k]||pts[0]; return {x:(p[0]/63-.5)*dw,y:(p[1]/63-.5)*dh}; } // Fallback stays inside the usual non-transparent body ellipse. const a=unit(seed,`mame-a-${index}`)*Math.PI*2, rr=Math.sqrt(unit(seed,`mame-r-${index}`))*.70; return {x:Math.cos(a)*dw*.34*rr,y:Math.sin(a)*dh*.28*rr+dh*.03}; } function hostMushroomCount(g){ return g<=.001?0:Math.max(1,Math.min(5,Math.ceil(g*5))); } function infect(t, source=null){ if(!t||t.dead||t.mamekusaredakeDisease) return false; t.mamekusaredakeDisease=true; t.mamekusaredakeGrowth=0; t.mamekusaredakeDeathPlanted=false; t.mamekusaredakeSpeechAt=(t.world?.time||0)+3+Math.random()*5; t.world?.log?.(`${t.name}がマメクサレダケ病に罹患した。`,"accident",{participants:[t]}); return true; } function visualSizeForHost(t,g=growthOf(t)){ const rendered=Number(t?._mameRenderedSize||0)||0; if(rendered>0) return Math.max(3,rendered); const radius=Math.max(16,Number(t?.radius||20)||20); return Math.max(3,radius*1.16*Math.max(.05,g)); } function spawnDetached(world,t,growth=growthOf(t)){ if(!world||!t||typeof Item==="undefined") return null; const side=t.facingDir?.()||1; const it=new Item("mamekusaredake", t.x+side*(t.radius||20)*0.46, t.y+(t.radius||20)*0.30); it.mameDetached=true; it.mamePlanted=false; it.mameLife=1.25; it.vx=side*(35+Math.random()*25); it.vy=-35-Math.random()*20; it.mameDetachedSize=visualSizeForHost(t,growth); it.r=Math.max(2,it.mameDetachedSize/2.15); world.addItem?.(it,"mame-detached",{terrain:false}); return it; } function recover(t, reason="キノコが取れた"){ if(!t?.mamekusaredakeDisease) return false; const growth=growthOf(t); spawnDetached(t.world,t,growth); t.mamekusaredakeDisease=false; t.mamekusaredakeGrowth=0; t.mamekusaredakeSpeechAt=0; t.mamekusaredakeDeathPlanted=false; t.world?.spawnEffect?.("ring",t.x,t.y,{size:(t.radius||20)*(.55+.75*growth),life:.55,color:"rgba(190,153,80,.66)"}); t.world?.log?.(`${t.name}のマメクサレダケが外れて治った。`,"event",{participants:[t]}); return true; } function plantAt(world,x,y,r=34){ if(!world||typeof Item==="undefined")return null; const it=new Item("mamekusaredake",x,y); it.r=r; it.mamePlanted=true; it.mameDetached=false; it.nextSporeAt=(world.time||0)+1.2+Math.random(); world.addItem?.(it,"mame-plant",{terrain:false}); return it; } function plantFromHost(t){ if(!t?.world||t.mamekusaredakeDeathPlanted) return null; t.mamekusaredakeDeathPlanted=true; const g=growthOf(t); // 死亡サイズの50%以下なら地面には残らず消滅する。 if(g<=.5) return null; // 表示上の本数とは無関係に、死亡時に植わるのは必ず1本だけ。 return plantAt(t.world,t.x,t.y,Math.max(22,(t.radius||20)*(.62+.32*g))); } function spawnSpore(world,m){ if(!world||typeof Item==="undefined")return null; const a=Math.random()*Math.PI*2,d=Math.random()*(m.r||34)*.35; const s=new Item("mame_spore",m.x+Math.cos(a)*d,m.y+Math.sin(a)*d*.55); s.r=22+Math.random()*18; s.sporeAge=0; s.sporeLife=7+Math.random()*5; s.sporeConcentration=.45+Math.random()*.25; s.vx=Math.cos(a)*(6+Math.random()*10); s.vy=-4+Math.sin(a)*5; world.addItem?.(s,"mame-spore",{terrain:false}); return s; } function updateTarinai(t,dt){ if(!t||t.dead)return false; const now=t.world?.time||0; const sick=Boolean(t.zunchiDisease||t.sleepDisease||t.explosionDisease||t.fightDisease||t.mamekusaredakeDisease); if(t.mamekusaredakeDisease){ if(t.state==="sunbath"||(t.sunbathTimer||0)>.04){ t.sunbathTimer=0; t.sunbathLeisure=false; t.sunbathCooldown=Math.max(t.sunbathCooldown||0,20); t.visibleSpriteId=""; t.setActionState?.("idle",{target:null,reason:"マメクサレダケ病のため日光浴できない",sleeping:false,clearTarget:true}); } t.mamekusaredakeGrowth=Math.min(1.08,(Number(t.mamekusaredakeGrowth||0)||0)+dt/90); const g=growthOf(t); if(g>=.5){ const maxEnergy=Math.max(1,typeof global.tarinaiMaxEnergy==="function"?global.tarinaiMaxEnergy(t):(Number(t.maxEnergy)||100)); const severity=Math.max(0,Math.min(1,(g-.5)/.5)); const loss=dt*maxEnergy*(.0018+.0037*severity); t.energy=Math.max(0,(Number(t.energy)||0)-loss); if(loss>.01) t.showHpBar?.(); if(t.energy<=.5){ t.die?.("マメクサレダケ病",{fromDamage:true}); return true; } } } if(t.isAcquiredTarinai && sick && now>=Number(t.mamekusaredakeSpeechAt||0) && (t.nextBubbleAt||0)<=now){ const choices=[{text:"くるち、くるち",id:"voice_ochibi_disease_001"},{text:"おみじゅ...",id:"voice_ochibi_hot_007"},{text:"ぶるぶる",id:"voice_temp_cold"}]; const c=choices[Math.floor(Math.random()*choices.length)]; if(c&&t.bubble?.(c.text,4.5,"rgba(96,72,48,.82)")){ const a=global.TarinaiAudio; a?.playSample?.(c.id,1.1,"voice")||a?.play?.(c.id,{category:"voice",minGap:1.1}); } t.mamekusaredakeSpeechAt=now+7+Math.random()*10; } if(t.mamekusaredakeDisease && t.mamekusaredakeGrowth>=1){ t.die?.("マメクサレダケ病"); } return true; } function updateItem(item,dt,world){ if(item.type==="mamekusaredake"){ if(item.mameDetached){ item.mameLife=(item.mameLife||1)-dt; item.x+=(item.vx||0)*dt; item.y+=(item.vy||0)*dt; item.vy=(item.vy||0)+55*dt; item.vx*=Math.pow(.6,dt); if(item.mameLife<=0)item.amount=0; return true; } item.mamePlanted=true; const now=world?.time||0; if(now>=Number(item.nextSporeAt||0)){ item.nextSporeAt=now+1.4+Math.random()*1.8; if(Math.random()<.75)spawnSpore(world,item); } return true; } if(item.type==="mame_spore"){ item.sporeAge=(item.sporeAge||0)+dt; const life=Math.max(1,item.sporeLife||9); item.sporeConcentration=Math.max(0,1-item.sporeAge/life); item.x+=(item.vx||0)*dt; item.y+=(item.vy||0)*dt; item.vx*=Math.pow(.72,dt); item.vy*=Math.pow(.72,dt); for(const t of world?.tarinai||[]){ if(!t||t.dead||t.mamekusaredakeDisease)continue; if(distXY(item.x,item.y,t.x,t.y)<=item.r+(t.radius||18)*.45 && Math.random()0?Number(item.mameDetachedSize):(item.r||34)*2.15; if(!item.mameDetached){ ctx.save(); ctx.globalAlpha*=.34; ctx.fillStyle="rgba(38,28,18,.72)"; ctx.beginPath(); ctx.ellipse(size*.055,size*.41,size*.30,size*.085,0,0,Math.PI*2); ctx.fill(); ctx.restore(); } return drawMushroom(ctx,0,0,size,alpha,item.mameDetached?(time*2.2):0); } if(item.type==="mame_spore"){ const r=item.r||28,c=Math.max(0,Math.min(1,item.sporeConcentration??1));ctx.save();ctx.globalAlpha*=.10+.22*c;ctx.fillStyle="rgba(181,139,65,.58)";for(let i=0;i<3;i++){const a=(item.seed||0)+i*2.2,rr=r*(.30+i*.06);ctx.beginPath();ctx.arc(Math.cos(a)*r*.18,Math.sin(a)*r*.12,rr,0,Math.PI*2);ctx.fill();}ctx.restore();return true;} return false; } function mushroomHit(t,x,y){ if(!t?.mamekusaredakeDisease)return false; const worldTargets=Array.isArray(t._mameHostWorldTargets)?t._mameHostWorldTargets:[]; for(const p of worldTargets){ if(distXY(x,y,p.x,p.y)<=Math.max(8,(p.size||10)*.52)) return true; } // Fallback for the short interval before the first render after infection. // It intentionally stays conservative so pinching the body itself does not // accidentally cure the disease. const g=Math.max(.05,growthOf(t)); const face=typeof t.facingDir==="function"?(t.facingDir()||1):(t.facing||1); return distXY(x,y,t.x+face*(t.radius||20)*.30,t.y+(t.radius||20)*.18)<=Math.max(7,(t.radius||20)*.34*g); } global.TarinaiMamekusaredakeSystem=Object.freeze({infect,recover,plantAt,plantFromHost,spawnSpore,updateTarinai,updateItem,drawOnTarinai,drawItem,mushroomHit}); })(typeof window!=="undefined"?window:globalThis);