Commit fe91dab7 authored by Vury Leo's avatar Vury Leo Committed by wind2009

Add 幻影融合 to new fusion + add fusion_spell_matfilter to FusionSpell opts + add...

Add 幻影融合 to new fusion + add fusion_spell_matfilter to FusionSpell opts + add LOCATION to 捕食植物トリアンティス
parent a5706fb3
...@@ -11,7 +11,7 @@ function s.initial_effect(c) ...@@ -11,7 +11,7 @@ function s.initial_effect(c)
e1:SetRange(LOCATION_PZONE) e1:SetRange(LOCATION_PZONE)
e1:SetTargetRange(LOCATION_PZONE,0) e1:SetTargetRange(LOCATION_PZONE,0)
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|LOCATION_MZONE 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(0,LOCATION_MZONE) --- only avaliable when pre_select_mat_location contains LOCATION_MZONE, 1st number is limitaion of count materials, set 0 as infinity 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)
......
--幻影融合 --幻影融合
function c57425061.initial_effect(c) local s,id,o=GetID()
function s.initial_effect(c)
--Activate --Activate
local e1=Effect.CreateEffect(c) local e1=FusionSpell.CreateSummonEffect(c,{
e1:SetCategory(CATEGORY_REMOVE+CATEGORY_SPECIAL_SUMMON+CATEGORY_FUSION_SUMMON) fusfilter=s.fusfilter,
e1:SetType(EFFECT_TYPE_ACTIVATE) pre_select_mat_location=LOCATION_HAND|LOCATION_MZONE|LOCATION_SZONE,
e1:SetCode(EVENT_FREE_CHAIN) fusion_spell_matfilter=s.fusion_spell_matfilter,
e1:SetCountLimit(1,57425061+EFFECT_COUNT_CODE_OATH) mat_operation_code_map={
e1:SetTarget(c57425061.target) { [LOCATION_SZONE]=FusionSpell.FUSION_OPERATION_BANISH },
e1:SetOperation(c57425061.activate) { [0xff]=FusionSpell.FUSION_OPERATION_GRAVE }
}
})
e1:SetCountLimit(1,id+EFFECT_COUNT_CODE_OATH)
c:RegisterEffect(e1) c:RegisterEffect(e1)
end end
function c57425061.cfilter(c)
return c:IsFaceup() and c:GetSequence()<5 function s.fusfilter(c)
and c:IsType(TYPE_TRAP) and c:IsType(TYPE_CONTINUOUS) and c:GetOriginalType()&TYPE_MONSTER==TYPE_MONSTER return c:IsSetCard(0x8)
end end
function c57425061.filter1(c,e)
return c:IsAbleToGrave() and not c:IsImmuneToEffect(e) function s.fusion_spell_matfilter(c)
end if c:IsLocation(LOCATION_SZONE) and not c:IsAllTypes(TYPE_CONTINUOUS|TYPE_TRAP) then
function c57425061.exfilter0(c) return false
return c57425061.cfilter(c) and c:IsCanBeFusionMaterial() and c:IsAbleToRemove()
end
function c57425061.exfilter1(c,e)
return c57425061.cfilter(c) and c:IsCanBeFusionMaterial() and c:IsAbleToRemove() and not c:IsImmuneToEffect(e)
end
function c57425061.filter2(c,e,tp,m,f,chkf)
return c:IsType(TYPE_FUSION) and c:IsSetCard(0x8) and (not f or f(c))
and c:IsCanBeSpecialSummoned(e,SUMMON_TYPE_FUSION,tp,false,false) and c:CheckFusionMaterial(m,nil,chkf)
end
function c57425061.fcheck(tp,sg,fc)
return sg:FilterCount(Card.IsLocation,nil,LOCATION_SZONE)<=2
end
function c57425061.gcheck(sg)
return sg:FilterCount(Card.IsLocation,nil,LOCATION_SZONE)<=2
end
function c57425061.target(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then
local chkf=tp
local mg1=Duel.GetFusionMaterial(tp):Filter(Card.IsAbleToGrave,nil)
if Duel.IsExistingMatchingCard(c57425061.cfilter,tp,LOCATION_SZONE,0,1,nil) then
local sg=Duel.GetMatchingGroup(c57425061.exfilter0,tp,LOCATION_SZONE,0,nil)
if sg:GetCount()>0 then
mg1:Merge(sg)
aux.FCheckAdditional=c57425061.fcheck
aux.GCheckAdditional=c57425061.gcheck
end
end
local res=Duel.IsExistingMatchingCard(c57425061.filter2,tp,LOCATION_EXTRA,0,1,nil,e,tp,mg1,nil,chkf)
aux.FCheckAdditional=nil
aux.GCheckAdditional=nil
if not res then
local ce=Duel.GetChainMaterial(tp)
if ce~=nil then
local fgroup=ce:GetTarget()
local mg2=fgroup(ce,e,tp)
local mf=ce:GetValue()
res=Duel.IsExistingMatchingCard(c57425061.filter2,tp,LOCATION_EXTRA,0,1,nil,e,tp,mg2,mf,chkf)
end end
end return true
return res
end
Duel.SetOperationInfo(0,CATEGORY_SPECIAL_SUMMON,nil,1,tp,LOCATION_EXTRA)
end end
function c57425061.activate(e,tp,eg,ep,ev,re,r,rp)
local chkf=tp --- @type FUSION_FGCHECK_FUNCTION
local mg1=Duel.GetFusionMaterial(tp):Filter(c57425061.filter1,nil,e) function s.fcheck(tp,mg,fc,mg_all)
local exmat=false local mg_szone=mg:Filter(function(c) return c:IsLocation(LOCATION_SZONE) end,nil)
if Duel.IsExistingMatchingCard(c57425061.cfilter,tp,LOCATION_SZONE,0,1,nil) then --- no more than 2
local sg=Duel.GetMatchingGroup(c57425061.exfilter1,tp,LOCATION_SZONE,0,nil,e) if #mg_szone>2 then
if sg:GetCount()>0 then return false
mg1:Merge(sg)
exmat=true
end
end
if exmat then
aux.FCheckAdditional=c57425061.fcheck
aux.GCheckAdditional=c57425061.gcheck
end
local sg1=Duel.GetMatchingGroup(c57425061.filter2,tp,LOCATION_EXTRA,0,nil,e,tp,mg1,nil,chkf)
aux.FCheckAdditional=nil
aux.GCheckAdditional=nil
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(c57425061.filter2,tp,LOCATION_EXTRA,0,nil,e,tp,mg2,mf,chkf)
end
if sg1:GetCount()>0 or (sg2~=nil and sg2:GetCount()>0) then
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()
mg1:RemoveCard(tc)
if sg1:IsContains(tc) and (sg2==nil or not sg2:IsContains(tc) or not Duel.SelectYesNo(tp,ce:GetDescription())) then
if exmat then
aux.FCheckAdditional=c57425061.fcheck
aux.GCheckAdditional=c57425061.gcheck
end
local mat1=Duel.SelectFusionMaterial(tp,tc,mg1,nil,chkf)
aux.FCheckAdditional=nil
aux.GCheckAdditional=nil
tc:SetMaterial(mat1)
local rg=mat1:Filter(Card.IsLocation,nil,LOCATION_SZONE)
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.SpecialSummon(tc,SUMMON_TYPE_FUSION,tp,tp,false,false,POS_FACEUP)
else
local mat2=Duel.SelectFusionMaterial(tp,tc,mg2,nil,chkf)
local fop=ce:GetOperation()
fop(ce,e,tp,tc,mat2)
end
tc:CompleteProcedure()
end end
return true
end end
...@@ -2267,13 +2267,13 @@ FusionSpell = {} ...@@ -2267,13 +2267,13 @@ FusionSpell = {}
--- @class FusionEffectParams --- @class FusionEffectParams
--- @field fusfilter? fun(c:Card):boolean --- @field fusfilter? fun(c:Card):boolean
--- Optional filter to restrict which Fusion Monsters can be summoned. --- Optional filter to restrict which Fusion Monsters can be summoned.
--- @field matfilter? fun(c:Card):boolean
--- Optional filter for valid Fusion Materials. --- Optional filter for valid Fusion Materials.
--- Use only under strong constraints (e.g., D-Fusion effects). --- Use only under strong constraints (e.g., D-Fusion effects).
--- @field pre_select_mat_location? integer|fun():integer --- If some card can not be used even under Chain Material or EXTRA_FUSION_MATERIAL, use this filter.
--- @field matfilter? fun(c:Card):boolean
--- Location(s) to look for materials before knowing which ones will be used. --- Location(s) to look for materials before knowing which ones will be used.
--- Defaults to `LOCATION_HAND | LOCATION_MZONE`. --- Defaults to `LOCATION_HAND | LOCATION_MZONE`.
--- @field mat_operation_code_map? {[integer]:FUSION_OPERATION_CODE}[] --- @field pre_select_mat_location? integer|fun():integer
--- List of operations to perform on materials based on location. --- List of operations to perform on materials based on location.
--- Defaults to: --- Defaults to:
--- ```lua --- ```lua
...@@ -2282,28 +2282,33 @@ FusionSpell = {} ...@@ -2282,28 +2282,33 @@ FusionSpell = {}
--- { [0xff] = FusionSpell.FUSION_OPERATION_GRAVE } --- { [0xff] = FusionSpell.FUSION_OPERATION_GRAVE }
--- } --- }
--- ``` --- ```
--- @field post_select_mat_location? integer --- @field mat_operation_code_map? {[integer]:FUSION_OPERATION_CODE}[]
--- 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 post_select_mat_location? integer
--- Optional quick check to validate the selected material group. --- Optional quick check to validate the selected material group.
--- @field additional_fgoalcheck? FUSION_FGCHECK_FUNCTION --- @field additional_fcheck? FUSION_FGCHECK_FUNCTION
--- Optional final check to validate the selected material group. --- Optional final check to validate the selected material group.
--- @field fuslocation? integer --- @field additional_fgoalcheck? FUSION_FGCHECK_FUNCTION
--- 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 fuslocation? integer
--- The summon type to perform. Defaults to `SUMMON_TYPE_FUSION`. --- The summon type to perform. Defaults to `SUMMON_TYPE_FUSION`.
--- @field sumpos? integer --- @field sumtype? integer
--- The position to summon the monster in. Defaults to `POS_FACEUP`. --- The position to summon the monster in. Defaults to `POS_FACEUP`.
--- @field stage_x_operation? FUSION_SPELL_STAGE_X_CALLBACK_FUNCTION --- @field sumpos? integer
--- Optional callback executed at key stages of the summon process. --- Optional callback executed at key stages of the summon process.
--- Example stage: `FusionSpell.STAGE_BEFORE_SUMMON_COMPLETE`. --- Example stage: `FusionSpell.STAGE_BEFORE_SUMMON_COMPLETE`.
--- @field extra_target? fun(e:Effect, tp:integer, eg:Group, ep:integer, ev:integer, re:Effect, r:integer, rp:integer, chk:integer):nil --- @field stage_x_operation? FUSION_SPELL_STAGE_X_CALLBACK_FUNCTION
--- Optional extra targeting logic (e.g., to show hints or manage chains). --- Optional extra targeting logic (e.g., to show hints or manage chains).
--- @field pre_select_mat_opponent_location? integer|fun():integer --- @field extra_target? fun(e:Effect, tp:integer, eg:Group, ep:integer, ev:integer, re:Effect, r:integer, rp:integer, chk:integer):nil
--- Opponent-side locations to search for materials before they are selected. --- Opponent-side locations to search for materials before they are selected.
--- @field gc? fun(e:Effect):Card|nil --- @field pre_select_mat_opponent_location? integer|fun():integer
--- Function that returns a card that must be included in the fusion materials --- Function that returns a card that must be included in the fusion materials
--- @field gc? fun(e:Effect):Card|nil
--- Function that material must pass to be legal as material come from fusion spell
--- Use under weak constraints (e.g., Vision Fusion).
--- If some card can not be used by fusion spell, but could be used with EXTRA_FUSION_MATERIAL, use this filter.
--- Fusion with Chain Material will never call this function, as no material comes from fusion spell.
--- @field fusion_spell_matfilter? fun(c:Card):boolean
--- Add LOCATION_EXTRA and opponent mzone to EFFECT_EXTRA_FUSION_MATERIAL list, remove once core updated --- Add LOCATION_EXTRA and opponent mzone to EFFECT_EXTRA_FUSION_MATERIAL list, remove once core updated
...@@ -2380,6 +2385,7 @@ function FusionSpell.CreateSummonEffect(c,opts) ...@@ -2380,6 +2385,7 @@ function FusionSpell.CreateSummonEffect(c,opts)
local extra_target=opts.extra_target or aux.TRUE local extra_target=opts.extra_target or aux.TRUE
local pre_select_mat_opponent_location=opts.pre_select_mat_opponent_location or 0 local pre_select_mat_opponent_location=opts.pre_select_mat_opponent_location or 0
local gc=opts.gc or function() return nil end local gc=opts.gc or function() return nil end
local fusion_spell_matfilter=opts.fusion_spell_matfilter or aux.TRUE
-- Ensure material operation fallbacks are present -- Ensure material operation fallbacks are present
table.insert(mat_operation_code_map,{ [LOCATION_GRAVE] = FusionSpell.FUSION_OPERATION_BANISH }) table.insert(mat_operation_code_map,{ [LOCATION_GRAVE] = FusionSpell.FUSION_OPERATION_BANISH })
...@@ -2403,7 +2409,8 @@ function FusionSpell.CreateSummonEffect(c,opts) ...@@ -2403,7 +2409,8 @@ function FusionSpell.CreateSummonEffect(c,opts)
sumpos, sumpos,
extra_target, extra_target,
pre_select_mat_opponent_location, pre_select_mat_opponent_location,
gc gc,
fusion_spell_matfilter
)) ))
e1:SetOperation(FusionSpell.GetSummonOperation( e1:SetOperation(FusionSpell.GetSummonOperation(
fusfilter, fusfilter,
...@@ -2418,7 +2425,8 @@ function FusionSpell.CreateSummonEffect(c,opts) ...@@ -2418,7 +2425,8 @@ function FusionSpell.CreateSummonEffect(c,opts)
sumpos, sumpos,
stage_x_operation, stage_x_operation,
pre_select_mat_opponent_location, pre_select_mat_opponent_location,
gc gc,
fusion_spell_matfilter
)) ))
e1:SetDescription(1169) --- 融合召喚 e1:SetDescription(1169) --- 融合召喚
return e1 return e1
...@@ -2437,6 +2445,7 @@ end ...@@ -2437,6 +2445,7 @@ end
---@param extra_target fun(e:Effect, tp:integer, eg:Group, ep:integer, ev:integer, re:Effect, r:integer, rp:integer, chk:integer):nil extra target function to add opration info etc ---@param extra_target fun(e:Effect, tp:integer, eg:Group, ep:integer, ev:integer, re:Effect, r:integer, rp:integer, chk:integer):nil extra target function to add opration info etc
---@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 Function that returns a card that must be included in the fusion materials ---@param gc fun(e:Effect):Card|nil Function that returns a card that must be included in the fusion materials
---@param fusion_spell_matfilter fun(c:Card):boolean a material must pass this to be legal as material come from fusion spell
function FusionSpell.GetSummonTarget( function FusionSpell.GetSummonTarget(
fusfilter, fusfilter,
matfilter, matfilter,
...@@ -2450,17 +2459,32 @@ function FusionSpell.GetSummonTarget( ...@@ -2450,17 +2459,32 @@ function FusionSpell.GetSummonTarget(
sumpos, sumpos,
extra_target, extra_target,
pre_select_mat_opponent_location, pre_select_mat_opponent_location,
gc gc,
fusion_spell_matfilter
) )
return function(e,tp,eg,ep,ev,re,r,rp,chk) return function(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then if chk==0 then
if extra_target(e,tp,eg,ep,ev,re,r,rp,chk)==false then if extra_target(e,tp,eg,ep,ev,re,r,rp,chk)==false then
return false return false
end end
local sg=Duel.IsExistingMatchingCard( local sg=Duel.IsExistingMatchingCard(function(c)
FusionSpell.SummonTargetFilter,tp,fuslocation,0,1,nil, return FusionSpell.SummonTargetFilter(
--- FusionSpell.SummonTargetFilter param 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) fusfilter,
aux.NecroValleyFilter(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,
fusion_spell_matfilter)
end,
tp,fuslocation,0,1,nil)
if sg==true then if sg==true then
return true return true
end end
...@@ -2491,6 +2515,7 @@ end ...@@ -2491,6 +2515,7 @@ end
---@param stage_x_operation function callback function when special summon is in progress. will be called with different stage name ---@param stage_x_operation function callback function when special summon is in progress. will be called with different stage name
---@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 Function that returns a card that must be included in the fusion materials ---@param gc fun(e:Effect):Card|nil Function that returns a card that must be included in the fusion materials
---@param fusion_spell_matfilter fun(c:Card):boolean a material must pass this to be legal as material come from fusion spell
function FusionSpell.GetSummonOperation( function FusionSpell.GetSummonOperation(
fusfilter, fusfilter,
matfilter, matfilter,
...@@ -2504,16 +2529,31 @@ function FusionSpell.GetSummonOperation( ...@@ -2504,16 +2529,31 @@ function FusionSpell.GetSummonOperation(
sumpos, sumpos,
stage_x_operation, stage_x_operation,
pre_select_mat_opponent_location, pre_select_mat_opponent_location,
gc gc,
fusion_spell_matfilter
) )
return function(e,tp,eg,ep,ev,re,r,rp) return function(e,tp,eg,ep,ev,re,r,rp)
-- if gc is gone, terminate -- if gc is gone, terminate
if gc(e)==nil or gc(e):IsRelateToEffect(e) then if gc(e)==nil or gc(e):IsRelateToEffect(e) then
local fusion_targets=Group.CreateGroup() local fusion_targets=Group.CreateGroup()
local sg=Duel.GetMatchingGroup( local sg=Duel.GetMatchingGroup(function(c)
FusionSpell.SummonTargetFilter,tp,fuslocation,0,nil, return FusionSpell.SummonTargetFilter(
--- FusionSpell.SummonTargetFilter param c,
fusfilter,aux.NecroValleyFilter(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) fusfilter,
aux.NecroValleyFilter(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,
fusion_spell_matfilter)
end,
tp,fuslocation,0,nil)
fusion_targets:Merge(sg) fusion_targets:Merge(sg)
--- check for chain material targets --- check for chain material targets
local ce_sgs={} local ce_sgs={}
...@@ -2563,8 +2603,9 @@ function FusionSpell.GetSummonOperation( ...@@ -2563,8 +2603,9 @@ function FusionSpell.GetSummonOperation(
mat_operation_code_map, mat_operation_code_map,
post_select_mat_location, post_select_mat_location,
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) fusion_spell_matfilter)
aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunction(additional_fcheck,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location,fusion_spell_matfilter)
aux.FGoalCheckAdditional=FusionSpell.GetFusionSpellFGoalCheckAdditionalFunction(additional_fgoalcheck,tp,tc,pre_select_mat_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
...@@ -2596,11 +2637,11 @@ function FusionSpell.GetSummonOperation( ...@@ -2596,11 +2637,11 @@ function FusionSpell.GetSummonOperation(
---@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,fusion_spell_matfilter))==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.
local fusion_operation=nil local fusion_operation=nil
local material_effect=FusionSpell.GetMaterialEffects(material,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location)[1] local material_effect=FusionSpell.GetMaterialEffects(material,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location,fusion_spell_matfilter)[1]
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)
...@@ -2622,7 +2663,7 @@ function FusionSpell.GetSummonOperation( ...@@ -2622,7 +2663,7 @@ function FusionSpell.GetSummonOperation(
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)
end end
local materials_with_two_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))==2 end,nil) local materials_with_two_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,fusion_spell_matfilter))==2 end,nil)
assert(#materials_with_one_material_effect+#materials_with_two_material_effect==#materials, "We can not have one material have zero/3+ material effect yet") assert(#materials_with_one_material_effect+#materials_with_two_material_effect==#materials, "We can not have one material have zero/3+ material effect yet")
--For material that can be material by multiple effect, ask user which to apply. --For material that can be material by multiple effect, ask user which to apply.
--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 be used as extra material, it must be able to be used as fusion spell material. The code below is based on this assumption.
...@@ -2752,6 +2793,7 @@ end ...@@ -2752,6 +2793,7 @@ end
---@param matfilter fun(c:Card):boolean filter for the materials, use it only under very strong limitation like D-Fusion. ---@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 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_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 fusion_spell_matfilter fun(c:Card,tp:integer):boolean a material must pass this to be legal as material come from fusion spell
function FusionSpell.GetMaterialsGroupForTargetCard( function FusionSpell.GetMaterialsGroupForTargetCard(
tc, tc,
tp, tp,
...@@ -2761,7 +2803,8 @@ function FusionSpell.GetMaterialsGroupForTargetCard( ...@@ -2761,7 +2803,8 @@ function FusionSpell.GetMaterialsGroupForTargetCard(
mat_operation_code_map, mat_operation_code_map,
post_select_mat_location, post_select_mat_location,
sumtype, sumtype,
pre_select_mat_opponent_location pre_select_mat_opponent_location,
fusion_spell_matfilter
) )
local all_locations=FusionSpell.GetAllLocationsForTargetCard(tc,tp,pre_select_mat_location,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) local mg=FusionSpell.GetFusionMaterial(tp,all_locations)
...@@ -2787,6 +2830,14 @@ function FusionSpell.GetMaterialsGroupForTargetCard( ...@@ -2787,6 +2830,14 @@ function FusionSpell.GetMaterialsGroupForTargetCard(
--mg=mg:Filter(Card.IsCanBeFusionMaterial,nil,tc,sumtype) --mg=mg:Filter(Card.IsCanBeFusionMaterial,nil,tc,sumtype)
--- workaround until core fixes --- workaround until core fixes
mg=mg:Filter(function(mc) return FusionSpell.IsCanBeFusionMaterial(mc,tc,sumtype) end,nil) mg=mg:Filter(function(mc) return FusionSpell.IsCanBeFusionMaterial(mc,tc,sumtype) end,nil)
--- a material must come from at least one source, either from fusion spell or EXTRA_FUSION_MATERIAL
mg=mg:Filter(function(mc)
local effects=FusionSpell.GetMaterialEffects(mc,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location,fusion_spell_matfilter)
if #effects<1 then
return false
end
return true
end,nil)
--- in order to be qualified for being material, it need to be able to perform the operation. --- in order to be qualified for being material, it need to be able to perform the operation.
--- @param mc Card --- @param mc Card
mg=mg:Filter(function(mc) mg=mg:Filter(function(mc)
...@@ -2831,13 +2882,14 @@ end ...@@ -2831,13 +2882,14 @@ 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,additional_fgoalcheck,sumtype,sumpos,pre_select_mat_opponent_location,gc) ---@param fusion_spell_matfilter fun(c:Card):boolean a material must pass this to be legal as material come from fusion spell
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,fusion_spell_matfilter)
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,fusion_spell_matfilter)
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,fusion_spell_matfilter)
aux.FGoalCheckAdditional=FusionSpell.GetFusionSpellFGoalCheckAdditionalFunction(additional_fgoalcheck,tp,c,pre_select_mat_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
...@@ -2917,7 +2969,10 @@ FusionSpell.STAGE_AT_ALL_OPERATION_FINISH=4 ...@@ -2917,7 +2969,10 @@ FusionSpell.STAGE_AT_ALL_OPERATION_FINISH=4
-- operation that would be applied on the material -- operation that would be applied on the material
---@alias FUSION_OPERATION_CODE integer ---@alias FUSION_OPERATION_CODE integer
FusionSpell.FUSION_OPERATION_INHERIT=0x10000 -- used only on EFFECT_EXTRA_FUSION_MATERIAL effects, inherits the operation of fusion spell --- used only on EFFECT_EXTRA_FUSION_MATERIAL effects, inherits the operation of fusion spell, use FusionSpell.FUSION_OPERATION_INHERIT|LOCATION to tell the desired location to inherit.
--- if location is not specified, use the material location.
--- E.g. for 捕食植物トリアンティス, it should be FUSION_OPERATION_INHERIT|LOCATION_MZONE.
FusionSpell.FUSION_OPERATION_INHERIT=0x10000
FusionSpell.FUSION_OPERATION_GRAVE=0x1 FusionSpell.FUSION_OPERATION_GRAVE=0x1
FusionSpell.FUSION_OPERATION_BANISH=0x2 FusionSpell.FUSION_OPERATION_BANISH=0x2
FusionSpell.FUSION_OPERATION_BANISH_FACEDOWN=0x3 FusionSpell.FUSION_OPERATION_BANISH_FACEDOWN=0x3
...@@ -2939,7 +2994,11 @@ function FusionSpell.GetFusionOperationByCode(code,matlocation,fusion_spell_oper ...@@ -2939,7 +2994,11 @@ function FusionSpell.GetFusionOperationByCode(code,matlocation,fusion_spell_oper
return FusionSpell.SendDeckBottomMaterial return FusionSpell.SendDeckBottomMaterial
elseif code==FusionSpell.FUSION_OPERATION_DESTROY then elseif code==FusionSpell.FUSION_OPERATION_DESTROY then
return FusionSpell.DestroyMaterial return FusionSpell.DestroyMaterial
elseif code==FusionSpell.FUSION_OPERATION_INHERIT then elseif code&FusionSpell.FUSION_OPERATION_INHERIT==FusionSpell.FUSION_OPERATION_INHERIT then
local inhreit_as=code&(~FusionSpell.FUSION_OPERATION_INHERIT)&0xff --- 0xff is LOCATION_ALL
if inhreit_as~=0 then
matlocation=inhreit_as
end
if matlocation==nil or fusion_spell_operation_code_map==nil then if matlocation==nil or fusion_spell_operation_code_map==nil then
-- we are in trouble -- we are in trouble
assert(false, "we have a material that inhreits, but no operation to inhreit from") assert(false, "we have a material that inhreits, but no operation to inhreit from")
...@@ -2947,6 +3006,8 @@ function FusionSpell.GetFusionOperationByCode(code,matlocation,fusion_spell_oper ...@@ -2947,6 +3006,8 @@ function FusionSpell.GetFusionOperationByCode(code,matlocation,fusion_spell_oper
end end
return FusionSpell.GetFusionOperationByCode(FusionSpell.GetOperationCodeByMaterialLocation(matlocation,fusion_spell_operation_code_map)) return FusionSpell.GetFusionOperationByCode(FusionSpell.GetOperationCodeByMaterialLocation(matlocation,fusion_spell_operation_code_map))
end end
assert(false, string.format("we have an unknown fusion operation code %d",code))
return FusionSpell.GraveMaterial
end end
---@return FUSION_FILTER_FUNCTION ---@return FUSION_FILTER_FUNCTION
...@@ -2963,7 +3024,11 @@ function FusionSpell.GetFusionFilterByCode(code,matlocation,fusion_spell_operati ...@@ -2963,7 +3024,11 @@ function FusionSpell.GetFusionFilterByCode(code,matlocation,fusion_spell_operati
return FusionSpell.SendDeckBottomMaterialFilter return FusionSpell.SendDeckBottomMaterialFilter
elseif code==FusionSpell.FUSION_OPERATION_DESTROY then elseif code==FusionSpell.FUSION_OPERATION_DESTROY then
return FusionSpell.DestroyMaterialFilter return FusionSpell.DestroyMaterialFilter
elseif code==FusionSpell.FUSION_OPERATION_INHERIT then elseif code&FusionSpell.FUSION_OPERATION_INHERIT==FusionSpell.FUSION_OPERATION_INHERIT then
local inhreit_as=code&(~FusionSpell.FUSION_OPERATION_INHERIT)&0xff --- 0xff is LOCATION_ALL
if inhreit_as~=0 then
matlocation=inhreit_as
end
if matlocation==nil or fusion_spell_operation_code_map==nil then if matlocation==nil or fusion_spell_operation_code_map==nil then
-- we are in trouble -- we are in trouble
assert(false, "we have a material that inhreits, but no operation to inhreit from") assert(false, "we have a material that inhreits, but no operation to inhreit from")
...@@ -2971,6 +3036,8 @@ function FusionSpell.GetFusionFilterByCode(code,matlocation,fusion_spell_operati ...@@ -2971,6 +3036,8 @@ function FusionSpell.GetFusionFilterByCode(code,matlocation,fusion_spell_operati
end end
return FusionSpell.GetFusionFilterByCode(FusionSpell.GetOperationCodeByMaterialLocation(matlocation,fusion_spell_operation_code_map)) return FusionSpell.GetFusionFilterByCode(FusionSpell.GetOperationCodeByMaterialLocation(matlocation,fusion_spell_operation_code_map))
end end
assert(false, string.format("we have an unknown fusion operation code %d",code))
return FusionSpell.GraveMaterialFilter
end end
---@alias FUSION_OPERATION_FUNCTION fun(sg:Card|Group,tp:integer):integer ---@alias FUSION_OPERATION_FUNCTION fun(sg:Card|Group,tp:integer):integer
...@@ -3041,8 +3108,9 @@ end ...@@ -3041,8 +3108,9 @@ end
--if element is true, stands for it can be included by the fusion effect itself. --if element is true, stands for it can be included by the fusion effect itself.
---@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 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 fusion_spell_matfilter fun(c:Card):boolean a material must pass this to be legal as material come from fusion spell
---@return (true|Effect)[] ---@return (true|Effect)[]
function FusionSpell.GetMaterialEffects(c,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location) function FusionSpell.GetMaterialEffects(c,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location,fusion_spell_matfilter)
local res={} local res={}
local calculated_mat_opponent_location=0 local calculated_mat_opponent_location=0
if type(pre_select_mat_opponent_location)=="function" then if type(pre_select_mat_opponent_location)=="function" then
...@@ -3051,9 +3119,9 @@ function FusionSpell.GetMaterialEffects(c,tp,tc,pre_select_mat_location,post_sel ...@@ -3051,9 +3119,9 @@ function FusionSpell.GetMaterialEffects(c,tp,tc,pre_select_mat_location,post_sel
calculated_mat_opponent_location=pre_select_mat_opponent_location calculated_mat_opponent_location=pre_select_mat_opponent_location
end end
local all_locations=FusionSpell.GetAllLocationsForTargetCard(tc,tp,pre_select_mat_location,post_select_mat_location) local all_locations=FusionSpell.GetAllLocationsForTargetCard(tc,tp,pre_select_mat_location,post_select_mat_location)
if c:IsControler(tp) and c:IsLocation(all_locations) then if c:IsControler(tp) and c:IsLocation(all_locations) and fusion_spell_matfilter(c) then
table.insert(res,true) table.insert(res,true)
elseif c:IsControler(1-tp) and c:IsLocation(calculated_mat_opponent_location) then elseif c:IsControler(1-tp) and c:IsLocation(calculated_mat_opponent_location) and fusion_spell_matfilter(c) then
table.insert(res,true) table.insert(res,true)
end end
local extra_effs={c:IsHasEffect(EFFECT_EXTRA_FUSION_MATERIAL)} local extra_effs={c:IsHasEffect(EFFECT_EXTRA_FUSION_MATERIAL)}
...@@ -3149,12 +3217,13 @@ end ...@@ -3149,12 +3217,13 @@ 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 post_select_mat_location integer? ---@param post_select_mat_location integer?
---@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
function FusionSpell.GetFusionSpellFCheckAdditionalFunction(fusion_spell_additional_fcheck_function,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location) ---@param fusion_spell_matfilter fun(c:Card):boolean a material must pass this to be legal as material come from fusion spell
function FusionSpell.GetFusionSpellFCheckAdditionalFunction(fusion_spell_additional_fcheck_function,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location,fusion_spell_matfilter)
---@param mg Group ---@param mg Group
return (function(f_tp,mg,fc) return (function(f_tp,mg,fc)
--- filter out materials that can only be added by extra material effects, and check the count limit --- filter out materials that can only be added by extra material effects, and check the count limit
local mandartory_extra_mg=mg:Filter(function (mc) local mandartory_extra_mg=mg:Filter(function (mc)
local material_effects=FusionSpell.GetMaterialEffects(mc,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location) local material_effects=FusionSpell.GetMaterialEffects(mc,tp,tc,pre_select_mat_location,post_select_mat_location,pre_select_mat_opponent_location,fusion_spell_matfilter)
if (#material_effects)==1 and material_effects[1]~=true then if (#material_effects)==1 and material_effects[1]~=true then
return true return true
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