diff --git a/c93053159.lua b/c93053159.lua index b9ac6b9b0..319feebe1 100644 --- a/c93053159.lua +++ b/c93053159.lua @@ -1,17 +1,8 @@ --白の枢機竜 local s,id,o=GetID() function s.initial_effect(c) - aux.AddCodeList(c,68468459) - aux.AddMaterialCodeList(c,68468459) - --aux.AddFusionProcCodeFun(c,68468459,s.mfilter,6,true,true) + aux.AddFusionProcCodeFun(c,68468459,s.mfilter,6,true,true) c:EnableReviveLimit() - local e0=Effect.CreateEffect(c) - e0:SetType(EFFECT_TYPE_SINGLE) - e0:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE) - e0:SetCode(EFFECT_FUSION_MATERIAL) - e0:SetCondition(s.Alba_System_Drugmata_Fusion_Condition()) - e0:SetOperation(s.Alba_System_Drugmata_Fusion_Operation()) - c:RegisterEffect(e0) local e1=Effect.CreateEffect(c) e1:SetType(EFFECT_TYPE_SINGLE) e1:SetProperty(EFFECT_FLAG_SINGLE_RANGE+EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE) @@ -45,79 +36,32 @@ end function s.splimit(e,se,sp,st) return bit.band(st,SUMMON_TYPE_FUSION)==SUMMON_TYPE_FUSION end -function s.Alba_System_Drugmata_Fusion_Filter(c,mg,fc,tp,chkf,gc) - if not c:IsFusionCode(68468459) and not c:IsHasEffect(EFFECT_FUSION_SUBSTITUTE) then return false end - local g=mg:Filter(s.matfilter,c,tp) - aux.GCheckAdditional=aux.dncheck - local res=g:CheckSubGroup(s.Alba_System_Drugmata_Fusion_Gcheck,6,6,fc,tp,c,chkf,gc) - aux.GCheckAdditional=nil - return res +function s.samecheck(c,sg) + local fuscodes={c:GetFusionCode()} + for _,code in ipairs(fuscodes) do + if not sg:IsExists(Card.IsCode,1,nil,code) then return true end + end + return false end -function s.matfilter(c,tp) - return c:IsLocation(LOCATION_GRAVE) and c:IsControler(tp) and not c:IsHasEffect(6205579) +function s.migfilter(c,fc) + return c:IsLocation(LOCATION_GRAVE) and c:IsControler(fc:GetControler()) end -function s.Alba_System_Drugmata_Fusion_Gcheck(g,fc,tp,ec,chkf,gc) - local sg=g:Clone() - sg:AddCard(ec) - if sg:IsExists(aux.TuneMagicianCheckX,1,nil,sg,EFFECT_TUNE_MAGICIAN_F) then return false end - if gc and not sg:IsContains(gc) then return false end - if aux.FCheckAdditional and not aux.FCheckAdditional(tp,sg,fc) - or aux.FGoalCheckAdditional and not aux.FGoalCheckAdditional(tp,sg,fc) then return false end - return g:GetClassCount(Card.GetFusionCode)==g:GetCount() - and (chkf==PLAYER_NONE or Duel.GetLocationCountFromEx(tp,tp,sg,fc)>0) + +if not s.abs_list then + s.abs_list={} end -function s.Alba_System_Drugmata_Fusion_Condition() - return function(e,g,gc,chkf) - if g==nil then return aux.MustMaterialCheck(nil,e:GetHandlerPlayer(),EFFECT_MUST_BE_FMATERIAL) end - local fc=e:GetHandler() - local tp=e:GetHandlerPlayer() - if gc then - if not g:IsContains(gc) then return false end - return g:IsExists(s.Alba_System_Drugmata_Fusion_Filter,1,nil,g,fc,tp,chkf,gc) - end - return g:IsExists(s.Alba_System_Drugmata_Fusion_Filter,1,nil,g,fc,tp,chkf,nil) - end -end -function s.Alba_System_Drugmata_Fusion_Operation() - return function(e,tp,eg,ep,ev,re,r,rp,gc,chkf) - local fc=e:GetHandler() - local tp=e:GetHandlerPlayer() - local fg=eg:Clone() - local g=nil - local sg=nil - while not sg do - if g then - fg:AddCard(g:GetFirst()) - end - if gc then - if s.Alba_System_Drugmata_Fusion_Filter(gc,fg,fc,tp,chkf) then - g=Group.FromCards(gc) - fg:RemoveCard(gc) - local mg=fg:Filter(s.matfilter,fc,tp) - Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_FMATERIAL) - sg=mg:SelectSubGroup(tp,s.Alba_System_Drugmata_Fusion_Gcheck,false,6,6,fc,tp,g:GetFirst(),chkf,gc) - else - Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_FMATERIAL) - g=fg:FilterSelect(tp,s.Alba_System_Drugmata_Fusion_Filter,1,1,nil,fg,fc,tp,chkf,gc) - fg:Sub(g) - local mg=fg:Filter(s.matfilter,fc,tp) - Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_FMATERIAL) - sg=mg:SelectSubGroup(tp,s.Alba_System_Drugmata_Fusion_Gcheck,true,6,6,fc,tp,g:GetFirst(),chkf,gc) - end - else - Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_FMATERIAL) - g=fg:FilterSelect(tp,s.Alba_System_Drugmata_Fusion_Filter,1,1,nil,fg,fc,tp,chkf,nil) - fg:Sub(g) - local mg=fg:Filter(s.matfilter,fc,tp) - aux.GCheckAdditional=aux.dncheck - Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_FMATERIAL) - sg=mg:SelectSubGroup(tp,s.Alba_System_Drugmata_Fusion_Gcheck,true,6,6,fc,tp,g:GetFirst(),chkf) - aux.GCheckAdditional=nil - end - end - g:Merge(sg) - Duel.SetFusionMaterial(g) + +function s.mfilter(c,fc,sub,mg,sg) + if not s.migfilter(c,fc) then return false end + if sg then + if #sg==0 then return false end -- must select at 2nd place, to determine which one is abs + if #sg==1 then + s.abs_list[fc]=sg:GetFirst() + return true end + return s.samecheck(c,sg-s.abs_list[fc]) + end + return true end function s.costfilter(c) return c:IsAbleToGraveAsCost() diff --git a/procedure.lua b/procedure.lua index 6eed821cb..07aa64818 100644 --- a/procedure.lua +++ b/procedure.lua @@ -874,36 +874,55 @@ end --Fusion Summon ----Fusion monster, mixed materials (fixed count) +---Fusion monster, ultimate ---@param fcard Card ---@param sub boolean Can be fusion summoned with substitute material ---@param insf boolean Can be fusion summoned with no material (Instant Fusion) ----@param ... number|function|table -function Auxiliary.AddFusionProcMix(fcard,sub,insf,...) +---@param ... table { min: number, max: number, f: function, code: number, multiple: (string|function)[] } +function Auxiliary.AddFusionProcUltimate(fcard,sub,insf,...) if fcard:IsStatus(STATUS_COPYING_EFFECT) then return end local val={...} - local fun={} local mat={} for i=1,#val do if type(val[i])=='function' then - fun[i]=function(c,fc,subm,mg,sg) return val[i](c,fc,subm,mg,sg) and not c:IsHasEffect(6205579) end - elseif type(val[i])=='table' then - fun[i]=function(c,fc,subm,mg,sg) - for _,fcode in ipairs(val[i]) do - if type(fcode)=='function' then - if fcode(c,fc,subm,mg,sg) and not c:IsHasEffect(6205579) then return true end - elseif type(fcode)=='number' then - if c:IsFusionCode(fcode) or (subm and c:CheckFusionSubstitute(fc)) then return true end - end + val[i]={ min=1, max=1, f=val[i] } + elseif type(val[i])=='number' then + local code=val[i] + val[i]={ min=1, max=1, code=code } + end + + if val[i].multiple then + local multiple_list=val[i].multiple + val[i].multiple=nil + local use_code=nil + for _,item in ipairs(multiple_list) do + if type(item)=="number" then + mat[item]=true + if not use_code then + use_code=item end - return false + end end - for _,fcode in ipairs(val[i]) do - if type(fcode)=='number' then mat[fcode]=true end + val[i].code=use_code + val[i].f=function(c,fc,subm,mg,sg) + for _,fcode in ipairs(multiple_list) do + if type(fcode)=='function' then + if fcode(c,fc,subm,mg,sg) and not c:IsHasEffect(6205579) then return true end + elseif type(fcode)=='number' then + if c:IsFusionCode(fcode) or (subm and c:CheckFusionSubstitute(fc)) then return true end + end + end + return false + end + elseif val[i].code then + local code=val[i].code + mat[code]=true + val[i].f = function(c,fc,subm) return c:IsFusionCode(code) or (subm and c:CheckFusionSubstitute(fc)) end + else + local f = val[i].f + val[i].f = function(c,fc,subm,mg,sg) + return f(c,fc,subm,mg,sg) and not c:IsHasEffect(6205579) end - elseif type(val[i])=='number' then - fun[i]=function(c,fc,subm) return c:IsFusionCode(val[i]) or (subm and c:CheckFusionSubstitute(fc)) end - mat[val[i]]=true end end local mt=getmetatable(fcard) @@ -911,7 +930,13 @@ function Auxiliary.AddFusionProcMix(fcard,sub,insf,...) mt.material=mat end if mt.material_count==nil then - mt.material_count={#fun,#fun} + local min=0 + local max=0 + for i=1,#val do + min=min+val[i].min + max=max+val[i].max + end + mt.material_count={min,max} end for index,_ in pairs(mat) do Auxiliary.AddCodeList(fcard,index) @@ -920,141 +945,180 @@ function Auxiliary.AddFusionProcMix(fcard,sub,insf,...) e1:SetType(EFFECT_TYPE_SINGLE) e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE) e1:SetCode(EFFECT_FUSION_MATERIAL) - e1:SetCondition(Auxiliary.FConditionMix(insf,sub,table.unpack(fun))) - e1:SetOperation(Auxiliary.FOperationMix(insf,sub,table.unpack(fun))) + e1:SetCondition(Auxiliary.FConditionUltimate(insf,sub,table.unpack(val))) + e1:SetOperation(Auxiliary.FOperationUltimate(insf,sub,table.unpack(val))) fcard:RegisterEffect(e1) end -function Auxiliary.FConditionMix(insf,sub,...) - --g:Material group(nil for Instant Fusion) - --gc:Material already used - --chkf: check field, default:PLAYER_NONE - --chkf&0x100: Not fusion summon, can use substitute (Hex-Sealed Fusion) - --chkf&0x200: Not fusion summon, can't use substitute ("Contact Fusion", Neos Fusion) - local funs={...} - return function(e,g,gc,chkfnf) - if g==nil then return insf and Auxiliary.MustMaterialCheck(nil,e:GetHandlerPlayer(),EFFECT_MUST_BE_FMATERIAL) end - local c=e:GetHandler() - local tp=c:GetControler() - local hexsealed=chkfnf&0x100>0 - local notfusion=chkfnf&0x200>0 - local sub2=(sub or hexsealed) and not notfusion - local mg=g:Filter(Auxiliary.FConditionFilterMix,c,c,sub2,notfusion,table.unpack(funs)) - if gc then - if not mg:IsContains(gc) then return false end - Duel.SetSelectedCard(gc) - end - return mg:CheckSubGroup(Auxiliary.FCheckMixGoal,#funs,#funs,tp,c,sub2,chkfnf,table.unpack(funs)) - end -end -function Auxiliary.FOperationMix(insf,sub,...) - local funs={...} - return function(e,tp,eg,ep,ev,re,r,rp,gc,chkfnf) - local c=e:GetHandler() - local hexsealed=chkfnf&0x100>0 - local notfusion=chkfnf&0x200>0 - local sub2=(sub or hexsealed) and not notfusion - local cancel=notfusion and Duel.GetCurrentChain()==0 - local mg=eg:Filter(Auxiliary.FConditionFilterMix,c,c,sub2,notfusion,table.unpack(funs)) - if gc then Duel.SetSelectedCard(gc) end - Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_FMATERIAL) - local sg=mg:SelectSubGroup(tp,Auxiliary.FCheckMixGoal,cancel,#funs,#funs,tp,c,sub2,chkfnf,table.unpack(funs)) - if sg then - Duel.SetFusionMaterial(sg) - else - Duel.SetFusionMaterial(Group.CreateGroup()) - end - end -end -function Auxiliary.FConditionFilterMix(c,fc,sub,notfusion,...) + +function Auxiliary.FConditionFilterUltimate(c,fc,sub,notfusion,conds) local check_type=notfusion and SUMMON_TYPE_SPECIAL or SUMMON_TYPE_FUSION if not c:IsCanBeFusionMaterial(fc,check_type) then return false end - for i,f in ipairs({...}) do - if f(c,fc,sub) then return true end + for _,o in ipairs(conds) do + if o.f(c,fc,sub) then return true end end return false end -function Auxiliary.FCheckMix(c,mg,sg,fc,sub,fun1,fun2,...) - if fun2 then - sg:AddCard(c) - local res=false - if fun1(c,fc,false,mg,sg) then - res=mg:IsExists(Auxiliary.FCheckMix,1,sg,mg,sg,fc,sub,fun2,...) - elseif sub and fun1(c,fc,true,mg,sg) then - res=mg:IsExists(Auxiliary.FCheckMix,1,sg,mg,sg,fc,false,fun2,...) + +function Auxiliary.FUltimateGoal(sg,tp,fc,sub,chkfnf,conds) + for i,o in ipairs(conds) do + if o.min>0 then + return false end - sg:RemoveCard(c) - return res - else - return fun1(c,fc,sub,mg,sg) end -end ---if sg1 is subset of sg2 then not Auxiliary.FCheckAdditional(tp,sg1,fc) -> not Auxiliary.FCheckAdditional(tp,sg2,fc) -function Auxiliary.FCheckMixGoal(sg,tp,fc,sub,chkfnf,...) + + local chkf=chkfnf&0xff local not_fusion=chkfnf&(0x100|0x200)>0 - if not not_fusion and sg:IsExists(Auxiliary.TuneMagicianCheckX,1,nil,sg,EFFECT_TUNE_MAGICIAN_F) then return false end if not Auxiliary.MustMaterialCheck(sg,tp,EFFECT_MUST_BE_FMATERIAL) then return false end local g=Group.CreateGroup() - return sg:IsExists(Auxiliary.FCheckMix,1,nil,sg,g,fc,sub,...) and (chkf==PLAYER_NONE or Duel.GetLocationCountFromEx(tp,tp,sg,fc)>0) - and (not Auxiliary.FCheckAdditional or Auxiliary.FCheckAdditional(tp,sg,fc)) + return (chkf==PLAYER_NONE or Duel.GetLocationCountFromEx(tp,tp,sg,fc)>0) and (not Auxiliary.FGoalCheckAdditional or Auxiliary.FGoalCheckAdditional(tp,sg,fc)) end ----Fusion monster, mixed material * minc to maxc + material + ... ----@param fcard Card ----@param sub boolean Can be fusion summoned with substitute material ----@param insf boolean Can be fusion summoned with no material (Instant Fusion) ----@param fun1 number|function|table ----@param minc integer ----@param maxc integer ----@param ... number|function|table -function Auxiliary.AddFusionProcMixRep(fcard,sub,insf,fun1,minc,maxc,...) - if fcard:IsStatus(STATUS_COPYING_EFFECT) then return end - local val={fun1,...} - local fun={} - local mat={} - for i=1,#val do - if type(val[i])=='function' then - fun[i]=function(c,fc,subm) return val[i](c,fc,subm) and not c:IsHasEffect(6205579) end - elseif type(val[i])=='table' then - fun[i]=function(c,fc,subm) - for _,fcode in ipairs(val[i]) do - if type(fcode)=='function' then - if fcode(c,fc,subm) and not c:IsHasEffect(6205579) then return true end - elseif type(fcode)=='number' then - if c:IsFusionCode(fcode) or (subm and c:CheckFusionSubstitute(fc)) then return true end +function Auxiliary.FUltimateGetCondsResultCode(c,conds,fc,sub,mg,sg) + -- -1 means crcode is invalid + if c:IsLocation(LOCATION_MZONE) or Auxiliary.FGoalCheckAdditional then return -1 end + + local code=0 + if sub and c:CheckFusionSubstitute(fc) then + code=code|0x1 + end + for i,o in ipairs(conds) do + if o.max>0 and o.f(c,fc,sub,mg,sg) then + code=code|(1<0 + if not not_fusion and Auxiliary.TuneMagicianCheckX(c,sg,EFFECT_TUNE_MAGICIAN_F) then return false end + + sg:AddCard(c) + + if Auxiliary.FCheckAdditional and not Auxiliary.FCheckAdditional(tp,sg,fc) + or chkf~=PLAYER_NONE and Duel.GetLocationCountFromEx(tp,tp,sg,fc)<=0 and not c:IsLocation(LOCATION_MZONE) then + sg:RemoveCard(c) + return false + end + + conds[i].min=conds[i].min-1 + conds[i].max=conds[i].max-1 + local res=Auxiliary.FUltimateGoal(sg,tp,fc,sub,chkfnf,conds) + or mg:IsExists(Auxiliary.CreateFUltimateCheck(mg,sg,tp,fc,sub,chkfnf,conds),1,sg) + conds[i].min=conds[i].min+1 + conds[i].max=conds[i].max+1 + + sg:RemoveCard(c) + return res +end + +function Auxiliary.FUltimateCheck(c,mg,sg,tp,fc,sub,chkfnf,conds) + -- we consider unfulfilled conditions first + local unfulfilled_conds={} + local fulfilled_conds={} + + for i,o in ipairs(conds) do + if o.min>0 then + table.insert(unfulfilled_conds, {cond=o, i=i}) + else + table.insert(fulfilled_conds, {cond=o, i=i}) + end + end + + local sorted_conds={} + for _,o in ipairs(unfulfilled_conds) do + table.insert(sorted_conds, o) + end + for _,o in ipairs(fulfilled_conds) do + table.insert(sorted_conds, o) + end + + for _,item in ipairs(sorted_conds) do + local o=item.cond + local i=item.i + if o.max>0 then + if o.f(c,fc,false,mg,sg) and Auxiliary.FUltimateNext(c,i,mg,sg,tp,fc,sub,chkfnf,conds) then + return true + elseif sub and o.code and o.f(c,fc,true,mg,sg) and Auxiliary.FUltimateNext(c,i,mg,sg,tp,fc,false,chkfnf,conds) then + return true + end + end + end + + return false +end + +function Auxiliary.CreateFUltimateCheck(mg,sg,tp,fc,sub,chkfnf,conds) + local crcode_cache={} + return function(c) + local crcode=Auxiliary.FUltimateGetCondsResultCode(c,conds,fc,sub,mg,sg) + local cached=crcode_cache[crcode] + if cached then return cached==1 end + local res=Auxiliary.FUltimateCheck(c,mg,sg,tp,fc,sub,chkfnf,conds) + if crcode~=-1 then + crcode_cache[crcode]=res and 1 or 0 + end + return res + end +end + +function Auxiliary.FUltimateGetNextRoutes(c,mg,sg,tp,fc,chkfnf,routes) + local next_routes={} + + for _,route in ipairs(routes) do + local conds=route.conds + local sub=route.sub + for i,o in ipairs(conds) do + if o.max>0 then + local new_route={ sub=sub, conds={} } + + for j,oo in ipairs(conds) do + if j==i then + table.insert(new_route.conds, { min=oo.min-1, max=oo.max-1, f=oo.f, code=oo.code }) + else + table.insert(new_route.conds, oo) + end + end + + local function check_duplicate(sub) + for _,r in ipairs(next_routes) do + if r.sub==sub then + local same=true + for j,oo in ipairs(r.conds) do + local cond=new_route.conds[j] + if oo.min~=cond.min or oo.max~=cond.max then + same=false + break + end + end + if same then return true end end end return false + end + + if o.f(c,fc,false,mg,sg) and not check_duplicate(sub) and Auxiliary.FUltimateNext(c,i,mg,sg,tp,fc,sub,chkfnf,conds) then + table.insert(next_routes, new_route) + elseif sub and o.code and o.f(c,fc,true,mg,sg) and not check_duplicate(false) and Auxiliary.FUltimateNext(c,i,mg,sg,tp,fc,false,chkfnf,conds) then + new_route.sub=false + table.insert(next_routes, new_route) + end end - for _,fcode in ipairs(val[i]) do - if type(fcode)=='number' then mat[fcode]=true end - end - elseif type(val[i])=='number' then - fun[i]=function(c,fc,subm) return c:IsFusionCode(val[i]) or (subm and c:CheckFusionSubstitute(fc)) end - mat[val[i]]=true end end - local mt=getmetatable(fcard) - if mt.material==nil then - mt.material=mat - end - if mt.material_count==nil then - mt.material_count={#fun+minc-1,#fun+maxc-1} - end - for index,_ in pairs(mat) do - Auxiliary.AddCodeList(fcard,index) - end - local e1=Effect.CreateEffect(fcard) - e1:SetType(EFFECT_TYPE_SINGLE) - e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE) - e1:SetCode(EFFECT_FUSION_MATERIAL) - e1:SetCondition(Auxiliary.FConditionMixRep(insf,sub,fun[1],minc,maxc,table.unpack(fun,2))) - e1:SetOperation(Auxiliary.FOperationMixRep(insf,sub,fun[1],minc,maxc,table.unpack(fun,2))) - fcard:RegisterEffect(e1) + + return next_routes end -function Auxiliary.FConditionMixRep(insf,sub,fun1,minc,maxc,...) - local funs={...} + +function Auxiliary.FConditionUltimate(insf,sub,...) + --g:Material group(nil for Instant Fusion) + --gc:Material already used + --chkf: check field, default:PLAYER_NONE + --chkf&0x100: Not fusion summon, can use substitute (Hex-Sealed Fusion) + --chkf&0x200: Not fusion summon, can't use substitute ("Contact Fusion", Neos Fusion) + local conds={...} return function(e,g,gc,chkfnf) if g==nil then return insf and Auxiliary.MustMaterialCheck(nil,e:GetHandlerPlayer(),EFFECT_MUST_BE_FMATERIAL) end local c=e:GetHandler() @@ -1062,162 +1126,184 @@ function Auxiliary.FConditionMixRep(insf,sub,fun1,minc,maxc,...) local hexsealed=chkfnf&0x100>0 local notfusion=chkfnf&0x200>0 local sub2=(sub or hexsealed) and not notfusion - local mg=g:Filter(Auxiliary.FConditionFilterMix,c,c,sub2,notfusion,fun1,table.unpack(funs)) + local mg=g:Filter(Auxiliary.FConditionFilterUltimate,c,c,sub2,notfusion,conds) + for _,cond in ipairs(conds) do + if not mg:IsExists(cond.f,cond.min,nil,c,sub) then return false end + end + local checkf=Auxiliary.CreateFUltimateCheck(mg,Group.CreateGroup(),tp,c,sub2,chkfnf,conds) if gc then if not mg:IsContains(gc) then return false end - local sg=Group.CreateGroup() - return Auxiliary.FSelectMixRep(gc,tp,mg,sg,c,sub2,chkfnf,fun1,minc,maxc,table.unpack(funs)) + return checkf(gc) end - local sg=Group.CreateGroup() - return mg:IsExists(Auxiliary.FSelectMixRep,1,nil,tp,mg,sg,c,sub2,chkfnf,fun1,minc,maxc,table.unpack(funs)) + return mg:IsExists(checkf,1,nil) end end -function Auxiliary.FOperationMixRep(insf,sub,fun1,minc,maxc,...) - local funs={...} + +function Auxiliary.FOperationUltimate(insf,sub,...) + local conds={...} return function(e,tp,eg,ep,ev,re,r,rp,gc,chkfnf) local c=e:GetHandler() - local tp=c:GetControler() local hexsealed=chkfnf&0x100>0 local notfusion=chkfnf&0x200>0 local sub2=(sub or hexsealed) and not notfusion local cancel=notfusion and Duel.GetCurrentChain()==0 - local mg=eg:Filter(Auxiliary.FConditionFilterMix,c,c,sub2,notfusion,fun1,table.unpack(funs)) + local mg=eg:Filter(Auxiliary.FConditionFilterUltimate,c,c,sub2,notfusion,conds) local sg=Group.CreateGroup() if gc then sg:AddCard(gc) end - while sg:GetCount()0 - if not not_fusion and sg:IsExists(Auxiliary.TuneMagicianCheckX,1,nil,sg,EFFECT_TUNE_MAGICIAN_F) then return false end - if not Auxiliary.MustMaterialCheck(sg,tp,EFFECT_MUST_BE_FMATERIAL) then return false end - if Auxiliary.FGoalCheckAdditional and not Auxiliary.FGoalCheckAdditional(tp,sg,fc) then return false end - return true -end -function Auxiliary.FCheckMixRepGoal(tp,sg,fc,sub,chkfnf,fun1,minc,maxc,...) - local chkf=chkfnf&0xff - if sg:GetCount()maxc+#{...} then return false end - if not (chkf==PLAYER_NONE or Duel.GetLocationCountFromEx(tp,tp,sg,fc)>0) then return false end - if Auxiliary.FCheckAdditional and not Auxiliary.FCheckAdditional(tp,sg,fc) then return false end - if not Auxiliary.FCheckMixRepGoalCheck(tp,sg,fc,chkfnf) then return false end - local g=Group.CreateGroup() - return Auxiliary.FCheckMixRep(sg,g,fc,sub,chkf,fun1,minc,maxc,...) -end -function Auxiliary.FCheckMixRepTemplate(c,cond,tp,mg,sg,g,fc,sub,chkfnf,fun1,minc,maxc,...) - for i,f in ipairs({...}) do - if f(c,fc,sub) then - g:AddCard(c) - local subf=sub and f(c,fc,false) - local t={...} - table.remove(t,i) - local res=cond(tp,mg,sg,g,fc,subf,chkfnf,fun1,minc,maxc,table.unpack(t)) - g:RemoveCard(c) - if res then return true end - end - end - if maxc>0 then - if fun1(c,fc,sub) then - g:AddCard(c) - local subf1=sub and fun1(c,fc,false) - local res=cond(tp,mg,sg,g,fc,subf1,chkfnf,fun1,minc-1,maxc-1,...) - g:RemoveCard(c) - if res then return true end + +---Fusion monster, mixed materials (fixed count) +---@param fcard Card +---@param sub boolean Can be fusion summoned with substitute material +---@param insf boolean Can be fusion summoned with no material (Instant Fusion) +---@param ... number|function|table +function Auxiliary.AddFusionProcMix(fcard,sub,insf,...) + if fcard:IsStatus(STATUS_COPYING_EFFECT) then return end + local val={...} + local conds={} + for i=1,#val do + if type(val[i])=='table' then + conds[i]={ + min=1, + max=1, + miltiple=val[i] + } + else + conds[i]=val[i] end end - return false -end -function Auxiliary.FCheckMixRepSelectedCond(tp,mg,sg,g,...) - if g:GetCount()0 then - if minc<=0 and #{...}==0 and Auxiliary.FCheckMixRepGoalCheck(tp,g,fc,chkfnf) then return true end - return mg:IsExists(Auxiliary.FCheckSelectMixRepAll,1,g,tp,mg,sg,g,fc,sub,chkfnf,fun1,minc,maxc,...) - else - return mg:IsExists(Auxiliary.FCheckSelectMixRepM,1,g,tp,mg,sg,g,fc,sub,chkfnf,fun1,minc,maxc,...) - end -end -function Auxiliary.FCheckSelectMixRepAll(c,tp,mg,sg,g,fc,sub,chkf,fun1,minc,maxc,fun2,...) - if fun2 then - if fun2(c,fc,sub) then - g:AddCard(c) - local subf2=sub and fun2(c,fc,false) - local res=Auxiliary.FCheckSelectMixRep(tp,mg,sg,g,fc,subf2,chkf,fun1,minc,maxc,...) - g:RemoveCard(c) - return res + + +---Fusion monster, mixed material * minc to maxc + material + ... +---@param fcard Card +---@param sub boolean Can be fusion summoned with substitute material +---@param insf boolean Can be fusion summoned with no material (Instant Fusion) +---@param fun1 number|function|table +---@param minc integer +---@param maxc integer +---@param ... number|function|table +function Auxiliary.AddFusionProcMixRep(fcard,sub,insf,fun1,minc,maxc,...) + if fcard:IsStatus(STATUS_COPYING_EFFECT) then return end + local val={fun1,...} + local conds={} + for i=1,#val do + if type(val[i])=='table' then + conds[i]={ + min=1, + max=1, + miltiple=val[i] + } + elseif type(val[i])=='function' then + conds[i]={ + min=1, + max=1, + f=val[i] + } + elseif type(val[i])=='number' then + conds[i]={ + min=1, + max=1, + code=val[i] + } end - elseif maxc>0 and fun1(c,fc,sub) then - g:AddCard(c) - local subf1=sub and fun1(c,fc,false) - local res=Auxiliary.FCheckSelectMixRep(tp,mg,sg,g,fc,subf1,chkf,fun1,minc-1,maxc-1) - g:RemoveCard(c) - return res end - return false -end -function Auxiliary.FCheckSelectMixRepM(c,tp,...) - return c:IsControler(tp) and c:IsLocation(LOCATION_MZONE) - and Auxiliary.FCheckMixRepTemplate(c,Auxiliary.FCheckSelectMixRep,tp,...) -end -function Auxiliary.FSelectMixRep(c,tp,mg,sg,fc,sub,chkfnf,...) - sg:AddCard(c) - local res=false - if Auxiliary.FCheckAdditional and not Auxiliary.FCheckAdditional(tp,sg,fc) then - res=false - elseif Auxiliary.FCheckMixRepGoal(tp,sg,fc,sub,chkfnf,...) then - res=true - else - local g=Group.CreateGroup() - res=sg:IsExists(Auxiliary.FCheckMixRepSelected,1,nil,tp,mg,sg,g,fc,sub,chkfnf,...) - end - sg:RemoveCard(c) - return res + conds[1].min=minc + conds[1].max=maxc + Auxiliary.AddFusionProcUltimate(fcard,sub,insf,table.unpack(conds)) end ---Fusion monster, name + name @@ -1257,11 +1343,11 @@ end ---@param sub boolean ---@param insf boolean function Auxiliary.AddFusionProcCodeRep(c,code1,cc,sub,insf) - local code={} - for i=1,cc do - code[i]=code1 - end - Auxiliary.AddFusionProcMix(c,sub,insf,table.unpack(code)) + Auxiliary.AddFusionProcUltimate(c,sub,insf,{ + min=cc, + max=cc, + code=code1 + }) end ---Fusion monster, name * minc to maxc ---@param c Card @@ -1281,11 +1367,11 @@ end ---@param sub boolean ---@param insf boolean function Auxiliary.AddFusionProcCodeFun(c,code1,f,cc,sub,insf) - local fun={} - for i=1,cc do - fun[i]=f - end - Auxiliary.AddFusionProcMix(c,sub,insf,code1,table.unpack(fun)) + Auxiliary.AddFusionProcUltimate(c,sub,insf,code1,{ + min=cc, + max=cc, + f=f + }) end ---Fusion monster, condition + condition ---@param c Card