Commit ab526506 authored by Vury Leo's avatar Vury Leo

add support for chain material

parent dc1d0a9d
--チェーン・マテリアル
local s,id,o=GetID()
function s.initial_effect(c)
--Activate
local e1=Effect.CreateEffect(c)
e1:SetType(EFFECT_TYPE_ACTIVATE)
e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET)
e1:SetCode(EVENT_FREE_CHAIN)
e1:SetCost(s.cost)
e1:SetTarget(s.target)
e1:SetOperation(s.activate)
c:RegisterEffect(e1)
end
function s.cost(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then return Duel.GetActivityCount(tp,ACTIVITY_ATTACK)==0 end
local e1=Effect.CreateEffect(e:GetHandler())
e1:SetType(EFFECT_TYPE_FIELD)
e1:SetCode(EFFECT_CANNOT_ATTACK)
e1:SetProperty(EFFECT_FLAG_OATH+EFFECT_FLAG_IGNORE_IMMUNE)
e1:SetTargetRange(LOCATION_MZONE,0)
e1:SetReset(RESET_PHASE+PHASE_END)
Duel.RegisterEffect(e1,tp)
end
function s.target(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then return e:IsHasType(EFFECT_TYPE_ACTIVATE) end
end
function s.activate(e,tp,eg,ep,ev,re,r,rp)
local e1=Effect.CreateEffect(e:GetHandler())
e1:SetDescription(aux.Stringid(id,0))
e1:SetType(EFFECT_TYPE_FIELD)
e1:SetCode(EFFECT_CHAIN_MATERIAL)
e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET)
e1:SetTargetRange(1,0)
e1:SetReset(RESET_PHASE+PHASE_END)
e1:SetTarget(s.chain_target)
e1:SetOperation(s.chain_operation)
e1:SetValue(aux.TRUE)
Duel.RegisterEffect(e1,tp)
end
function s.filter(c,e)
return c:IsType(TYPE_MONSTER) and c:IsCanBeFusionMaterial() and c:IsAbleToRemove() and not c:IsImmuneToEffect(e)
end
function s.chain_target(e,te,tp)
return Duel.GetMatchingGroup(s.filter,tp,LOCATION_ONFIELD+LOCATION_GRAVE+LOCATION_HAND+LOCATION_DECK,0,nil,te)
end
function s.chain_operation(e,te,tp,tc,mat,sumtype,sumpos)
if not sumtype then sumtype=SUMMON_TYPE_FUSION end
tc:SetMaterial(mat)
Duel.Remove(mat,POS_FACEUP,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION)
Duel.BreakEffect()
Duel.SpecialSummonStep(tc,sumtype,tp,tp,false,false,sumpos)
tc:RegisterFlagEffect(id,RESET_EVENT+RESETS_STANDARD-RESET_TURN_SET,0,1)
local e1=Effect.CreateEffect(e:GetHandler())
e1:SetType(EFFECT_TYPE_FIELD+EFFECT_TYPE_CONTINUOUS)
e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
e1:SetCode(EVENT_PHASE+PHASE_END)
e1:SetLabelObject(tc)
e1:SetCondition(s.descon)
e1:SetOperation(s.desop)
e1:SetCountLimit(1)
Duel.RegisterEffect(e1,tp)
end
function s.descon(e,tp,eg,ep,ev,re,r,rp)
local tc=e:GetLabelObject()
if tc:GetFlagEffect(id)~=0 then
return true
else
e:Reset()
return false
end
end
function s.desop(e,tp,eg,ep,ev,re,r,rp)
local tc=e:GetLabelObject()
Duel.Destroy(tc,REASON_EFFECT)
end
\ No newline at end of file
--サイバネティック・フュージョン・サポート
local s,id,o=GetID()
function s.initial_effect(c)
--Activate
local e1=Effect.CreateEffect(c)
e1:SetType(EFFECT_TYPE_ACTIVATE)
e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET)
e1:SetCode(EVENT_FREE_CHAIN)
e1:SetCountLimit(1,id+EFFECT_COUNT_CODE_OATH)
e1:SetCost(s.cost)
e1:SetOperation(s.activate)
c:RegisterEffect(e1)
end
function s.cost(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then return true end
Duel.PayLPCost(tp,math.floor(Duel.GetLP(tp)/2))
end
function s.activate(e,tp,eg,ep,ev,re,r,rp)
local e1=Effect.CreateEffect(e:GetHandler())
e1:SetDescription(aux.Stringid(id,0))
e1:SetType(EFFECT_TYPE_FIELD)
e1:SetCode(EFFECT_CHAIN_MATERIAL)
e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET)
e1:SetTargetRange(1,0)
e1:SetReset(RESET_PHASE+PHASE_END)
e1:SetTarget(s.chain_target)
e1:SetOperation(s.chain_operation)
e1:SetValue(aux.FilterBoolFunction(Card.IsRace,RACE_MACHINE))
Duel.RegisterEffect(e1,tp)
end
function s.filter(c,e)
return c:IsType(TYPE_MONSTER) and c:IsCanBeFusionMaterial() and c:IsAbleToRemove() and not c:IsImmuneToEffect(e)
end
function s.chain_target(e,te,tp)
return Duel.GetMatchingGroup(s.filter,tp,LOCATION_MZONE+LOCATION_GRAVE+LOCATION_HAND,0,nil,te)
end
function s.chain_operation(e,te,tp,tc,mat,sumtype,sumpos)
if not sumtype then sumtype=SUMMON_TYPE_FUSION end
tc:SetMaterial(mat)
Duel.Remove(mat,POS_FACEUP,REASON_EFFECT+REASON_MATERIAL+REASON_FUSION)
Duel.BreakEffect()
Duel.SpecialSummonStep(tc,sumtype,tp,tp,false,false,sumpos)
e:Reset()
end
\ No newline at end of file
......@@ -13,7 +13,7 @@ function s.fusfilter(c)
return c:IsSetCard(0xdf)
end
---@type FUSION_SPELL_PRE_SELECT_MAT_LOCATION_FUNCTION
---@type FUSION_SPELL_PRE_SELECT_MAT_LOCATION_FUNCTION
function s.pre_select_mat_location(tc,tp)
local res=LOCATION_HAND|LOCATION_ONFIELD
if Duel.IsExistingMatchingCard(s.cfilter,tp,0,LOCATION_MZONE,1,nil) then
......
......@@ -2034,7 +2034,8 @@ end
---@param sumtype integer? summon type (default SUMMON_TYPE_FUSION)
---@param sumpos integer? summon position (default POS_FACEUP)
---@param stage_x_operation function? callback function when special summon is in progress. will be called with different stage name
function FusionSpell.CreateSummonEffect(c,fusfilter,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,additional_gcheck,fuslocation,sumtype,sumpos,stage_x_operation)
---@param extra_target function? extra target function to add opration info etc
function FusionSpell.CreateSummonEffect(c,fusfilter,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,additional_gcheck,fuslocation,sumtype,sumpos,stage_x_operation,extra_target)
matfilter=matfilter or aux.TRUE
pre_select_mat_location=pre_select_mat_location or LOCATION_HAND|LOCATION_ONFIELD
mat_operation_code_map=mat_operation_code_map or {}
......@@ -2066,20 +2067,27 @@ end
---@param fuslocation integer? location where to summon fusion monsters from (default LOCATION_EXTRA), use it on Clock Lizard
---@param sumtype integer? summon type
---@param sumpos integer? summon position
function FusionSpell.GetSummonTarget(fusfilter,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,additional_gcheck,fuslocation,sumtype,sumpos)
---@param extra_target function? extra target function to add opration info etc
function FusionSpell.GetSummonTarget(fusfilter,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,additional_gcheck,fuslocation,sumtype,sumpos,extra_target)
return function(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then
local sg=Duel.GetMatchingGroup(FusionSpell.SummonTargetFilter,tp,fuslocation,0,nil,fusfilter,matfilter,e,tp,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,sumtype,sumpos)
local sg=Duel.IsExistingMatchingCard(FusionSpell.SummonTargetFilter,tp,fuslocation,0,1,nil,fusfilter,matfilter,e,tp,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,sumtype,sumpos)
if sg==true then
return true
end
-- --- check for chain material targets
-- if sumtype&SUMMON_TYPE_FUSION~=0 then
-- local ce_sg=FusionSpell.ListChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,sumtype,sumpos)
-- if #ce_sg>0 then
-- sg:Merge(ce_sg)
-- end
-- end
return #sg>0
if sumtype&SUMMON_TYPE_FUSION~=0 then
local ce_sg=FusionSpell.IsExistsChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,fuslocation,sumtype,sumpos)
if ce_sg==true then
return true
end
end
return false
end
Duel.SetOperationInfo(0,CATEGORY_SPECIAL_SUMMON,nil,1,tp,fuslocation)
if extra_target~=nil then
extra_target()
end
end
end
......@@ -2099,13 +2107,19 @@ function FusionSpell.GetSummonOperation(fusfilter,matfilter,pre_select_mat_locat
local sg=Duel.GetMatchingGroup(FusionSpell.SummonTargetFilter,tp,fuslocation,0,nil,fusfilter,matfilter,e,tp,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,sumtype,sumpos)
--- check for chain material targets
local ce_sg={}
-- if sumtype&SUMMON_TYPE_FUSION~=0 then
-- local ce_sgs=FusionSpell.ListChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,sumtype,sumpos)
-- end
local ce_sgs={}
local can_chain_material=false
if sumtype&SUMMON_TYPE_FUSION~=0 then
ce_sgs=FusionSpell.ListChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,fuslocation,sumtype,sumpos)
--- if there's any chain material effect has valid target
for _ in pairs(ce_sgs) do
can_chain_material=true
break
end
end
local tc=nil
if #sg>0 or #ce_sgs>0 then
if #sg>0 or can_chain_material==true then
local materials=Group.CreateGroup()
local fusion_effect=nil
......@@ -2113,9 +2127,9 @@ function FusionSpell.GetSummonOperation(fusfilter,matfilter,pre_select_mat_locat
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON)
---@type Group
local fusion_targets=sg:Clone()
-- for _, ce_sg in pairs(ce_sgs) do
-- fusion_targets:Merge(ce_sg)
-- end
for _, ce_sg in pairs(ce_sgs) do
fusion_targets:Merge(ce_sg)
end
tc=fusion_targets:Select(tp,1,1,nil):GetFirst()
......@@ -2124,11 +2138,11 @@ function FusionSpell.GetSummonOperation(fusfilter,matfilter,pre_select_mat_locat
if sg:IsContains(tc) then
table.insert(avaliable_fusion_effect,e)
end
-- for ce, ce_sg in pairs(ce_sgs) do
-- if ce_sg:IsContains(tc) then
-- table.insert(avaliable_fusion_effect,ce)
-- end
-- end
for ce, ce_sg in pairs(ce_sgs) do
if ce_sg:IsContains(tc) then
table.insert(avaliable_fusion_effect,ce)
end
end
assert(#avaliable_fusion_effect>0, "Selected a target card that has 0 fusion effect")
fusion_effect=avaliable_fusion_effect[1]
if #avaliable_fusion_effect>1 then
......@@ -2143,16 +2157,16 @@ function FusionSpell.GetSummonOperation(fusfilter,matfilter,pre_select_mat_locat
materials=Duel.SelectFusionMaterial(tp,tc,mg,nil,tp)
aux.FCheckAdditional=nil
else
-- --- use chain material effect
-- ---@type function
-- local chain_material_filter=ce:GetTarget()
-- local chain_mg=chain_material_filter(ce,e,tp)
-- assert(#chain_mg>0, "we are trying to apply a chain material, but it has no possible material")
-- if additional_fcheck~=nil then
-- aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunctionForChainMaterial(additional_fcheck,tp,c)
-- end
-- materials=Duel.SelectFusionMaterial(tp,tc,chain_mg)
-- aux.FCheckAdditional=nil
--- use chain material effect
---@type function
local chain_material_filter=fusion_effect:GetTarget()
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")
if additional_fcheck~=nil then
aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunctionForChainMaterial(additional_fcheck,tp,c)
end
materials=Duel.SelectFusionMaterial(tp,tc,chain_mg)
aux.FCheckAdditional=nil
end
end
......@@ -2215,8 +2229,8 @@ function FusionSpell.GetSummonOperation(fusfilter,matfilter,pre_select_mat_locat
Duel.BreakEffect()
Duel.SpecialSummonStep(tc,SUMMON_TYPE_FUSION,tp,tp,false,false,sumpos)
else
-- --- fusion with chain material
-- fusion_effect:GetOperation()(e,e,tp,tc,materials,sumtype,sumpos)
--- fusion with chain material
fusion_effect:GetOperation()(e,e,tp,tc,materials,sumtype,sumpos)
end
end
......@@ -2299,19 +2313,22 @@ end
---@param matfilter fun(c:Card,tp:integer):boolean
---@param pre_select_mat_location integer|function location where to find the materials before known the materials (default LOCATION_HAND|LOCATION_MZONE)
function FusionSpell.SummonTargetFilter(c,fusfilter,matfilter,e,tp,pre_select_mat_location,mat_operation_code_map,post_select_mat_location,additional_fcheck,sumtype,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
return false
end
local mg=FusionSpell.GetMaterialsGroupForTargetCard(c,tp,e,matfilter,pre_select_mat_location,mat_operation_code_map,post_select_mat_location)
Debug.Message(string.format("%d materials for %d",#mg,c:GetCode()))
if additional_fcheck~=nil then
aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunction(additional_fcheck,tp,c)
end
local res=c:IsType(TYPE_FUSION) and (not fusfilter or fusfilter(c,tp)) and c:IsCanBeSpecialSummoned(e,sumtype,tp,false,false,sumpos) and c:CheckFusionMaterial(mg,nil,tp)
res=c:CheckFusionMaterial(mg,nil,tp)
aux.FCheckAdditional=nil
return res
end
---@return {[Effect]:Group} effect_targets_map Return a map of different chain material to potiential fusion targets
function FusionSpell.ListChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,sumtype,sumpos)
local chain_material_effects={Duel.GetPlayerEffect(tp,EFFECT_CHAIN_MATERIAL)}
function FusionSpell.ListChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,fuslocation,sumtype,sumpos)
local chain_material_effects={Duel.IsPlayerAffectedByEffect(tp,EFFECT_CHAIN_MATERIAL)}
---@type {[Effect]:Group}
local chain_material_targets={}
for _,ce in ipairs(chain_material_effects) do
......@@ -2320,7 +2337,7 @@ function FusionSpell.ListChainMaterialSummonTargets(e,tp,fusfilter,additional_fc
local chain_mg=chain_material_filter(ce,e,tp)
if #chain_mg>0 then
local ce_fusfilter=ce:GetValue()
local ce_sg=Duel.GetMatchingGroup(FusionSpell.ChainMaterialSummonTargetFilter,tp,fuslocation,0,nil,aux.AND(ce_fusfilter,fusfilter or aux.TRUE),e,tp,chain_mg,additional_fcheck,sumtype,sumpos)
local ce_sg=Duel.GetMatchingGroup(FusionSpell.ChainMaterialSummonTargetFilter,tp,fuslocation,0,nil,aux.AND(ce_fusfilter,fusfilter or aux.TRUE),e,tp,chain_mg,additional_fcheck,sumtype,sumpos)
if #ce_sg>0 then
chain_material_targets[ce]=ce_sg
end
......@@ -2329,11 +2346,35 @@ function FusionSpell.ListChainMaterialSummonTargets(e,tp,fusfilter,additional_fc
return chain_material_targets
end
---@return boolean res return whether there is a valid target for any chain material effect
function FusionSpell.IsExistsChainMaterialSummonTargets(e,tp,fusfilter,additional_fcheck,fuslocation,sumtype,sumpos)
local chain_material_effects={Duel.IsPlayerAffectedByEffect(tp,EFFECT_CHAIN_MATERIAL)}
---@type {[Effect]:Group}
for _,ce in ipairs(chain_material_effects) do
---@type function
local chain_material_filter=ce:GetTarget()
local chain_mg=chain_material_filter(ce,e,tp)
if #chain_mg>0 then
local ce_fusfilter=ce:GetValue()
local res=Duel.IsExistingMatchingCard(FusionSpell.ChainMaterialSummonTargetFilter,tp,fuslocation,0,1,nil,aux.AND(ce_fusfilter,fusfilter or aux.TRUE),e,tp,chain_mg,additional_fcheck,sumtype,sumpos)
if res==true then
return res
end
end
end
return false
end
---@param c Card
function FusionSpell.ChainMaterialSummonTargetFilter(c,fusfilter,e,tp,mg,additional_fcheck,sumtype,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
return false
end
if additional_fcheck~=nil then
aux.FCheckAdditional=FusionSpell.GetFusionSpellFCheckAdditionalFunctionForChainMaterial(additional_fcheck)
end
local res=c:IsType(TYPE_FUSION) and (not fusfilter or fusfilter(c,tp)) and c:IsCanBeSpecialSummoned(e,sumtype,tp,false,false,sumpos) and c:CheckFusionMaterial(mg,nil,tp)
res=c:CheckFusionMaterial(mg,nil,tp)
aux.FCheckAdditional=nil
return res
end
......@@ -2522,7 +2563,7 @@ end
-- when a material has multiple effect make it could be material, ask for which to apply.
---@return true|Effect
function FusionSpell.MultiMaterialEffectPrompt(effects,tp,e)
local ops= {}
local ops={}
for i,eff in ipairs(effects) do
if eff==true then
-- this can be used as default material
......@@ -2540,14 +2581,14 @@ end
function FusionSpell.GetFusionSpellFCheckAdditionalFunction(fusion_spell_additional_fcheck_function,tp,tc)
return (function(f_tp,mg,fc)
local extra_mg=mg:Filter(FusionSpell.GetExtraMaterialEffect,nil,tp,tc)
return fusion_spell_additional_fcheck_function(f_tp,mg-extra_mg,fc,sg)
return fusion_spell_additional_fcheck_function(f_tp,mg-extra_mg,fc,mg)
end)
end
--- all material must come from chain material, only pass all and pass to the gcheck of fusion spell
--- @param fusion_spell_additional_fcheck_function FUSION_FCHECK_FUNCTION
function FusionSpell.GetFusionSpellFCheckAdditionalFunctionForChainMaterial(fusion_spell_additional_fcheck_function)
function FusionSpell.GetFusionSpellFCheckAdditionalFunctionForChainMaterial(fusion_spell_additional_fcheck_function,tp,c)
return (function(f_tp,mg,fc)
return fusion_spell_additional_fcheck_function(f_tp,Group.CreateGroup(),fc,sg)
return fusion_spell_additional_fcheck_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