Commit fcb2357a authored by root's avatar root

Refresh on 2025-06-02 18:03:15

parent 62c7721e
...@@ -88,7 +88,7 @@ function s.splimit(e,se,sp,st) ...@@ -88,7 +88,7 @@ function s.splimit(e,se,sp,st)
if c:IsLocation(LOCATION_EXTRA) and c:IsFacedown() then if c:IsLocation(LOCATION_EXTRA) and c:IsFacedown() then
return st&SUMMON_TYPE_FUSION==SUMMON_TYPE_FUSION and Duel.GetFlagEffect(sp,id)==0 return st&SUMMON_TYPE_FUSION==SUMMON_TYPE_FUSION and Duel.GetFlagEffect(sp,id)==0
end end
return true return false
end end
function s.desfilter(c) function s.desfilter(c)
return c:IsFaceup() and c:IsSetCard(0xae) return c:IsFaceup() and c:IsSetCard(0xae)
......
...@@ -5,7 +5,7 @@ function s.initial_effect(c) ...@@ -5,7 +5,7 @@ function s.initial_effect(c)
c:EnableReviveLimit() c:EnableReviveLimit()
aux.AddLinkProcedure(c,aux.FilterBoolFunction(Card.IsLinkType,TYPE_EFFECT),2) aux.AddLinkProcedure(c,aux.FilterBoolFunction(Card.IsLinkType,TYPE_EFFECT),2)
--fusion --fusion
local e1=FusionSpell.CreateSummonEffect(c,nil,nil,LOCATION_ONFIELD) local e1=FusionSpell.CreateSummonEffect(c,{pre_select_mat_location=LOCATION_ONFIELD})
e1:SetDescription(aux.Stringid(id,0)) e1:SetDescription(aux.Stringid(id,0))
e1:SetType(EFFECT_TYPE_IGNITION) e1:SetType(EFFECT_TYPE_IGNITION)
e1:SetRange(LOCATION_MZONE) e1:SetRange(LOCATION_MZONE)
......
...@@ -2,7 +2,10 @@ ...@@ -2,7 +2,10 @@
local s,id,o=GetID() local s,id,o=GetID()
function s.initial_effect(c) function s.initial_effect(c)
--Activate --Activate
FusionSpell.RegisterSummonEffect(c,s.fusfilter,nil,nil,nil,nil,nil,nil,nil,nil,nil,s.stage_x_operation) FusionSpell.RegisterSummonEffect(c,{
fusfilter=s.fusfilter,
stage_x_operation=s.stage_x_operation
})
end end
---@param c Card ---@param c Card
...@@ -41,4 +44,4 @@ function s.stage_x_operation(e,tc,tp,stage,mg_fuison_spell,mg_all) ...@@ -41,4 +44,4 @@ function s.stage_x_operation(e,tc,tp,stage,mg_fuison_spell,mg_all)
end end
function s.damop(e,tp,eg,ep,ev,re,r,rp) function s.damop(e,tp,eg,ep,ev,re,r,rp)
Duel.Damage(tp,e:GetLabel(),REASON_EFFECT) Duel.Damage(tp,e:GetLabel(),REASON_EFFECT)
end end
\ No newline at end of file
--チェーン・マテリアル
local s,id,o=GetID()
function s.initial_effect(c)
--Activate
local e1=Effect.CreateEffect(c)
e1:SetType(EFFECT_TYPE_ACTIVATE)
e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET)
e1:SetCode(EVENT_FREE_CHAIN)
e1:SetCost(s.cost)
e1:SetTarget(s.target)
e1:SetOperation(s.activate)
c:RegisterEffect(e1)
end
function s.cost(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then return Duel.GetActivityCount(tp,ACTIVITY_ATTACK)==0 end
local e1=Effect.CreateEffect(e:GetHandler())
e1:SetType(EFFECT_TYPE_FIELD)
e1:SetCode(EFFECT_CANNOT_ATTACK)
e1:SetProperty(EFFECT_FLAG_OATH+EFFECT_FLAG_IGNORE_IMMUNE)
e1:SetTargetRange(LOCATION_MZONE,0)
e1:SetReset(RESET_PHASE+PHASE_END)
Duel.RegisterEffect(e1,tp)
end
function s.target(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then return e:IsHasType(EFFECT_TYPE_ACTIVATE) end
end
function s.activate(e,tp,eg,ep,ev,re,r,rp)
local e1=Effect.CreateEffect(e:GetHandler())
e1:SetDescription(aux.Stringid(id,0))
e1:SetType(EFFECT_TYPE_FIELD)
e1:SetCode(EFFECT_CHAIN_MATERIAL)
e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET)
e1:SetTargetRange(1,0)
e1:SetReset(RESET_PHASE+PHASE_END)
e1:SetTarget(s.chain_target)
e1:SetOperation(s.chain_operation)
e1:SetValue(aux.TRUE)
Duel.RegisterEffect(e1,tp)
end
function s.filter(c,e)
return c:IsType(TYPE_MONSTER) and c:IsCanBeFusionMaterial() and c:IsAbleToRemove() and not c:IsImmuneToEffect(e)
end
function s.chain_target(e,te,tp)
return Duel.GetMatchingGroup(s.filter,tp,LOCATION_ONFIELD+LOCATION_GRAVE+LOCATION_HAND+LOCATION_DECK,0,nil,te)
end
function s.chain_operation(e,te,tp,tc,mat,sumtype,sumpos)
if not sumtype then sumtype=SUMMON_TYPE_FUSION end
tc:SetMaterial(mat)
Duel.Remove(mat,POS_FACEUP,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION)
Duel.BreakEffect()
Duel.SpecialSummonStep(tc,sumtype,tp,tp,false,false,sumpos)
tc:RegisterFlagEffect(id,RESET_EVENT+RESETS_STANDARD-RESET_TURN_SET,0,1)
local e1=Effect.CreateEffect(e:GetHandler())
e1:SetType(EFFECT_TYPE_FIELD+EFFECT_TYPE_CONTINUOUS)
e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
e1:SetCode(EVENT_PHASE+PHASE_END)
e1:SetLabelObject(tc)
e1:SetCondition(s.descon)
e1:SetOperation(s.desop)
e1:SetCountLimit(1)
Duel.RegisterEffect(e1,tp)
end
function s.descon(e,tp,eg,ep,ev,re,r,rp)
local tc=e:GetLabelObject()
if tc:GetFlagEffect(id)~=0 then
return true
else
e:Reset()
return false
end
end
function s.desop(e,tp,eg,ep,ev,re,r,rp)
local tc=e:GetLabelObject()
Duel.Destroy(tc,REASON_EFFECT)
end
\ No newline at end of file
--超融合
local s,id,o=GetID()
function s.initial_effect(c)
--Activate
local e1=FusionSpell.CreateSummonEffect(c,{
pre_select_mat_location=LOCATION_ONFIELD,
pre_select_mat_opponent_location=LOCATION_ONFIELD,
extra_target=s.extra_target
})
e1:SetHintTiming(0,TIMINGS_CHECK_MONSTER+TIMING_END_PHASE)
e1:SetCost(s.cost)
c:RegisterEffect(e1)
end
function s.cost(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then return Duel.IsExistingMatchingCard(Card.IsDiscardable,tp,LOCATION_HAND,0,1,e:GetHandler()) end
Duel.DiscardHand(tp,Card.IsDiscardable,1,1,REASON_COST+REASON_DISCARD)
end
function s.extra_target(e,tp,eg,ep,ev,re,r,rp,chk)
if e:IsHasType(EFFECT_TYPE_ACTIVATE) then
Duel.SetChainLimit(aux.FALSE)
end
end
--サイバネティック・フュージョン・サポート
local s,id,o=GetID()
function s.initial_effect(c)
--Activate
local e1=Effect.CreateEffect(c)
e1:SetType(EFFECT_TYPE_ACTIVATE)
e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET)
e1:SetCode(EVENT_FREE_CHAIN)
e1:SetCountLimit(1,id+EFFECT_COUNT_CODE_OATH)
e1:SetCost(s.cost)
e1:SetOperation(s.activate)
c:RegisterEffect(e1)
end
function s.cost(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then return true end
Duel.PayLPCost(tp,math.floor(Duel.GetLP(tp)/2))
end
function s.activate(e,tp,eg,ep,ev,re,r,rp)
local e1=Effect.CreateEffect(e:GetHandler())
e1:SetDescription(aux.Stringid(id,0))
e1:SetType(EFFECT_TYPE_FIELD)
e1:SetCode(EFFECT_CHAIN_MATERIAL)
e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET)
e1:SetTargetRange(1,0)
e1:SetReset(RESET_PHASE+PHASE_END)
e1:SetCountLimit(1)
e1:SetTarget(s.chain_target)
e1:SetOperation(s.chain_operation)
e1:SetValue(aux.FilterBoolFunction(Card.IsRace,RACE_MACHINE))
Duel.RegisterEffect(e1,tp)
end
function s.filter(c,e)
return c:IsType(TYPE_MONSTER) and c:IsCanBeFusionMaterial() and c:IsAbleToRemove() and not c:IsImmuneToEffect(e)
end
function s.chain_target(e,te,tp)
return Duel.GetMatchingGroup(s.filter,tp,LOCATION_MZONE+LOCATION_GRAVE+LOCATION_HAND,0,nil,te)
end
function s.chain_operation(e,te,tp,tc,mat,sumtype,sumpos)
if not sumtype then sumtype=SUMMON_TYPE_FUSION end
tc:SetMaterial(mat)
Duel.Remove(mat,POS_FACEUP,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION)
Duel.BreakEffect()
Duel.SpecialSummonStep(tc,sumtype,tp,tp,false,false,sumpos)
end
\ No newline at end of file
--多層融合
local s,id,o=GetID()
function s.initial_effect(c)
--Activate
local e1=Effect.CreateEffect(c)
e1:SetDescription(aux.Stringid(id,0))
e1:SetCategory(CATEGORY_SPECIAL_SUMMON+CATEGORY_FUSION_SUMMON)
e1:SetType(EFFECT_TYPE_ACTIVATE)
e1:SetCode(EVENT_FREE_CHAIN)
e1:SetTarget(s.target)
e1:SetOperation(s.activate)
c:RegisterEffect(e1)
end
s.fusion_effect=true
function s.fcheck1(ct)
return function(tp,sg,fc)
if ct>0 and sg:FilterCount(Card.IsLocation,nil,LOCATION_EXTRA)>ct then
return false
end
return true
end
end
function s.fcheck2(tp,sg,fc)
return sg:GetCount()>=3
end
function s.filter0(c)
return c:IsType(TYPE_MONSTER) and c:IsCanBeFusionMaterial() and c:IsAbleToRemove()
end
function s.filter2(c,e,tp,m,f,chkf)
return c:IsType(TYPE_FUSION) and (not f or f(c))
and c:IsCanBeSpecialSummoned(e,SUMMON_TYPE_FUSION,tp,false,false) and c:CheckFusionMaterial(m,nil,chkf)
end
function s.target(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then
local chkf=tp
local mg=Duel.GetFusionMaterial(tp):Filter(aux.NOT(Card.IsImmuneToEffect),nil,e)
local ct=Duel.GetFieldGroupCount(tp,0,LOCATION_MZONE)
if ct>0 then
local mg2=Duel.GetMatchingGroup(s.filter0,tp,LOCATION_EXTRA,0,nil)
if mg2:GetCount()>0 then
mg:Merge(mg2)
end
end
aux.FCheckAdditional=s.fcheck1(ct)
aux.FGoalCheckAdditional=s.fcheck2
local res=Duel.IsExistingMatchingCard(s.filter2,tp,LOCATION_EXTRA,0,1,nil,e,tp,mg,nil,chkf)
aux.FCheckAdditional=nil
aux.FGoalCheckAdditional=nil
if not res then
local ce=Duel.GetChainMaterial(tp)
if ce~=nil then
local fgroup=ce:GetTarget()
local mg3=fgroup(ce,e,tp)
local mf=ce:GetValue()
res=Duel.IsExistingMatchingCard(s.filter2,tp,LOCATION_EXTRA,0,1,nil,e,tp,mg3,mf,chkf)
end
end
return res
end
end
function s.activate(e,tp,eg,ep,ev,re,r,rp)
local chkf=tp
local mg1=Duel.GetFusionMaterial(tp):Filter(aux.NOT(Card.IsImmuneToEffect),nil,e)
local ct=Duel.GetFieldGroupCount(tp,0,LOCATION_MZONE)
if ct>0 then
local mg2=Duel.GetMatchingGroup(s.filter0,tp,LOCATION_EXTRA,0,nil)
if mg2:GetCount()>0 then
mg1:Merge(mg2)
end
end
aux.FCheckAdditional=s.fcheck1(ct)
aux.FGoalCheckAdditional=s.fcheck2
local sg1=Duel.GetMatchingGroup(s.filter2,tp,LOCATION_EXTRA,0,nil,e,tp,mg1,nil,chkf)
local mg2=nil
local sg2=nil
local ce=Duel.GetChainMaterial(tp)
if ce~=nil then
local fgroup=ce:GetTarget()
mg2=fgroup(ce,e,tp)
local mf=ce:GetValue()
sg2=Duel.GetMatchingGroup(s.filter2,tp,LOCATION_EXTRA,0,nil,e,tp,mg2,mf,chkf)
end
local sg=sg1:Clone()
if sg2 then sg:Merge(sg2) end
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON)
local tg=sg:Select(tp,1,1,nil)
local tc=tg:GetFirst()
if tc then
if sg1:IsContains(tc) and (sg2==nil or not sg2:IsContains(tc) or ce and not Duel.SelectYesNo(tp,ce:GetDescription())) then
aux.FCheckAdditional=s.fcheck1(ct)
aux.FGoalCheckAdditional=s.fcheck2
local mat1=Duel.SelectFusionMaterial(tp,tc,mg1,nil,chkf)
aux.FCheckAdditional=nil
aux.FGoalCheckAdditional=nil
tc:SetMaterial(mat1)
local rg=mat1:Filter(Card.IsLocation,nil,LOCATION_EXTRA)
mat1:Sub(rg)
Duel.SendtoGrave(mat1,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION)
Duel.Remove(rg,POS_FACEUP,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION)
Duel.BreakEffect()
Duel.SpecialSummonStep(tc,SUMMON_TYPE_FUSION,tp,tp,false,false,POS_FACEUP)
elseif ce then
local mat2=Duel.SelectFusionMaterial(tp,tc,mg2,nil,chkf)
local fop=ce:GetOperation()
fop(ce,e,tp,tc,mat2)
end
local exmat=tc:GetMaterial():Filter(Card.IsPreviousLocation,nil,LOCATION_EXTRA)
if #exmat>0 then
local dam=exmat:GetSum(Card.GetAttack)
local lp=Duel.GetLP(tp)
if lp>=dam then
Duel.SetLP(tp,lp-dam)
else
Duel.SetLP(tp,0)
end
end
Duel.SpecialSummonComplete()
tc:CompleteProcedure()
end
aux.FCheckAdditional=nil
aux.FGoalCheckAdditional=nil
end
--Recettes de Nouvellez~ヌーベルズのレシピ帳~
local s,id,o=GetID()
function s.initial_effect(c)
--Activate
local e1=Effect.CreateEffect(c)
e1:SetType(EFFECT_TYPE_ACTIVATE)
e1:SetCode(EVENT_FREE_CHAIN)
e1:SetCountLimit(1,id+EFFECT_COUNT_CODE_OATH)
c:RegisterEffect(e1)
--Pos Change
local e2=Effect.CreateEffect(c)
e2:SetType(EFFECT_TYPE_FIELD)
e2:SetCode(EFFECT_SET_POSITION)
e2:SetRange(LOCATION_SZONE)
e2:SetCondition(s.poscon)
e2:SetTarget(s.target)
e2:SetTargetRange(0,LOCATION_MZONE)
e2:SetValue(POS_FACEUP_ATTACK)
c:RegisterEffect(e2)
--lp
local e3=Effect.CreateEffect(c)
e3:SetType(EFFECT_TYPE_FIELD+EFFECT_TYPE_CONTINUOUS)
e3:SetCode(EVENT_RELEASE)
e3:SetProperty(EFFECT_FLAG_DELAY)
e3:SetRange(LOCATION_SZONE)
e3:SetCondition(s.lpcon)
e3:SetOperation(s.lpop)
c:RegisterEffect(e3)
--search
local custom_code=aux.RegisterMergedDelayedEvent_ToSingleCard(c,id,EVENT_SPSUMMON_SUCCESS)
local e4=Effect.CreateEffect(c)
e4:SetDescription(aux.Stringid(id,2))
e4:SetCategory(CATEGORY_TOHAND+CATEGORY_SEARCH)
e4:SetType(EFFECT_TYPE_FIELD+EFFECT_TYPE_TRIGGER_O)
e4:SetCode(custom_code)
e4:SetRange(LOCATION_SZONE)
e4:SetProperty(EFFECT_FLAG_CARD_TARGET+EFFECT_FLAG_DELAY)
e4:SetCountLimit(1)
e4:SetCondition(s.thcon)
e4:SetTarget(s.thtg)
e4:SetOperation(s.thop)
c:RegisterEffect(e4)
end
function s.cfilter(c)
return c:IsFaceup() and c:IsSetCard(0x196) and c:GetOriginalType()&TYPE_MONSTER==TYPE_MONSTER
end
function s.poscon(e)
return Duel.IsExistingMatchingCard(s.cfilter,e:GetHandlerPlayer(),LOCATION_ONFIELD,0,1,nil)
end
function s.target(e,c)
return c:IsFaceup()
end
function s.cfilter2(c)
return c:IsType(TYPE_MONSTER) and c:IsReason(REASON_EFFECT)
end
function s.lpcon(e,tp,eg,ep,ev,re,r,rp)
return re and re:GetHandler():IsAllTypes(TYPE_RITUAL+TYPE_MONSTER)
and eg:IsExists(s.cfilter2,1,nil)
end
function s.lpop(e,tp,eg,ep,ev,re,r,rp)
if Duel.GetLP(1-tp)>=850 then
Duel.Hint(HINT_CARD,0,id)
Duel.PayLPCost(1-tp,850)
end
end
function s.cfilter3(c,tp,e)
return c:IsLocation(LOCATION_MZONE) and c:IsSummonPlayer(tp) and c:IsFaceup()
and c:IsCanBeEffectTarget(e) and c:IsType(TYPE_RITUAL) and c:IsLevelAbove(1)
end
function s.thcon(e,tp,eg,ep,ev,re,r,rp)
return eg:IsExists(s.cfilter3,1,nil,tp,e)
end
function s.thfilter(c)
return c:IsSetCard(0x196,0x197) and not c:IsAllTypes(TYPE_CONTINUOUS+TYPE_SPELL) and c:IsAbleToHand()
end
function s.thtg(e,tp,eg,ep,ev,re,r,rp,chk,chkc)
local g=eg:Filter(s.cfilter3,nil,tp,e)
if chkc then return g:IsContains(chkc) end
if chk==0 then return #g>0 and Duel.IsExistingMatchingCard(s.thfilter,tp,LOCATION_DECK,0,1,nil) end
local sg
if g:GetCount()==1 then
sg=g:Clone()
Duel.SetTargetCard(sg)
else
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_TARGET)
sg=Duel.SelectTarget(tp,aux.IsInGroup,tp,LOCATION_MZONE,0,1,1,nil,g)
end
Duel.SetOperationInfo(0,CATEGORY_TOHAND,nil,1,tp,LOCATION_DECK)
end
function s.thop(e,tp,eg,ep,ev,re,r,rp)
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_ATOHAND)
local g=Duel.SelectMatchingCard(tp,s.thfilter,tp,LOCATION_DECK,0,1,1,nil)
if g:GetCount()>0 then
Duel.SendtoHand(g,nil,REASON_EFFECT)
Duel.ConfirmCards(1-tp,g)
local tc=Duel.GetFirstTarget()
if tc:IsFaceup() and tc:IsRelateToChain() and tc:IsType(TYPE_MONSTER) then
local e1=Effect.CreateEffect(e:GetHandler())
e1:SetType(EFFECT_TYPE_SINGLE)
e1:SetCode(EFFECT_UPDATE_LEVEL)
e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE)
e1:SetValue(1)
e1:SetReset(RESET_EVENT+RESETS_STANDARD)
tc:RegisterEffect(e1)
end
end
end
...@@ -2,7 +2,12 @@ ...@@ -2,7 +2,12 @@
local s,id=GetID() local s,id=GetID()
function s.initial_effect(c) function s.initial_effect(c)
--Activate --Activate
local e1=FusionSpell.CreateSummonEffect(c,s.fusfilter,nil,s.pre_select_mat_location,nil,nil,nil,s.fcheck,s.gcheck) local e1=FusionSpell.CreateSummonEffect(c,{
fusfilter=s.fusfilter,
pre_select_mat_location=s.pre_select_mat_location,
additional_fcheck=s.fcheck,
additional_gcheck=s.gcheck
})
e1:SetCategory(CATEGORY_SPECIAL_SUMMON+CATEGORY_FUSION_SUMMON+CATEGORY_DECKDES) e1:SetCategory(CATEGORY_SPECIAL_SUMMON+CATEGORY_FUSION_SUMMON+CATEGORY_DECKDES)
e1:SetCountLimit(1,id+EFFECT_COUNT_CODE_OATH) e1:SetCountLimit(1,id+EFFECT_COUNT_CODE_OATH)
c:RegisterEffect(e1) c:RegisterEffect(e1)
...@@ -13,7 +18,7 @@ function s.fusfilter(c) ...@@ -13,7 +18,7 @@ function s.fusfilter(c)
return c:IsSetCard(0xdf) return c:IsSetCard(0xdf)
end end
---@type FUSION_SPELL_PRE_SELECT_MAT_LOCATION_FUNCTION ---@type FUSION_SPELL_PRE_SELECT_MAT_LOCATION_FUNCTION
function s.pre_select_mat_location(tc,tp) function s.pre_select_mat_location(tc,tp)
local res=LOCATION_HAND|LOCATION_ONFIELD local res=LOCATION_HAND|LOCATION_ONFIELD
if Duel.IsExistingMatchingCard(s.cfilter,tp,0,LOCATION_MZONE,1,nil) then if Duel.IsExistingMatchingCard(s.cfilter,tp,0,LOCATION_MZONE,1,nil) then
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -1982,449 +1982,3 @@ function Auxiliary.MonsterEffectPropertyFilter(flag) ...@@ -1982,449 +1982,3 @@ function Auxiliary.MonsterEffectPropertyFilter(flag)
return e:IsHasProperty(flag) and not e:IsHasRange(LOCATION_PZONE) return e:IsHasProperty(flag) and not e:IsHasRange(LOCATION_PZONE)
end end
end end
FusionSpell = {}
---@alias FUSION_SPELL_PRE_SELECT_MAT_LOCATION_FUNCTION fun(tc:Card,tp:integer):integer
---@alias FUSION_FCHECK_FUNCTION fun(tp:integer,mg:Group,fc:Card,all_mg:Group):boolean
--- Add LOCATION_EXTRA to EFFECT_EXTRA_FUSION_MATERIAL list, remove once core updated
function FusionSpell.GetFusionMaterial(tp,locations)
local res=Duel.GetFusionMaterial(tp,locations)
local g=Duel.GetMatchingGroup(Card.IsHasEffect,tp,LOCATION_EXTRA,0,nil,EFFECT_EXTRA_FUSION_MATERIAL)
if #g>0 then
res:Merge(g)
end
return res
end
---@param c Card card that uses the effect
---@param fusfilter (fun(c:Card):boolean)? filter for the monster to be Fusion Summoned
---@param matfilter (fun(c:Card):boolean)? filter for the materials, use it only under very strong limitation like D-Fusion.
---@param pre_select_mat_location integer|FUSION_SPELL_PRE_SELECT_MAT_LOCATION_FUNCTION? location where to find the materials before known the materials (default LOCATION_HAND|LOCATION_MZONE)
---@param mat_operation_code_map {[integer]:FUSION_OPERATION_CODE}[]? operation code to do for the materials, it will be check in order (default [{ LOCATION_GRAVE: FUSION_OPERATION_BANISH}, { 0xff: FUSION_OPERATION_GRAVE}])
---@param post_select_mat_location integer? location where to find the materials after known the materials (default nil)
---@param post_select_mat_check function? function to check whether we can enable the extra locations
---@param additional_fcheck function? function to check the final material group fits the requirement
---@param additional_gcheck function? function to check the part of potiential material group fits the requirement to improve performance
---@param fuslocation integer? location where to summon fusion monsters from (default LOCATION_EXTRA), use it on Clock Lizard
---@param sumtype integer? summon type (default SUMMON_TYPE_FUSION)
---@param sumpos integer? summon position (default POS_FACEUP)
function FusionSpell.RegisterSummonEffect(c,fusfilter,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,post_select_mat_check,additional_fcheck,additional_gcheck,fuslocation,sumtype,sumpos)
local e1=FusionSpell.CreateSummonEffect(c,fusfilter,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,post_select_mat_check,additional_fcheck,additional_gcheck,fuslocation,sumtype,sumpos)
Card.RegisterEffect(c,e1)
return e1
end
---@param c Card card that uses the effect
---@param fusfilter (fun(c:Card):boolean)? filter for the monster to be Fusion Summoned
---@param matfilter (fun(c:Card):boolean)? filter for the materials, use it only under very strong limitation like D-Fusion.
---@param pre_select_mat_location integer|FUSION_SPELL_PRE_SELECT_MAT_LOCATION_FUNCTION? location where to find the materials before known the materials (default LOCATION_HAND|LOCATION_ONFIELD)
---@param mat_operation_code_map {[integer]:FUSION_OPERATION_CODE}[]? operation code to do for the materials, it will be check in order (default [{ LOCATION_GRAVE: FUSION_OPERATION_BANISH}, { 0xff: FUSION_OPERATION_GRAVE}])
---@param post_select_mat_location integer? location where to find the materials after known the materials (default nil)
---@param post_select_mat_check function? function to check whether we can enable the extra locations
---@param additional_fcheck function? function to check the final material group fits the requirement
---@param additional_gcheck function? function to check the part of potiential material group fits the requirement to improve performance
---@param fuslocation integer? location where to summon fusion monsters from (default LOCATION_EXTRA), use it on Clock Lizard
---@param sumtype integer? summon type (default SUMMON_TYPE_FUSION)
---@param sumpos integer? summon position (default POS_FACEUP)
function FusionSpell.CreateSummonEffect(c,fusfilter,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,post_select_mat_check,additional_fcheck,additional_gcheck,fuslocation,sumtype,sumpos)
matfilter=matfilter or aux.TRUE
pre_select_mat_location=pre_select_mat_location or LOCATION_HAND|LOCATION_ONFIELD
mat_operation_code_map=mat_operation_code_map or {}
-- add last fallback, banish grave, grave others
table.insert(mat_operation_code_map,{[LOCATION_GRAVE]=FusionSpell.FUSION_OPERATION_BANISH})
table.insert(mat_operation_code_map,{[0xff]=FusionSpell.FUSION_OPERATION_GRAVE})
fuslocation=fuslocation or LOCATION_EXTRA
sumtype=sumtype or SUMMON_TYPE_FUSION
sumpos=sumpos or POS_FACEUP
local e1=Effect.CreateEffect(c)
e1:SetCategory(CATEGORY_SPECIAL_SUMMON+CATEGORY_FUSION_SUMMON)
e1:SetType(EFFECT_TYPE_ACTIVATE)
e1:SetCode(EVENT_FREE_CHAIN)
e1:SetTarget(FusionSpell.GetSummonTarget(fusfilter,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,post_select_mat_check,additional_fcheck,additional_gcheck,fuslocation,sumtype,sumpos))
e1:SetOperation(FusionSpell.GetSummonOperation(fusfilter,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,post_select_mat_check,additional_fcheck,additional_gcheck,fuslocation,sumtype,sumpos))
return e1
end
---@param fusfilter fun(c:Card):boolean? filter for the monster to be Fusion Summoned
---@param matfilter fun(c:Card):boolean? filter for the materials, use it only under very strong limitation like D-Fusion.
---@param pre_select_mat_location integer|FUSION_SPELL_PRE_SELECT_MAT_LOCATION_FUNCTION? location where to find the materials before known the materials (default LOCATION_HAND|LOCATION_MZONE)
---@param mat_operation_code_map {[integer]:FUSION_OPERATION_CODE}[]? operation code to do for the materials, it will be check in order (default [{ LOCATION_GRAVE: FUSION_OPERATION_BANISH}, { 0xff: FUSION_OPERATION_GRAVE}])
---@param post_select_mat_location integer? location where to find the materials after known the materials (default nil)
---@param post_select_mat_check function? function to check whether we can enable the extra locations
---@param additional_fcheck function? function to check the final material group fits the requirement
---@param additional_gcheck function? function to check the part of potiential material group fits the requirement to improve performance
---@param fuslocation integer? location where to summon fusion monsters from (default LOCATION_EXTRA), use it on Clock Lizard
---@param sumtype integer? summon type (default SUMMON_TYPE_FUSION)
---@param sumpos integer? summon position (default POS_FACEUP)
function FusionSpell.GetSummonTarget(fusfilter,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,post_select_mat_check,additional_fcheck,additional_gcheck,fuslocation,sumtype,sumpos)
return function(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then
if additional_fcheck~=nil then
aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunction(additional_fcheck,tp,c)
end
local sg=Duel.GetMatchingGroup(FusionSpell.SummonTargetFilter,tp,fuslocation,0,nil,fusfilter,e,tp,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,sumtype,sumpos)
aux.FCheckAdditional=nil
return #sg>0
end
Duel.SetOperationInfo(0,CATEGORY_SPECIAL_SUMMON,nil,1,tp,fuslocation)
end
end
---@param fusfilter fun(c:Card):boolean filter for the monster to be Fusion Summoned
---@param matfilter fun(c:Card):boolean filter for the materials, use it only under very strong limitation like D-Fusion.
---@param pre_select_mat_location integer|FUSION_SPELL_PRE_SELECT_MAT_LOCATION_FUNCTION location where to find the materials before known the materials
---@param mat_operation_code_map {[integer]:FUSION_OPERATION_CODE}[] operation code to do for the materials, it will be check in order
---@param post_select_mat_location integer? location where to find the materials after known the materials (default nil)
---@param post_select_mat_check function? function to check whether we can enable the extra locations
---@param additional_fcheck function? function to check the final material group fits the requirement
---@param additional_gcheck function? function to check the part of potiential material group fits the requirement to improve performance
---@param fuslocation integer location where to summon fusion monsters from (default LOCATION_EXTRA), use it on Clock Lizard
---@param sumtype integer summon type (default SUMMON_TYPE_FUSION)
---@param sumpos integer summon position (default POS_FACEUP)
function FusionSpell.GetSummonOperation(fusfilter,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,post_select_mat_check,additional_fcheck,additional_gcheck,fuslocation,sumtype,sumpos)
return function(e,tp,eg,ep,ev,re,r,rp)
local sg=Duel.GetMatchingGroup(FusionSpell.SummonTargetFilter,tp,fuslocation,0,nil,fusfilter,e,tp,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,sumtype,sumpos)
if #sg>0 then
local tc=nil
local materials=Group.CreateGroup()
while #materials==0 do
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON)
tc=sg:Select(tp,1,1,nil):GetFirst()
local mg_for_tc=FusionSpell.GetMaterialsGroupForTargetCard(tc,tp,e,pre_select_mat_location,mat_operation_code_map,post_select_mat_location)
if additional_fcheck~=nil then
aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunction(additional_fcheck,tp,c)
end
materials=Duel.SelectFusionMaterial(tp,tc,mg_for_tc)
aux.FCheckAdditional=nil
end
assert(tc~=nil)
if #materials>0 then
local all_locations=FusionSpell.GetAllLocationsForTargetCard(tc,tp,pre_select_mat_location,post_select_mat_location)
---@type Effect[]
local applied_extra_effects={}
---@type {[function]:Group}
local material_grouped_by_op={}
--For material that can be material only by 1 effect, either fusion spell or extra material effect, do the operation on it.
--For material that can be material by multiple effect, ask user which to apply.
for material in aux.Next(materials) do
local material_effects=FusionSpell.GetMaterialEffects(material,tc,all_locations,materials)
if material_effects~=nil and #material_effects>0 then
local material_effect=nil
if #material_effects==1 then
material_effect=material_effects[1]
else
-- more than one effect. ask player to choose from one.
material_effect=FusionSpell.MultiMaterialEffectPrompt(material_effects,tp,e)
end
local fusion_operation=nil
if material_effect==true then
local fusion_operation_code=FusionSpell.GetOperationCodeByMaterialLocation(material:GetLocation(),mat_operation_code_map)
fusion_operation=FusionSpell.GetFusionOperationByCode(fusion_operation_code)
else
-- extra material effects
local fusion_operation_code=material_effect:GetOperation()()
fusion_operation=FusionSpell.GetFusionOperationByCode(fusion_operation_code,material:GetLocation(),mat_operation_code_map)
table.insert(applied_extra_effects,material_effect)
end
assert(fusion_operation~=nil)
material_grouped_by_op[fusion_operation]=material_grouped_by_op[fusion_operation] or Group.CreateGroup()
material_grouped_by_op[fusion_operation]:AddCard(material)
else
--else we are in trouble
assert(false,string.format("card %d has no material effect",material:GetCode()))
end
end
-- perform operations on materials
for operation,materials in pairs(material_grouped_by_op) do
operation(materials,tp)
end
-- mark effect as used once. if count limit reached, reset the effect
for _,effect in ipairs(applied_extra_effects) do
effect:UseCountLimit(tp)
if effect:CheckCountLimit(tp)==false then
effect:Reset()
end
end
end
Duel.BreakEffect()
Duel.SpecialSummonStep(tc,SUMMON_TYPE_FUSION,tp,tp,false,false,sumpos)
Duel.SpecialSummonComplete()
tc:CompleteProcedure()
end
end
end
---@param pre_select_mat_location integer|(fun(tc:Card,tp:integer):integer) location where to find the materials before known the materials
---@return integer locations all possible locations of the material
function FusionSpell.GetAllLocationsForTargetCard(tc,tp,pre_select_mat_location,post_select_mat_location)
local all_locations=0
if type(pre_select_mat_location)=="function" then
all_locations=all_locations|pre_select_mat_location(tc,tp)
else
assert(pre_select_mat_location~=nil, "pre_select_mat_location is nil")
all_locations=all_locations|pre_select_mat_location
end
if post_select_mat_location~=nil then
all_locations=all_locations|post_select_mat_location
end
return all_locations
end
---@param pre_select_mat_location integer|function location where to find the materials before known the materials
function FusionSpell.GetMaterialsGroupForTargetCard(tc,tp,e,pre_select_mat_location,mat_operation_code_map,post_select_mat_location)
local all_locations=FusionSpell.GetAllLocationsForTargetCard(tc,tp,pre_select_mat_location,post_select_mat_location)
local mg=FusionSpell.GetFusionMaterial(tp,all_locations)
mg=mg:Filter(function(mc)
--- in order to be qualified for being material, it need to be able to perform the operation.
local can_be_fusion_spell_material=false
if mc:IsLocation(all_locations) then
---@type FUSION_FILTER_FUNCTION
local filter_by_operation=FusionSpell.GetFusionFilterByCode(FusionSpell.GetOperationCodeByMaterialLocation(mc:GetLocation(),mat_operation_code_map))
can_be_fusion_spell_material=filter_by_operation(mc,tp,e)
end
local can_be_extra_material=false
local extra_effect=FusionSpell.GetExtraMaterialEffect(mc,tp,tc)
if extra_effect~=nil then
---@type FUSION_OPERATION_CODE
local operation_code=FusionSpell.FUSION_OPERATION_INHERIT
if extra_effect:GetOperation()~=nil then
operation_code=extra_effect:GetOperation()()
end
operation_code=operation_code or FusionSpell.FUSION_OPERATION_INHERIT
local filter_by_operation=FusionSpell.GetFusionFilterByCode(operation_code,mc:GetLocation(),mat_operation_code_map)
can_be_extra_material=filter_by_operation(mc,tp,e)
end
return can_be_fusion_spell_material or can_be_extra_material
end,tc)
return mg
end
---@param location integer
---@param mat_operation_code_map {[integer]:FUSION_OPERATION_CODE}[]? operation code to do for the materials, it will be check in order
function FusionSpell.GetOperationCodeByMaterialLocation(location,mat_operation_code_map)
for _,map in ipairs(mat_operation_code_map) do
for key,value in pairs(map) do
if location&key~=0 then
return value
end
end
end
end
---@param fusfilter fun(c:Card,tp:integer):boolean
---@param pre_select_mat_location integer|function location where to find the materials before known the materials (default LOCATION_HAND|LOCATION_MZONE)
function FusionSpell.SummonTargetFilter(c,fusfilter,e,tp,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,sumtype,sumpos)
local mg=FusionSpell.GetMaterialsGroupForTargetCard(c,tp,e,pre_select_mat_location,mat_operation_code_map,post_select_mat_location)
if additional_fcheck~=nil then
aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunction(additional_fcheck,tp,c)
end
local res=c:IsType(TYPE_FUSION) and (not fusfilter or fusfilter(c,tp)) and c:IsCanBeSpecialSummoned(e,sumtype,tp,false,false,sumpos) and c:CheckFusionMaterial(mg)
aux.FCheckAdditional=nil
return res
end
-- operation that would be applied on the material
---@alias FUSION_OPERATION_CODE integer
FusionSpell.FUSION_OPERATION_INHERIT=0x10000 -- used only on EFFECT_EXTRA_FUSION_MATERIAL effects, inherits the operation of fusion spell
FusionSpell.FUSION_OPERATION_GRAVE=0x1
FusionSpell.FUSION_OPERATION_BANISH=0x2
FusionSpell.FUSION_OPERATION_BANISH_FACEDOWN=0x3
FusionSpell.FUSION_OPERATION_SHUFFLE=0x4
FusionSpell.FUSION_OPERATION_DECK_BOTTOM=0x5
FusionSpell.FUSION_OPERATION_DESTROY=0x6
---@return FUSION_OPERATION_FUNCTION
function FusionSpell.GetFusionOperationByCode(code,matlocation,fusion_spell_operation_code_map)
if code==FusionSpell.FUSION_OPERATION_GRAVE then
return FusionSpell.GraveMaterial
elseif code==FusionSpell.FUSION_OPERATION_BANISH then
return FusionSpell.BanishMaterial
elseif code==FusionSpell.FUSION_OPERATION_BANISH_FACEDOWN then
return FusionSpell.BanishMaterialFaceDown
elseif code==FusionSpell.FUSION_OPERATION_SHUFFLE then
return FusionSpell.ShuffleMaterial
elseif code==FusionSpell.FUSION_OPERATION_DECK_BOTTOM then
return FusionSpell.SendDeckBottomMaterial
elseif code==FusionSpell.FUSION_OPERATION_DESTROY then
return FusionSpell.DestroyMaterial
elseif code==FusionSpell.FUSION_OPERATION_INHERIT then
if matlocation==nil or fusion_spell_operation_code_map==nil then
-- we are in trouble
assert(false, "we have an material that inhreits, but operation can be inhreited")
return FusionSpell.GraveMaterial
end
return FusionSpell.GetFusionOperationByCode(fusion_spell_operation_code_map[matlocation])
end
end
---@return FUSION_FILTER_FUNCTION
function FusionSpell.GetFusionFilterByCode(code,matlocation,fusion_spell_operation_code_map)
if code==FusionSpell.FUSION_OPERATION_GRAVE then
return FusionSpell.GraveMaterialFilter
elseif code==FusionSpell.FUSION_OPERATION_BANISH then
return FusionSpell.BanishMaterialFilter
elseif code==FusionSpell.FUSION_OPERATION_BANISH_FACEDOWN then
return FusionSpell.BanishMaterialFaceDownFilter
elseif code==FusionSpell.FUSION_OPERATION_SHUFFLE then
return FusionSpell.ShuffleMaterialFilter
elseif code==FusionSpell.FUSION_OPERATION_DECK_BOTTOM then
return FusionSpell.SendDeckBottomMaterialFilter
elseif code==FusionSpell.FUSION_OPERATION_DESTROY then
return FusionSpell.DestroyMaterialFilter
elseif code==FusionSpell.FUSION_OPERATION_INHERIT then
if matlocation==nil or fusion_spell_operation_code_map==nil then
-- we are in trouble
return nil
end
return FusionSpell.GetFusionFilterByCode(fusion_spell_operation_code_map[matlocation])
end
end
---@alias FUSION_OPERATION_FUNCTION fun(sg:Card|Group,tp:integer):integer
---@alias FUSION_FILTER_FUNCTION fun(c:Card,tp:integer?,e:Effect?):boolean
---@type FUSION_OPERATION_FUNCTION
function FusionSpell.DestroyMaterial(sg,tp)
return Duel.Destroy(sg,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION,nil,tp)
end
---@type FUSION_FILTER_FUNCTION
function FusionSpell.DestroyMaterialFilter(c,tp,e)
return c:IsDestructable(e)
end
---@type FUSION_OPERATION_FUNCTION
function FusionSpell.GraveMaterial(sg,tp)
return Duel.SendtoGrave(sg,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION,tp)
end
---@type FUSION_FILTER_FUNCTION
function FusionSpell.GraveMaterialFilter(c)
return c:IsAbleToGrave()
end
---@type FUSION_OPERATION_FUNCTION
function FusionSpell.BanishMaterial(sg,tp)
return Duel.Remove(sg,POS_FACEUP,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION,tp)
end
---@type FUSION_FILTER_FUNCTION
function FusionSpell.BanishMaterialFilter(c,tp)
return c:IsAbleToRemove(tp,POS_FACEUP,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION)
end
---@type FUSION_OPERATION_FUNCTION
function FusionSpell.BanishMaterialFaceDown(sg,tp)
return Duel.Remove(sg,POS_FACEDOWN,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION,tp)
end
---@type FUSION_FILTER_FUNCTION
function FusionSpell.BanishMaterialFaceDownFilter(c,tp)
return c:IsAbleToRemove(tp,POS_FACEDOWN,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION)
end
---@type FUSION_OPERATION_FUNCTION
function FusionSpell.ShuffleMaterial(sg,tp)
return Duel.SendtoDeck(sg,nil,SEQ_DECKSHUFFLE,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION,tp)
end
---@type FUSION_FILTER_FUNCTION
function FusionSpell.ShuffleMaterialFilter(c)
return c:IsAbleToDeck()
end
---@type FUSION_OPERATION_FUNCTION
function FusionSpell.SendDeckBottomMaterial(sg,tp)
-- prompt user to select order
return Duel.SendtoDeck(sg,nil,SEQ_DECKBOTTOM,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION,tp)
end
---@type FUSION_FILTER_FUNCTION
function FusionSpell.SendDeckBottomMaterialFilter(c)
return c:IsAbleToDeck()
end
--Returns a list of effect, if element is the EFFECT_EXTRA_FUSION_MATERIAL, stands for it can be included by that extra material effect.
--if element is true, stands for it can be included by the fusion effect itself.
---@return (true|Effect)[]
function FusionSpell.GetMaterialEffects(c,summon_card,matlocation,materials)
local res={}
if c:IsLocation(matlocation) then
table.insert(res,true)
end
local extra_effs={c:IsHasEffect(EFFECT_EXTRA_FUSION_MATERIAL)}
for _,eff in ipairs(extra_effs) do
if not summon_card then
table.insert(res,eff)
end
local val=eff:GetValue()
if (type(val)=="function" and val(eff,summon_card)) or val==1 then
table.insert(res,eff)
end
end
return res
end
--Returns the 1st EFFECT_EXTRA_FUSION_MATERIAL is applied on Card c.
--If summon_card is provided, it will filter on whether the effect's value function applies to that card.
---@param c Card the material card card
---@param tp integer the player
---@param summon_card Card the target card
function FusionSpell.GetExtraMaterialEffect(c,tp,summon_card)
local effs={c:IsHasEffect(EFFECT_EXTRA_FUSION_MATERIAL)}
for _,eff in ipairs(effs) do
if eff:CheckCountLimit(tp)==true then
if summon_card==nil then
return eff
end
local val=eff:GetValue()
if (type(val)=="function" and val(eff,summon_card)) or val==1 then
return eff
end
end
end
end
-- when a material has multiple effect make it could be material, ask for which to apply.
---@return true|Effect
function FusionSpell.MultiMaterialEffectPrompt(effects,tp,e)
local ops= {}
for i,eff in ipairs(effects) do
if eff==true then
-- this can be used as default material
table.insert(ops,e:GetDescription())
else
table.insert(ops,eff:GetDescription())
end
end
local op=Duel.SelectOption(tp,table.unpack(ops))
return effects[op + 1]
end
--- filter out materials that does not necessary come from fusion spell and pass to the gcheck of fusion spell
--- @param fusion_spell_additional_fcheck_function FUSION_FCHECK_FUNCTION
function FusionSpell.GetFusionSpellFCheckAdditionalFunction(fusion_spell_additional_fcheck_function,tp,tc)
return (function(f_tp,mg,fc)
local extra_mg=mg:Filter(FusionSpell.GetExtraMaterialEffect,nil,tp,tc)
return fusion_spell_additional_fcheck_function(f_tp,mg-extra_mg,fc,sg)
end)
end
#The first line is used for comment #The first line is used for comment
!setname 0x1c3 巳剑 Mitsurugi
!counter 0x6e 四季指示物
!counter 0x106f 少女指示物 !counter 0x106f 少女指示物
!setname 0x2cc 瞬间移动
!setname 0x2cd 神艺
!setname 0x2ce 狱神
!setname 0x2cf 树熊 !setname 0x2cf 树熊
!setname 0x2d0 死伟王 !setname 0x2d0 死伟王
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment