Commit a4a308f3 authored by wind2009's avatar wind2009

Merge branch 'new-fusion-Vision-Fusion' into 'master'

Add 幻影融合 to new fusion + add fusion_spell_matfilter to FusionSpell opts + add LOCATION to 捕食植物トリアンティス

See merge request !15
parents a5706fb3 fe91dab7
......@@ -11,7 +11,7 @@ function s.initial_effect(c)
e1:SetRange(LOCATION_PZONE)
e1:SetTargetRange(LOCATION_PZONE,0)
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.
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)
......
--幻影融合
function c57425061.initial_effect(c)
local s,id,o=GetID()
function s.initial_effect(c)
--Activate
local e1=Effect.CreateEffect(c)
e1:SetCategory(CATEGORY_REMOVE+CATEGORY_SPECIAL_SUMMON+CATEGORY_FUSION_SUMMON)
e1:SetType(EFFECT_TYPE_ACTIVATE)
e1:SetCode(EVENT_FREE_CHAIN)
e1:SetCountLimit(1,57425061+EFFECT_COUNT_CODE_OATH)
e1:SetTarget(c57425061.target)
e1:SetOperation(c57425061.activate)
local e1=FusionSpell.CreateSummonEffect(c,{
fusfilter=s.fusfilter,
pre_select_mat_location=LOCATION_HAND|LOCATION_MZONE|LOCATION_SZONE,
fusion_spell_matfilter=s.fusion_spell_matfilter,
mat_operation_code_map={
{ [LOCATION_SZONE]=FusionSpell.FUSION_OPERATION_BANISH },
{ [0xff]=FusionSpell.FUSION_OPERATION_GRAVE }
}
})
e1:SetCountLimit(1,id+EFFECT_COUNT_CODE_OATH)
c:RegisterEffect(e1)
end
function c57425061.cfilter(c)
return c:IsFaceup() and c:GetSequence()<5
and c:IsType(TYPE_TRAP) and c:IsType(TYPE_CONTINUOUS) and c:GetOriginalType()&TYPE_MONSTER==TYPE_MONSTER
function s.fusfilter(c)
return c:IsSetCard(0x8)
end
function c57425061.filter1(c,e)
return c:IsAbleToGrave() and not c:IsImmuneToEffect(e)
end
function c57425061.exfilter0(c)
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)
function s.fusion_spell_matfilter(c)
if c:IsLocation(LOCATION_SZONE) and not c:IsAllTypes(TYPE_CONTINUOUS|TYPE_TRAP) then
return false
end
end
return res
end
Duel.SetOperationInfo(0,CATEGORY_SPECIAL_SUMMON,nil,1,tp,LOCATION_EXTRA)
return true
end
function c57425061.activate(e,tp,eg,ep,ev,re,r,rp)
local chkf=tp
local mg1=Duel.GetFusionMaterial(tp):Filter(c57425061.filter1,nil,e)
local exmat=false
if Duel.IsExistingMatchingCard(c57425061.cfilter,tp,LOCATION_SZONE,0,1,nil) then
local sg=Duel.GetMatchingGroup(c57425061.exfilter1,tp,LOCATION_SZONE,0,nil,e)
if sg:GetCount()>0 then
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()
--- @type FUSION_FGCHECK_FUNCTION
function s.fcheck(tp,mg,fc,mg_all)
local mg_szone=mg:Filter(function(c) return c:IsLocation(LOCATION_SZONE) end,nil)
--- no more than 2
if #mg_szone>2 then
return false
end
return true
end
......@@ -2267,13 +2267,13 @@ FusionSpell = {}
--- @class FusionEffectParams
--- @field fusfilter? fun(c:Card):boolean
--- Optional filter to restrict which Fusion Monsters can be summoned.
--- @field matfilter? fun(c:Card):boolean
--- Optional filter for valid Fusion Materials.
--- 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.
--- 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.
--- Defaults to:
--- ```lua
......@@ -2282,28 +2282,33 @@ FusionSpell = {}
--- { [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.
--- @field additional_fcheck? FUSION_FGCHECK_FUNCTION
--- @field post_select_mat_location? integer
--- 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.
--- @field fuslocation? integer
--- @field additional_fgoalcheck? FUSION_FGCHECK_FUNCTION
--- 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`.
--- @field sumpos? integer
--- @field sumtype? integer
--- 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.
--- 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).
--- @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.
--- @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
--- @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
......@@ -2380,6 +2385,7 @@ function FusionSpell.CreateSummonEffect(c,opts)
local extra_target=opts.extra_target or aux.TRUE
local pre_select_mat_opponent_location=opts.pre_select_mat_opponent_location or 0
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
table.insert(mat_operation_code_map,{ [LOCATION_GRAVE] = FusionSpell.FUSION_OPERATION_BANISH })
......@@ -2403,7 +2409,8 @@ function FusionSpell.CreateSummonEffect(c,opts)
sumpos,
extra_target,
pre_select_mat_opponent_location,
gc
gc,
fusion_spell_matfilter
))
e1:SetOperation(FusionSpell.GetSummonOperation(
fusfilter,
......@@ -2418,7 +2425,8 @@ function FusionSpell.CreateSummonEffect(c,opts)
sumpos,
stage_x_operation,
pre_select_mat_opponent_location,
gc
gc,
fusion_spell_matfilter
))
e1:SetDescription(1169) --- 融合召喚
return e1
......@@ -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 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 fusion_spell_matfilter fun(c:Card):boolean a material must pass this to be legal as material come from fusion spell
function FusionSpell.GetSummonTarget(
fusfilter,
matfilter,
......@@ -2450,17 +2459,32 @@ function FusionSpell.GetSummonTarget(
sumpos,
extra_target,
pre_select_mat_opponent_location,
gc
gc,
fusion_spell_matfilter
)
return function(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then
if extra_target(e,tp,eg,ep,ev,re,r,rp,chk)==false then
return false
end
local sg=Duel.IsExistingMatchingCard(
FusionSpell.SummonTargetFilter,tp,fuslocation,0,1,nil,
--- FusionSpell.SummonTargetFilter param
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 sg=Duel.IsExistingMatchingCard(function(c)
return FusionSpell.SummonTargetFilter(
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,
fusion_spell_matfilter)
end,
tp,fuslocation,0,1,nil)
if sg==true then
return true
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 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 fusion_spell_matfilter fun(c:Card):boolean a material must pass this to be legal as material come from fusion spell
function FusionSpell.GetSummonOperation(
fusfilter,
matfilter,
......@@ -2504,16 +2529,31 @@ function FusionSpell.GetSummonOperation(
sumpos,
stage_x_operation,
pre_select_mat_opponent_location,
gc
gc,
fusion_spell_matfilter
)
return function(e,tp,eg,ep,ev,re,r,rp)
-- if gc is gone, terminate
if gc(e)==nil or gc(e):IsRelateToEffect(e) then
local fusion_targets=Group.CreateGroup()
local sg=Duel.GetMatchingGroup(
FusionSpell.SummonTargetFilter,tp,fuslocation,0,nil,
--- FusionSpell.SummonTargetFilter param
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)
local sg=Duel.GetMatchingGroup(function(c)
return FusionSpell.SummonTargetFilter(
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,
fusion_spell_matfilter)
end,
tp,fuslocation,0,nil)
fusion_targets:Merge(sg)
--- check for chain material targets
local ce_sgs={}
......@@ -2563,8 +2603,9 @@ function FusionSpell.GetSummonOperation(
mat_operation_code_map,
post_select_mat_location,
sumtype,
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)
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)
materials=Duel.SelectFusionMaterial(tp,tc,mg,gc(e),tp)
aux.FCheckAdditional=nil
......@@ -2596,11 +2637,11 @@ function FusionSpell.GetSummonOperation(
---@type {[FUSION_OPERATION_FUNCTION]:Group}
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 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 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
local fusion_operation_code=FusionSpell.GetOperationCodeByMaterialLocation(material:GetLocation(),mat_operation_code_map)
......@@ -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]:AddCard(material)
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")
--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.
......@@ -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 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 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(
tc,
tp,
......@@ -2761,7 +2803,8 @@ function FusionSpell.GetMaterialsGroupForTargetCard(
mat_operation_code_map,
post_select_mat_location,
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 mg=FusionSpell.GetFusionMaterial(tp,all_locations)
......@@ -2787,6 +2830,14 @@ function FusionSpell.GetMaterialsGroupForTargetCard(
--mg=mg:Filter(Card.IsCanBeFusionMaterial,nil,tc,sumtype)
--- workaround until core fixes
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.
--- @param mc Card
mg=mg:Filter(function(mc)
......@@ -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_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 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)
if res==false then
return false
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)
aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunction(additional_fcheck,tp,c,pre_select_mat_location,post_select_mat_location,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,fusion_spell_matfilter)
aux.FGoalCheckAdditional=FusionSpell.GetFusionSpellFGoalCheckAdditionalFunction(additional_fgoalcheck,tp,c,pre_select_mat_location)
res=c:CheckFusionMaterial(mg,gc(e),tp)
aux.FCheckAdditional=nil
......@@ -2917,7 +2969,10 @@ FusionSpell.STAGE_AT_ALL_OPERATION_FINISH=4
-- 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
--- 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_BANISH=0x2
FusionSpell.FUSION_OPERATION_BANISH_FACEDOWN=0x3
......@@ -2939,7 +2994,11 @@ function FusionSpell.GetFusionOperationByCode(code,matlocation,fusion_spell_oper
return FusionSpell.SendDeckBottomMaterial
elseif code==FusionSpell.FUSION_OPERATION_DESTROY then
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
-- we are in trouble
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
end
return FusionSpell.GetFusionOperationByCode(FusionSpell.GetOperationCodeByMaterialLocation(matlocation,fusion_spell_operation_code_map))
end
assert(false, string.format("we have an unknown fusion operation code %d",code))
return FusionSpell.GraveMaterial
end
---@return FUSION_FILTER_FUNCTION
......@@ -2963,7 +3024,11 @@ function FusionSpell.GetFusionFilterByCode(code,matlocation,fusion_spell_operati
return FusionSpell.SendDeckBottomMaterialFilter
elseif code==FusionSpell.FUSION_OPERATION_DESTROY then
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
-- we are in trouble
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
end
return FusionSpell.GetFusionFilterByCode(FusionSpell.GetOperationCodeByMaterialLocation(matlocation,fusion_spell_operation_code_map))
end
assert(false, string.format("we have an unknown fusion operation code %d",code))
return FusionSpell.GraveMaterialFilter
end
---@alias FUSION_OPERATION_FUNCTION fun(sg:Card|Group,tp:integer):integer
......@@ -3041,8 +3108,9 @@ end
--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_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)[]
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 calculated_mat_opponent_location=0
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
calculated_mat_opponent_location=pre_select_mat_opponent_location
end
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)
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)
end
local extra_effs={c:IsHasEffect(EFFECT_EXTRA_FUSION_MATERIAL)}
......@@ -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 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
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
return (function(f_tp,mg,fc)
--- 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 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
return true
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