Commit b02703c0 authored by Vury Leo's avatar Vury Leo

Add 多層融合 to new fusion

parent cc23a09b
Pipeline #37080 failed with stages
in 3 minutes and 7 seconds
...@@ -13,7 +13,7 @@ function s.initial_effect(c) ...@@ -13,7 +13,7 @@ function s.initial_effect(c)
e1:SetValue(s.mtval) e1:SetValue(s.mtval)
e1:SetOperation(function() return FusionSpell.FUSION_OPERATION_INHERIT end) e1:SetOperation(function() return FusionSpell.FUSION_OPERATION_INHERIT end)
-- as of 2025 May, there is no card can add LOCATION_MZONE base on material group. So we can just check pre_select_mat_location. -- as of 2025 May, there is no card can add LOCATION_MZONE base on material group. So we can just check pre_select_mat_location.
e1:SetLabel(0xff,LOCATION_MZONE) --- only avaliable when pre_select_mat_location contains LOCATION_MZONE, 1st number is limitaion of count materials, set 0xff as a placeholder e1:SetLabel(0,LOCATION_MZONE) --- only avaliable when pre_select_mat_location contains LOCATION_MZONE, 1st number is limitaion of count materials, set 0 as infinity
c:RegisterEffect(e1) c:RegisterEffect(e1)
--counter --counter
local e2=Effect.CreateEffect(c) local e2=Effect.CreateEffect(c)
......
...@@ -2,121 +2,50 @@ ...@@ -2,121 +2,50 @@
local s,id,o=GetID() local s,id,o=GetID()
function s.initial_effect(c) function s.initial_effect(c)
--Activate --Activate
local e1=Effect.CreateEffect(c) local e1=FusionSpell.CreateSummonEffect(c,{
additional_fcheck=s.additional_fcheck,
additional_fgoalcheck=s.additional_fgoalcheck,
pre_select_mat_location=LOCATION_HAND|LOCATION_MZONE|LOCATION_EXTRA,
mat_operation_code_map={
{ [LOCATION_EXTRA|LOCATION_GRAVE] = FusionSpell.FUSION_OPERATION_BANISH },
{ [0xff] = FusionSpell.FUSION_OPERATION_GRAVE }
},
stage_x_operation=s.stage_x_operation
})
e1:SetDescription(aux.Stringid(id,0)) 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) c:RegisterEffect(e1)
end end
s.fusion_effect=true
function s.fcheck1(ct) ---@type FUSION_FGCHECK_FUNCTION
return function(tp,sg,fc) function s.additional_fcheck(tp,mg,fc,all_mg)
if ct>0 and sg:FilterCount(Card.IsLocation,nil,LOCATION_EXTRA)>ct then --- material from extra deck by this fusion spell can not exceed monster opponent controls
return false local count_from_extra=mg:FilterCount(Card.IsLocation,nil,LOCATION_EXTRA)
end local monster_count_of_opponet=Duel.GetMatchingGroupCount(aux.TRUE,tp,0,LOCATION_MZONE,nil)
return true if count_from_extra>monster_count_of_opponet then
end return false
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
return true
end end
function s.activate(e,tp,eg,ep,ev,re,r,rp)
local chkf=tp ---@type FUSION_FGCHECK_FUNCTION
local mg1=Duel.GetFusionMaterial(tp):Filter(aux.NOT(Card.IsImmuneToEffect),nil,e) function s.additional_fgoalcheck(tp,mg,fc,all_mg)
local ct=Duel.GetFieldGroupCount(tp,0,LOCATION_MZONE) return all_mg:GetCount()>=3
if ct>0 then end
local mg2=Duel.GetMatchingGroup(s.filter0,tp,LOCATION_EXTRA,0,nil)
if mg2:GetCount()>0 then ---@type FUSION_SPELL_STAGE_X_CALLBACK_FUNCTION
mg1:Merge(mg2) function s.stage_x_operation(e,tc,tp,stage,mg_fuison_spell,mg_all)
end if stage==FusionSpell.STAGE_BEFORE_SUMMON_COMPLETE then
end local exmat=mg_fuison_spell:Filter(Card.IsPreviousLocation,nil,LOCATION_EXTRA)
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 if #exmat>0 then
local dam=exmat:GetSum(Card.GetAttack) local dam=exmat:GetSum(Card.GetAttack)
local lp=Duel.GetLP(tp) if dam>0 then
if lp>=dam then local lp=Duel.GetLP(tp)
Duel.SetLP(tp,lp-dam) if lp>=dam then
else Duel.SetLP(tp,lp-dam)
Duel.SetLP(tp,0) else
Duel.SetLP(tp,0)
end
end end
end end
Duel.SpecialSummonComplete()
tc:CompleteProcedure()
end end
aux.FCheckAdditional=nil
aux.FGoalCheckAdditional=nil
end end
...@@ -2285,9 +2285,9 @@ FusionSpell = {} ...@@ -2285,9 +2285,9 @@ FusionSpell = {}
--- @field post_select_mat_location? integer --- @field post_select_mat_location? integer
--- Location(s) to look for materials after they've been selected. --- Location(s) to look for materials after they've been selected.
--- @field additional_fcheck? FUSION_FGCHECK_FUNCTION --- @field additional_fcheck? FUSION_FGCHECK_FUNCTION
--- Optional quick check to validate the selected material group.
--- @field additional_fgoalcheck? FUSION_FGCHECK_FUNCTION
--- Optional final check to validate the selected material group. --- Optional final check to validate the selected material group.
--- @field additional_gcheck? FUSION_FGCHECK_FUNCTION
--- Optional quick check to validate partial material groups (for performance).
--- @field fuslocation? integer --- @field fuslocation? integer
--- The location to summon Fusion Monsters from. Defaults to `LOCATION_EXTRA`. --- The location to summon Fusion Monsters from. Defaults to `LOCATION_EXTRA`.
--- @field sumtype? integer --- @field sumtype? integer
...@@ -2372,7 +2372,7 @@ function FusionSpell.CreateSummonEffect(c,opts) ...@@ -2372,7 +2372,7 @@ function FusionSpell.CreateSummonEffect(c,opts)
local mat_operation_code_map=opts.mat_operation_code_map or {} local mat_operation_code_map=opts.mat_operation_code_map or {}
local post_select_mat_location=opts.post_select_mat_location local post_select_mat_location=opts.post_select_mat_location
local additional_fcheck=opts.additional_fcheck or aux.TRUE local additional_fcheck=opts.additional_fcheck or aux.TRUE
local additional_gcheck=opts.additional_gcheck or aux.TRUE local additional_fgoalcheck=opts.additional_fgoalcheck or aux.TRUE
local fuslocation=opts.fuslocation or LOCATION_EXTRA local fuslocation=opts.fuslocation or LOCATION_EXTRA
local sumtype=opts.sumtype or SUMMON_TYPE_FUSION local sumtype=opts.sumtype or SUMMON_TYPE_FUSION
local sumpos=opts.sumpos or POS_FACEUP local sumpos=opts.sumpos or POS_FACEUP
...@@ -2397,7 +2397,7 @@ function FusionSpell.CreateSummonEffect(c,opts) ...@@ -2397,7 +2397,7 @@ function FusionSpell.CreateSummonEffect(c,opts)
mat_operation_code_map, mat_operation_code_map,
post_select_mat_location, post_select_mat_location,
additional_fcheck, additional_fcheck,
additional_gcheck, additional_fgoalcheck,
fuslocation, fuslocation,
sumtype, sumtype,
sumpos, sumpos,
...@@ -2412,7 +2412,7 @@ function FusionSpell.CreateSummonEffect(c,opts) ...@@ -2412,7 +2412,7 @@ function FusionSpell.CreateSummonEffect(c,opts)
mat_operation_code_map, mat_operation_code_map,
post_select_mat_location, post_select_mat_location,
additional_fcheck, additional_fcheck,
additional_gcheck, additional_fgoalcheck,
fuslocation, fuslocation,
sumtype, sumtype,
sumpos, sumpos,
...@@ -2429,8 +2429,8 @@ end ...@@ -2429,8 +2429,8 @@ end
---@param pre_select_mat_location integer|FUSION_SPELL_PRE_SELECT_MAT_LOCATION_FUNCTION location where to find the materials before known the materials ---@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 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 ---@param post_select_mat_location integer? location where to find the materials after known the materials
---@param additional_fcheck FUSION_FGCHECK_FUNCTION function to check the final material group fits the requirement ---@param additional_fcheck FUSION_FGCHECK_FUNCTION function to check the partial material group fits the requirement
---@param additional_gcheck FUSION_FGCHECK_FUNCTION function to check the part of potiential material group fits the requirement to improve performance ---@param additional_fgoalcheck FUSION_FGCHECK_FUNCTION function to check the final material group fits the requirement
---@param fuslocation integer location where to summon fusion monsters from (default LOCATION_EXTRA), use it on Clock Lizard ---@param fuslocation integer location where to summon fusion monsters from (default LOCATION_EXTRA), use it on Clock Lizard
---@param sumtype integer summon type ---@param sumtype integer summon type
---@param sumpos integer summon position ---@param sumpos integer summon position
...@@ -2444,7 +2444,7 @@ function FusionSpell.GetSummonTarget( ...@@ -2444,7 +2444,7 @@ function FusionSpell.GetSummonTarget(
mat_operation_code_map, mat_operation_code_map,
post_select_mat_location, post_select_mat_location,
additional_fcheck, additional_fcheck,
additional_gcheck, additional_fgoalcheck,
fuslocation, fuslocation,
sumtype, sumtype,
sumpos, sumpos,
...@@ -2460,13 +2460,13 @@ function FusionSpell.GetSummonTarget( ...@@ -2460,13 +2460,13 @@ function FusionSpell.GetSummonTarget(
local sg=Duel.IsExistingMatchingCard( local sg=Duel.IsExistingMatchingCard(
FusionSpell.SummonTargetFilter,tp,fuslocation,0,1,nil, FusionSpell.SummonTargetFilter,tp,fuslocation,0,1,nil,
--- FusionSpell.SummonTargetFilter param --- FusionSpell.SummonTargetFilter param
fusfilter,matfilter,e,tp,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,sumtype,sumpos,pre_select_mat_opponent_location,gc) fusfilter,matfilter,e,tp,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,additional_fgoalcheck,sumtype,sumpos,pre_select_mat_opponent_location,gc)
if sg==true then if sg==true then
return true return true
end end
-- --- check for chain material targets -- --- check for chain material targets
if sumtype&SUMMON_TYPE_FUSION~=0 then if sumtype&SUMMON_TYPE_FUSION~=0 then
local ce_sg=FusionSpell.IsExistsChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,fuslocation,sumtype,sumpos,gc) local ce_sg=FusionSpell.IsExistsChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,additional_fgoalcheck,fuslocation,sumtype,sumpos,gc)
if ce_sg==true then if ce_sg==true then
return true return true
end end
...@@ -2483,8 +2483,8 @@ end ...@@ -2483,8 +2483,8 @@ end
---@param pre_select_mat_location integer|FUSION_SPELL_PRE_SELECT_MAT_LOCATION_FUNCTION location where to find the materials before known the materials ---@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 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 ---@param post_select_mat_location integer? location where to find the materials after known the materials
---@param additional_fcheck function function to check the final material group fits the requirement ---@param additional_fcheck FUSION_FGCHECK_FUNCTION function to check the partial 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 additional_fgoalcheck FUSION_FGCHECK_FUNCTION function to check the final material group fits the requirement
---@param fuslocation integer location where to summon fusion monsters from, use it on Clock Lizard ---@param fuslocation integer location where to summon fusion monsters from, use it on Clock Lizard
---@param sumtype integer summon type ---@param sumtype integer summon type
---@param sumpos integer summon position ---@param sumpos integer summon position
...@@ -2498,7 +2498,7 @@ function FusionSpell.GetSummonOperation( ...@@ -2498,7 +2498,7 @@ function FusionSpell.GetSummonOperation(
mat_operation_code_map, mat_operation_code_map,
post_select_mat_location, post_select_mat_location,
additional_fcheck, additional_fcheck,
additional_gcheck, additional_fgoalcheck,
fuslocation, fuslocation,
sumtype, sumtype,
sumpos, sumpos,
...@@ -2510,12 +2510,12 @@ function FusionSpell.GetSummonOperation( ...@@ -2510,12 +2510,12 @@ function FusionSpell.GetSummonOperation(
local sg=Duel.GetMatchingGroup( local sg=Duel.GetMatchingGroup(
FusionSpell.SummonTargetFilter,tp,fuslocation,0,nil, FusionSpell.SummonTargetFilter,tp,fuslocation,0,nil,
--- FusionSpell.SummonTargetFilter param --- FusionSpell.SummonTargetFilter param
fusfilter,matfilter,e,tp,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,sumtype,sumpos,pre_select_mat_opponent_location,gc) fusfilter,matfilter,e,tp,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,additional_fgoalcheck,sumtype,sumpos,pre_select_mat_opponent_location,gc)
--- check for chain material targets --- check for chain material targets
local ce_sgs={} local ce_sgs={}
local can_chain_material=false local can_chain_material=false
if sumtype&SUMMON_TYPE_FUSION~=0 then if sumtype&SUMMON_TYPE_FUSION~=0 then
ce_sgs=FusionSpell.ListChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,fuslocation,sumtype,sumpos,gc) ce_sgs=FusionSpell.ListChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,additional_fgoalcheck,fuslocation,sumtype,sumpos,gc)
--- if there's any chain material effect has valid target --- if there's any chain material effect has valid target
for _ in pairs(ce_sgs) do for _ in pairs(ce_sgs) do
can_chain_material=true can_chain_material=true
...@@ -2566,8 +2566,10 @@ function FusionSpell.GetSummonOperation( ...@@ -2566,8 +2566,10 @@ function FusionSpell.GetSummonOperation(
sumtype, sumtype,
pre_select_mat_opponent_location) pre_select_mat_opponent_location)
aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunction(additional_fcheck,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location) aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunction(additional_fcheck,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location)
aux.FGoalCheckAdditional=FusionSpell.GetFusionSpellFGoalCheckAdditionalFunction(additional_fgoalcheck,tp,tc,pre_select_mat_location)
materials=Duel.SelectFusionMaterial(tp,tc,mg,gc(e),tp) materials=Duel.SelectFusionMaterial(tp,tc,mg,gc(e),tp)
aux.FCheckAdditional=nil aux.FCheckAdditional=nil
aux.FGoalCheckAdditional=nil
else else
--- use chain material effect --- use chain material effect
---@type function ---@type function
...@@ -2575,8 +2577,10 @@ function FusionSpell.GetSummonOperation( ...@@ -2575,8 +2577,10 @@ function FusionSpell.GetSummonOperation(
local chain_mg=chain_material_filter(fusion_effect,e,tp) local chain_mg=chain_material_filter(fusion_effect,e,tp)
assert(#chain_mg>0, "we are trying to apply a chain material, but it has no possible material") assert(#chain_mg>0, "we are trying to apply a chain material, but it has no possible material")
aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunctionForChainMaterial(additional_fcheck) aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunctionForChainMaterial(additional_fcheck)
aux.FGoalCheckAdditional=FusionSpell.GetFusionSpellFGoalCheckAdditionalFunctionForChainMaterial(additional_fgoalcheck)
materials=Duel.SelectFusionMaterial(tp,tc,chain_mg,gc(e),tp) materials=Duel.SelectFusionMaterial(tp,tc,chain_mg,gc(e),tp)
aux.FCheckAdditional=nil aux.FCheckAdditional=nil
aux.FGoalCheckAdditional=nil
end end
end end
...@@ -2584,6 +2588,7 @@ function FusionSpell.GetSummonOperation( ...@@ -2584,6 +2588,7 @@ function FusionSpell.GetSummonOperation(
assert(fusion_effect~=nil) assert(fusion_effect~=nil)
if #materials>0 then if #materials>0 then
local materials_from_spell_card=Group.CreateGroup()
if fusion_effect==e then if fusion_effect==e then
--- fusion with fusion spell --- fusion with fusion spell
tc:SetMaterial(materials) tc:SetMaterial(materials)
...@@ -2591,6 +2596,7 @@ function FusionSpell.GetSummonOperation( ...@@ -2591,6 +2596,7 @@ function FusionSpell.GetSummonOperation(
local applied_extra_effects={} local applied_extra_effects={}
---@type {[FUSION_OPERATION_FUNCTION]:Group} ---@type {[FUSION_OPERATION_FUNCTION]:Group}
local material_grouped_by_op={} local material_grouped_by_op={}
local materials_with_one_material_effect=materials:Filter(function(mc) return (#FusionSpell.GetMaterialEffects(mc,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location))==1 end,nil) local materials_with_one_material_effect=materials:Filter(function(mc) return (#FusionSpell.GetMaterialEffects(mc,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location))==1 end,nil)
for material in aux.Next(materials_with_one_material_effect) do for material in aux.Next(materials_with_one_material_effect) do
--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 only by 1 effect, either fusion spell or extra material effect, do the operation on it.
...@@ -2600,6 +2606,7 @@ function FusionSpell.GetSummonOperation( ...@@ -2600,6 +2606,7 @@ function FusionSpell.GetSummonOperation(
if material_effect==true then if material_effect==true then
local fusion_operation_code=FusionSpell.GetOperationCodeByMaterialLocation(material:GetLocation(),mat_operation_code_map) local fusion_operation_code=FusionSpell.GetOperationCodeByMaterialLocation(material:GetLocation(),mat_operation_code_map)
fusion_operation=FusionSpell.GetFusionOperationByCode(fusion_operation_code) fusion_operation=FusionSpell.GetFusionOperationByCode(fusion_operation_code)
materials_from_spell_card:AddCard(material)
else else
-- extra material effects -- extra material effects
--- pay the operation cost, only valid in 影牢の呪縛 as of 2025 May --- pay the operation cost, only valid in 影牢の呪縛 as of 2025 May
...@@ -2644,6 +2651,7 @@ function FusionSpell.GetSummonOperation( ...@@ -2644,6 +2651,7 @@ function FusionSpell.GetSummonOperation(
local fusion_operation=FusionSpell.GetFusionOperationByCode(fusion_operation_code) local fusion_operation=FusionSpell.GetFusionOperationByCode(fusion_operation_code)
material_grouped_by_op[fusion_operation]=material_grouped_by_op[fusion_operation] or Group.CreateGroup() material_grouped_by_op[fusion_operation]=material_grouped_by_op[fusion_operation] or Group.CreateGroup()
material_grouped_by_op[fusion_operation]:AddCard(material) material_grouped_by_op[fusion_operation]:AddCard(material)
materials_from_spell_card:AddCard(material)
end end
end end
if #materials_to_apply>0 then if #materials_to_apply>0 then
...@@ -2687,13 +2695,13 @@ function FusionSpell.GetSummonOperation( ...@@ -2687,13 +2695,13 @@ function FusionSpell.GetSummonOperation(
fusion_effect:Reset() fusion_effect:Reset()
end end
end end
end
stage_x_operation(e,tc,tp,FusionSpell.STAGE_BEFORE_SUMMON_COMPLETE) stage_x_operation(e,tc,tp,FusionSpell.STAGE_BEFORE_SUMMON_COMPLETE,materials_from_spell_card,materials)
Duel.SpecialSummonComplete() Duel.SpecialSummonComplete()
stage_x_operation(e,tc,tp,FusionSpell.STAGE_BEFORE_PROCEDURE_COMPLETE) stage_x_operation(e,tc,tp,FusionSpell.STAGE_BEFORE_PROCEDURE_COMPLETE,materials_from_spell_card,materials)
tc:CompleteProcedure() tc:CompleteProcedure()
stage_x_operation(e,tc,tp,FusionSpell.STAGE_AT_SUMMON_OPERATION_FINISH) stage_x_operation(e,tc,tp,FusionSpell.STAGE_AT_SUMMON_OPERATION_FINISH,materials_from_spell_card,materials)
end
end end
stage_x_operation(e,tc,tp,FusionSpell.STAGE_AT_ALL_OPERATION_FINISH) stage_x_operation(e,tc,tp,FusionSpell.STAGE_AT_ALL_OPERATION_FINISH)
end end
...@@ -2794,21 +2802,23 @@ end ...@@ -2794,21 +2802,23 @@ end
---@param pre_select_mat_location integer|function location where to find the materials before known the materials (default LOCATION_HAND|LOCATION_MZONE) ---@param pre_select_mat_location integer|function location where to find the materials before known the materials (default LOCATION_HAND|LOCATION_MZONE)
---@param pre_select_mat_opponent_location integer|FUSION_SPELL_PRE_SELECT_MAT_LOCATION_FUNCTION location where to find the materials before known the materials on opponent location ---@param pre_select_mat_opponent_location integer|FUSION_SPELL_PRE_SELECT_MAT_LOCATION_FUNCTION location where to find the materials before known the materials on opponent location
---@param gc fun(e:Effect):Card|nil ---@param gc fun(e:Effect):Card|nil
function FusionSpell.SummonTargetFilter(c,fusfilter,matfilter,e,tp,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,sumtype,sumpos,pre_select_mat_opponent_location,gc) function FusionSpell.SummonTargetFilter(c,fusfilter,matfilter,e,tp,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,additional_fgoalcheck,sumtype,sumpos,pre_select_mat_opponent_location,gc)
local res=c:IsType(TYPE_FUSION) and fusfilter(c,tp) and c:IsCanBeSpecialSummoned(e,sumtype,tp,false,false,sumpos) local res=c:IsType(TYPE_FUSION) and fusfilter(c,tp) and c:IsCanBeSpecialSummoned(e,sumtype,tp,false,false,sumpos)
if res==false then if res==false then
return false return false
end end
local mg=FusionSpell.GetMaterialsGroupForTargetCard(c,tp,e,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,sumtype,pre_select_mat_opponent_location) local mg=FusionSpell.GetMaterialsGroupForTargetCard(c,tp,e,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,sumtype,pre_select_mat_opponent_location)
aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunction(additional_fcheck,tp,c,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location) aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunction(additional_fcheck,tp,c,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location)
aux.FGoalCheckAdditional=FusionSpell.GetFusionSpellFGoalCheckAdditionalFunction(additional_fgoalcheck,tp,c,pre_select_mat_location)
res=c:CheckFusionMaterial(mg,gc(e),tp) res=c:CheckFusionMaterial(mg,gc(e),tp)
aux.FCheckAdditional=nil aux.FCheckAdditional=nil
aux.FGoalCheckAdditional=nil
return res return res
end end
---@return {[Effect]:Group} effect_targets_map Return a map of different chain material to potiential fusion targets ---@return {[Effect]:Group} effect_targets_map Return a map of different chain material to potiential fusion targets
---@param gc fun(e:Effect):Card|nil ---@param gc fun(e:Effect):Card|nil
function FusionSpell.ListChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,fuslocation,sumtype,sumpos,gc) function FusionSpell.ListChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,additional_fgoalcheck,fuslocation,sumtype,sumpos,gc)
local chain_material_effects={Duel.IsPlayerAffectedByEffect(tp,EFFECT_CHAIN_MATERIAL)} local chain_material_effects={Duel.IsPlayerAffectedByEffect(tp,EFFECT_CHAIN_MATERIAL)}
---@type {[Effect]:Group} ---@type {[Effect]:Group}
local chain_material_targets={} local chain_material_targets={}
...@@ -2820,7 +2830,7 @@ function FusionSpell.ListChainMaterialSummonTargets(e,tp,fusfilter,additional_fc ...@@ -2820,7 +2830,7 @@ function FusionSpell.ListChainMaterialSummonTargets(e,tp,fusfilter,additional_fc
local ce_fusfilter=ce:GetValue() local ce_fusfilter=ce:GetValue()
local ce_sg=Duel.GetMatchingGroup(FusionSpell.ChainMaterialSummonTargetFilter,tp,fuslocation,0,nil, local ce_sg=Duel.GetMatchingGroup(FusionSpell.ChainMaterialSummonTargetFilter,tp,fuslocation,0,nil,
---FusionSpell.ChainMaterialSummonTargetFilter params ---FusionSpell.ChainMaterialSummonTargetFilter params
aux.AND(ce_fusfilter,fusfilter or aux.TRUE),e,tp,chain_mg,additional_fcheck,sumtype,sumpos,gc) aux.AND(ce_fusfilter,fusfilter or aux.TRUE),e,tp,chain_mg,additional_fcheck,additional_fgoalcheck,sumtype,sumpos,gc)
if #ce_sg>0 then if #ce_sg>0 then
chain_material_targets[ce]=ce_sg chain_material_targets[ce]=ce_sg
end end
...@@ -2831,7 +2841,7 @@ end ...@@ -2831,7 +2841,7 @@ end
---@return boolean res return whether there is a valid target for any chain material effect ---@return boolean res return whether there is a valid target for any chain material effect
---@param gc fun(e:Effect):Card|nil ---@param gc fun(e:Effect):Card|nil
function FusionSpell.IsExistsChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,fuslocation,sumtype,sumpos,gc) function FusionSpell.IsExistsChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,additional_fgoalcheck,fuslocation,sumtype,sumpos,gc)
local chain_material_effects={Duel.IsPlayerAffectedByEffect(tp,EFFECT_CHAIN_MATERIAL)} local chain_material_effects={Duel.IsPlayerAffectedByEffect(tp,EFFECT_CHAIN_MATERIAL)}
---@type {[Effect]:Group} ---@type {[Effect]:Group}
for _,ce in ipairs(chain_material_effects) do for _,ce in ipairs(chain_material_effects) do
...@@ -2842,7 +2852,7 @@ function FusionSpell.IsExistsChainMaterialSummonTargets(e,tp,fusfilter,additiona ...@@ -2842,7 +2852,7 @@ function FusionSpell.IsExistsChainMaterialSummonTargets(e,tp,fusfilter,additiona
local ce_fusfilter=ce:GetValue() local ce_fusfilter=ce:GetValue()
local res=Duel.IsExistingMatchingCard(FusionSpell.ChainMaterialSummonTargetFilter,tp,fuslocation,0,1,nil, local res=Duel.IsExistingMatchingCard(FusionSpell.ChainMaterialSummonTargetFilter,tp,fuslocation,0,1,nil,
---FusionSpell.ChainMaterialSummonTargetFilter params ---FusionSpell.ChainMaterialSummonTargetFilter params
aux.AND(ce_fusfilter,fusfilter or aux.TRUE),e,tp,chain_mg,additional_fcheck,sumtype,sumpos,gc) aux.AND(ce_fusfilter,fusfilter or aux.TRUE),e,tp,chain_mg,additional_fcheck,additional_fgoalcheck,sumtype,sumpos,gc)
if res==true then if res==true then
return res return res
end end
...@@ -2854,14 +2864,16 @@ end ...@@ -2854,14 +2864,16 @@ end
---@param c Card ---@param c Card
---@param gc fun(e:Effect):Card|nil ---@param gc fun(e:Effect):Card|nil
---@return boolean result Whether c could be fusion summoned by this chain material effect ---@return boolean result Whether c could be fusion summoned by this chain material effect
function FusionSpell.ChainMaterialSummonTargetFilter(c,fusfilter,e,tp,mg,additional_fcheck,sumtype,sumpos,gc) function FusionSpell.ChainMaterialSummonTargetFilter(c,fusfilter,e,tp,mg,additional_fcheck,additional_fgoalcheck,sumtype,sumpos,gc)
local res=c:IsType(TYPE_FUSION) and (not fusfilter or fusfilter(c,tp)) and c:IsCanBeSpecialSummoned(e,sumtype,tp,false,false,sumpos) local res=c:IsType(TYPE_FUSION) and (not fusfilter or fusfilter(c,tp)) and c:IsCanBeSpecialSummoned(e,sumtype,tp,false,false,sumpos)
if res==false then if res==false then
return false return false
end end
aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunctionForChainMaterial(additional_fcheck) aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunctionForChainMaterial(additional_fcheck)
aux.FGoalCheckAdditional=FusionSpell.GetFusionSpellFGoalCheckAdditionalFunctionForChainMaterial(additional_fgoalcheck)
res=c:CheckFusionMaterial(mg,gc(e),tp) res=c:CheckFusionMaterial(mg,gc(e),tp)
aux.FCheckAdditional=nil aux.FCheckAdditional=nil
aux.FGoalCheckAdditional=nil
return res return res
end end
...@@ -3099,8 +3111,8 @@ end ...@@ -3099,8 +3111,8 @@ end
--- filter out materials that does not necessary come from fusion spell and pass to the gcheck of fusion spell --- filter out materials that does not necessary come from fusion spell and pass to the gcheck of fusion spell
--- for each extra material effect, check the maximuim size is not exceeded. --- for each extra material effect, check the maximuim size is not exceeded.
--As of 2025 May, if a material could be used as extra material, it must be able to be used as fusion spell material. The code below is based on this assumption. --- As of 2025 May, if a material could (but not forced) be used as extra material, it must be able to be used as fusion spell material. The code below is based on this assumption.
-- If we have Aiラブ融合 + 影牢の呪縛 or 多層融合 + アマゾネスの秘術 in same archetype, is code would fail in some scenario. --- If we have Aiラブ融合 + 影牢の呪縛 or 多層融合 + アマゾネスの秘術 in same archetype, is code would fail in some scenario.
---@param fusion_spell_additional_fcheck_function FUSION_FGCHECK_FUNCTION ---@param fusion_spell_additional_fcheck_function FUSION_FGCHECK_FUNCTION
---@param tp integer ---@param tp integer
---@param tc Card ---@param tc Card
...@@ -3130,7 +3142,7 @@ function FusionSpell.GetFusionSpellFCheckAdditionalFunction(fusion_spell_additio ...@@ -3130,7 +3142,7 @@ function FusionSpell.GetFusionSpellFCheckAdditionalFunction(fusion_spell_additio
for extra_material_effect,materials in pairs(material_grouped_by_extra_material_effect) do for extra_material_effect,materials in pairs(material_grouped_by_extra_material_effect) do
local labels={extra_material_effect:GetLabel()} local labels={extra_material_effect:GetLabel()}
--- first element of label is the material count limit --- first element of label is the material count limit
if labels~=nil and #labels>0 and #materials>labels[1] then if labels~=nil and #labels>0 and labels[1]>0 and #materials>labels[1] then
return false return false
end end
end end
...@@ -3140,10 +3152,32 @@ function FusionSpell.GetFusionSpellFCheckAdditionalFunction(fusion_spell_additio ...@@ -3140,10 +3152,32 @@ function FusionSpell.GetFusionSpellFCheckAdditionalFunction(fusion_spell_additio
end) end)
end end
--- all material must come from chain material, only pass all material group to the gcheck of fusion spell
--- filter out materials that does not necessary come from fusion spell and pass to the gcheck of fusion spell
---@param fusion_spell_additional_fgoalcheck_function FUSION_FGCHECK_FUNCTION
---@param tp integer
---@param tc Card
---@param pre_select_mat_location integer|function location where to find the materials before known the materials (default LOCATION_HAND|LOCATION_MZONE)
function FusionSpell.GetFusionSpellFGoalCheckAdditionalFunction(fusion_spell_additional_fgoalcheck_function,tp,tc,pre_select_mat_location)
---@param mg Group
return (function(f_tp,mg,fc)
local extra_mg=mg:Filter(FusionSpell.GetExtraMaterialEffect,nil,tp,tc,pre_select_mat_location)
return fusion_spell_additional_fgoalcheck_function(f_tp,mg-extra_mg,fc,mg)
end)
end
--- all material must come from chain material, only pass all material group to the fcheck of fusion spell
--- @param fusion_spell_additional_fcheck_function FUSION_FGCHECK_FUNCTION --- @param fusion_spell_additional_fcheck_function FUSION_FGCHECK_FUNCTION
function FusionSpell.GetFusionSpellFCheckAdditionalFunctionForChainMaterial(fusion_spell_additional_fcheck_function) function FusionSpell.GetFusionSpellFCheckAdditionalFunctionForChainMaterial(fusion_spell_additional_fcheck_function)
return (function(f_tp,mg,fc) return (function(f_tp,mg,fc)
return fusion_spell_additional_fcheck_function(f_tp,Group.CreateGroup(),fc,mg) return fusion_spell_additional_fcheck_function(f_tp,Group.CreateGroup(),fc,mg)
end) end)
end end
--- all material must come from chain material, only pass all material group to the gcheck of fusion spell
--- @param fusion_spell_additional_fgoalcheck_function FUSION_FGCHECK_FUNCTION
function FusionSpell.GetFusionSpellFGoalCheckAdditionalFunctionForChainMaterial(fusion_spell_additional_fgoalcheck_function)
return (function(f_tp,mg,fc)
return fusion_spell_additional_fgoalcheck_function(f_tp,Group.CreateGroup(),fc,mg)
end)
end
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