Commit 786ef25f authored by Vury Leo's avatar Vury Leo

Add ガーディアン・キマイラ

parent 81a1b411
--ガーディアン・キマイラ
function c11321089.initial_effect(c)
local s,id,o=GetID()
function s.initial_effect(c)
aux.AddCodeList(c,24094653)
c:EnableReviveLimit()
aux.AddFusionProcFunRep(c,c11321089.ffilter,3,false)
Fusion.AddFusionProcedure(c,{
slots={
Fusion.Slot.Group({
min=3,
max=3,
unique_by=function(mc) return { mc:GetCode(),mc:GetFusionCode() } end,
})
},
mat_filter=s.mat_filter,
fgoalcheck=s.fgoalcheck,
})
--material limit
local e0=Effect.CreateEffect(c)
e0:SetType(EFFECT_TYPE_SINGLE)
e0:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE)
e0:SetCode(EFFECT_MATERIAL_LIMIT)
e0:SetValue(c11321089.matlimit)
e0:SetValue(s.matlimit)
c:RegisterEffect(e0)
--spsummon condition
local e1=Effect.CreateEffect(c)
e1:SetType(EFFECT_TYPE_SINGLE)
e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE)
e1:SetCode(EFFECT_SPSUMMON_CONDITION)
e1:SetValue(c11321089.splimit)
e1:SetValue(s.splimit)
c:RegisterEffect(e1)
--draw
local e2=Effect.CreateEffect(c)
e2:SetDescription(aux.Stringid(11321089,0))
e2:SetDescription(aux.Stringid(id,0))
e2:SetCategory(CATEGORY_DRAW+CATEGORY_DESTROY)
e2:SetType(EFFECT_TYPE_SINGLE+EFFECT_TYPE_TRIGGER_O)
e2:SetCode(EVENT_SPSUMMON_SUCCESS)
e2:SetProperty(EFFECT_FLAG_DELAY)
e2:SetCountLimit(1,11321089)
e2:SetCondition(c11321089.drcon)
e2:SetTarget(c11321089.drtg)
e2:SetOperation(c11321089.drop)
e2:SetCountLimit(1,id)
e2:SetCondition(s.drcon)
e2:SetTarget(s.drtg)
e2:SetOperation(s.drop)
c:RegisterEffect(e2)
local e3=Effect.CreateEffect(c)
e3:SetType(EFFECT_TYPE_SINGLE)
e3:SetCode(EFFECT_MATERIAL_CHECK)
e3:SetValue(c11321089.valcheck)
e3:SetValue(s.valcheck)
e3:SetLabelObject(e2)
c:RegisterEffect(e3)
--cannot target
......@@ -41,30 +52,48 @@ function c11321089.initial_effect(c)
e4:SetProperty(EFFECT_FLAG_SINGLE_RANGE)
e4:SetCode(EFFECT_CANNOT_BE_EFFECT_TARGET)
e4:SetRange(LOCATION_MZONE)
e4:SetCondition(c11321089.indcon)
e4:SetCondition(s.indcon)
e4:SetValue(aux.tgoval)
c:RegisterEffect(e4)
end
function c11321089.ffilter(c,fc,sub,mg,sg)
function s.ffilter(c,fc,sub,mg,sg)
if not sg then return true end
local chkloc=LOCATION_HAND
if c:IsOnField() then chkloc=LOCATION_ONFIELD end
return not sg:IsExists(Card.IsFusionCode,1,c,c:GetFusionCode())
and (not c:IsLocation(LOCATION_HAND+LOCATION_ONFIELD) or #sg<2 or sg:IsExists(aux.NOT(Card.IsLocation),1,c,chkloc))
end
function c11321089.matlimit(e,c,fc,st)
function s.fgoalcheck(mg)
-- must include ≥1 from hand and ≥1 from field
local hand,field=0,0
for c in aux.Next(mg) do
if c:IsLocation(LOCATION_HAND) then
hand=hand+1
else
field=field+1
end
end
return hand>=1 and field>=1
end
function s.mat_filter(mc,tc)
return mc:IsLocation(LOCATION_HAND) or mc:IsControler(tc:GetControler()) and mc:IsOnField()
end
function s.matlimit(e,c,fc,st)
if st~=SUMMON_TYPE_FUSION then return true end
return c:IsLocation(LOCATION_HAND) or c:IsControler(fc:GetControler()) and c:IsOnField()
end
function c11321089.splimit(e,se,sp,st)
function s.splimit(e,se,sp,st)
return not e:GetHandler():IsLocation(LOCATION_EXTRA)
or st&SUMMON_TYPE_FUSION==SUMMON_TYPE_FUSION
end
function c11321089.drcon(e,tp,eg,ep,ev,re,r,rp)
function s.drcon(e,tp,eg,ep,ev,re,r,rp)
local c=e:GetHandler()
return re and re:IsActiveType(TYPE_SPELL) and c:IsSummonType(SUMMON_TYPE_FUSION)
end
function c11321089.drtg(e,tp,eg,ep,ev,re,r,rp,chk)
function s.drtg(e,tp,eg,ep,ev,re,r,rp,chk)
local dr,des=e:GetLabel()
if chk==0 then return dr and des and Duel.IsPlayerCanDraw(tp,dr)
and Duel.GetFieldGroupCount(tp,0,LOCATION_ONFIELD)>=des end
......@@ -74,7 +103,7 @@ function c11321089.drtg(e,tp,eg,ep,ev,re,r,rp,chk)
local g=Duel.GetMatchingGroup(aux.TRUE,tp,0,LOCATION_ONFIELD,nil)
Duel.SetOperationInfo(0,CATEGORY_DESTROY,g,1,0,0)
end
function c11321089.drop(e,tp,eg,ep,ev,re,r,rp)
function s.drop(e,tp,eg,ep,ev,re,r,rp)
local dr,des=e:GetLabel()
if Duel.Draw(tp,dr,REASON_EFFECT)>0 then
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_DESTROY)
......@@ -85,12 +114,12 @@ function c11321089.drop(e,tp,eg,ep,ev,re,r,rp)
end
end
end
function c11321089.valcheck(e,c)
function s.valcheck(e,c)
local mg=c:GetMaterial()
local mg1=mg:Filter(Card.IsLocation,nil,LOCATION_HAND)
local mg2=mg:Filter(Card.IsLocation,nil,LOCATION_ONFIELD)
e:GetLabelObject():SetLabel(#mg1,#mg2)
end
function c11321089.indcon(e)
function s.indcon(e)
return Duel.IsExistingMatchingCard(Card.IsCode,e:GetHandlerPlayer(),LOCATION_GRAVE,0,1,nil,24094653)
end
......@@ -3375,28 +3375,46 @@ end
Fusion={}
function Fusion.AddFusionProcedure(fcard,opts)
function Fusion.AddFusionProcedure(tc,opts)
local slots=opts.slots
local mat_filter=opts.mat_filter or nil
local fgoalcheck=opts.fgoalcheck or aux.TRUE
-- Register effect
local e=Effect.CreateEffect(fcard)
local e=Effect.CreateEffect(tc)
e:SetType(EFFECT_TYPE_SINGLE)
e:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE)
e:SetCode(EFFECT_FUSION_MATERIAL)
e:SetCondition(Fusion.FusionCondition(slots,true))
e:SetOperation(Fusion.FusionOperation(slots))
e:SetCondition(Fusion.FusionCondition(tc,slots,mat_filter,fgoalcheck,true))
e:SetOperation(Fusion.FusionOperation(tc,slots,mat_filter,fgoalcheck))
e:SetDescription(1379) --- 启用扩展卡包调试模式
fcard:RegisterEffect(e)
tc:RegisterEffect(e)
end
---@param allow_extras boolean whether to allow extra materials for checking propose
function Fusion.FusionCondition(slots,allow_extras)
function Fusion.FusionCondition(tc,slots,mat_filter,fgoalcheck,allow_extras,selected)
--g:Material group(nil for Instant Fusion)
--gc:Material already used
--chkf: check field, default:PLAYER_NONE
--chkf&0x100: Not fusion summon, can use substitute (Hex-Sealed Fusion)
--chkf&0x200: Not fusion summon, can't use substitute ("Contact Fusion", Neos Fusion)
return function(e,g,gc,chkf)
if not g or g:GetCount()<#slots then return false end
if not g then return false end
-- array
local cards={}
for mc in aux.Next(g) do
table.insert(cards,mc)
end
-- apply the global mat_filter if present
if mat_filter~=nil then
local tg={}
for _,mc in ipairs(cards) do
if mat_filter(mc,tc) then
table.insert(tg,mc)
end
end
cards=tg
end
if #cards<#slots then return false end
-- split slots
local single_slots, group_slots = {}, {}
for _, slot in ipairs(slots) do
......@@ -3415,11 +3433,6 @@ function Fusion.FusionCondition(slots,allow_extras)
return false
end
local cards={}
for tc in aux.Next(g) do
table.insert(cards,tc)
end
local used={}
local sub_count=0
-- DFS assign slots
......@@ -3427,17 +3440,17 @@ function Fusion.FusionCondition(slots,allow_extras)
if i>#single_slots then
-- check group slots on leftovers
local leftovers={}
for idx,tc in ipairs(cards) do
for idx,mc in ipairs(cards) do
if not used[idx] then
table.insert(leftovers,tc)
table.insert(leftovers,mc)
end
end
-- if strict (no extra), ensure leftover only match group slots
if not allow_extras then
for _,tc in ipairs(leftovers) do
for _,mc in ipairs(leftovers) do
local ok=false
for _,grp in ipairs(group_slots) do
if (not grp.filter or grp.filter(tc)) then
if (not grp.filter or grp.filter(mc)) then
ok=true
break
end
......@@ -3451,9 +3464,9 @@ function Fusion.FusionCondition(slots,allow_extras)
for _,grp in ipairs(group_slots) do
-- collect exactly the cards from leftovers that match this grp
local matched={}
for _,tc in ipairs(leftovers) do
if (not grp.filter or grp.filter(tc)) then
table.insert(matched,tc)
for _,mc in ipairs(leftovers) do
if (not grp.filter or grp.filter(mc)) then
table.insert(matched,mc)
end
end
-- cardinality check
......@@ -3579,6 +3592,16 @@ function Fusion.FusionCondition(slots,allow_extras)
end
end
end
if fgoalcheck then
--- merge selected card if provided
local mg=g:Clone()
if selected then
mg:Merge(selected)
end
if not fgoalcheck(mg) then
return false
end
end
return true
end
......@@ -3594,9 +3617,9 @@ function Fusion.FusionCondition(slots,allow_extras)
end
-- try each card
local slot=single_slots[i]
for idx,tc in ipairs(cards) do
for idx,mc in ipairs(cards) do
if not used[idx] then
local match,is_sub=Fusion.MatchSlot(tc,slot,e:GetHandler())
local match,is_sub=Fusion.MatchSlot(mc,slot,tc)
if match==true then
used[idx]=true
local prev_sub=sub_count
......@@ -3647,10 +3670,20 @@ end
--- Generator: operation from named slots
---@param slots table[]
function Fusion.FusionOperation(slots)
function Fusion.FusionOperation(tc,slots,mat_filter,fgoalcheck)
return function(e,tp,eg,ep,ev,re,rp,gc,chkf)
if mat_filter then
local pool=eg
pool=Group.CreateGroup()
for mc in aux.Next(eg) do
if mat_filter(mc,e:GetHandler()) then
pool:AddCard(mc)
end
end
eg=pool
end
-- strict final check (no extras)
local strict_cond=Fusion.FusionCondition(slots,false)
local strict_cond=Fusion.FusionCondition(tc,slots,mat_filter,fgoalcheck,false)
-- precompute minimum materials required
local min_req=0
local max_req=0
......@@ -3677,18 +3710,18 @@ function Fusion.FusionOperation(slots)
local addable=Group.CreateGroup()
local candidates={}
for tc in aux.Next(eg) do
if not sg:IsContains(tc) then
table.insert(candidates,tc)
for mc in aux.Next(eg) do
if not sg:IsContains(mc) then
table.insert(candidates,mc)
end
end
for _,tc in ipairs(candidates) do
sg:AddCard(tc)
if Fusion.CanCompleteFromMappings(e,sg,eg,slots,e:GetHandler(),gc,chkf) then
addable:AddCard(tc)
for _,mc in ipairs(candidates) do
sg:AddCard(mc)
if Fusion.CanCompleteFromMappings(e,sg,eg,slots,mat_filter,fgoalcheck,tc,gc,chkf) then
addable:AddCard(mc)
end
sg:RemoveCard(tc)
sg:RemoveCard(mc)
end
if addable:GetCount()==0 then
......@@ -3905,9 +3938,9 @@ end
--- @param sel Group currently picked materials
--- @param eg Group the full pool (e.g. your material group)
--- @param slots table[] your slot definitions
--- @param handler Card the Fusion monster (for substitutes)
--- @param tc Card the Fusion monster (for substitutes)
--- @return boolean true if ∃ a mapping + completion path
function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf)
function Fusion.CanCompleteFromMappings(e,sel,eg,slots,mat_filter,fgoalcheck,tc,gc,chkf)
-- arrayify sel so we can refer by index
local cards_sel={}
for c in aux.Next(sel) do
......@@ -3915,7 +3948,7 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf)
end
-- get every possible assignment of sel→slots
local mappings=Fusion.FindAllMappings(cards_sel,slots,handler)
local mappings=Fusion.FindAllMappings(cards_sel,slots,tc)
if #mappings==0 then
return false
end
......@@ -3980,7 +4013,7 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf)
-- fold each selected card’s fn(...) into either bitmask or keytbl
for idx,mapped_i in pairs(mapping) do
if mapped_i==i then
local v=fn(cards_sel[idx],handler)
local v=fn(cards_sel[idx],tc)
if type(v)=="number" then
bitmask=bitmask and (bitmask&v) or v
elseif type(v)=="table" then
......@@ -4006,7 +4039,7 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf)
end
-- for each fn in has_same, check against the precomputed overlap
for fn,overlap in pairs(used_overlap) do
local v=fn(mc,handler)
local v=fn(mc,tc)
if type(overlap)=="number" then
-- bitmask path
if (overlap&v)==0 then
......@@ -4030,7 +4063,7 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf)
end
end
end
if need>0 then
if slot.group.max-slot.group.min+need>0 then
-- preserve the full group slot
table.insert(rem_slots,{
group={
......@@ -4050,13 +4083,17 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf)
end
end
-- if nothing remains, we already succeed
-- if nothing remains, we already succeed, check fgoal
if #rem_slots==0 then
return true
if fgoalcheck==nil or fgoalcheck(sel)==true then
return true
else
return false
end
end
-- delegate to FusionCondition (allow_extras = true)
local search_cond=Fusion.FusionCondition(rem_slots,true)
local search_cond=Fusion.FusionCondition(tc,rem_slots,mat_filter,fgoalcheck,true,sel)
if search_cond(e,rem_pool,gc,chkf) 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