Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
ygopro-scripts-888
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
3
Merge Requests
3
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
ygopro-scripts-888
Commits
d97d98da
Commit
d97d98da
authored
Jul 13, 2025
by
Vury Leo
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add 究極竜魔導師
parent
2afce688
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
308 additions
and
167 deletions
+308
-167
c12381100.lua
c12381100.lua
+34
-7
c71143015.lua
c71143015.lua
+8
-1
procedure.lua
procedure.lua
+266
-159
No files found.
c12381100.lua
View file @
d97d98da
...
@@ -2,6 +2,33 @@
...
@@ -2,6 +2,33 @@
local
s
,
id
,
o
=
GetID
()
local
s
,
id
,
o
=
GetID
()
function
s
.
initial_effect
(
c
)
function
s
.
initial_effect
(
c
)
aux
.
AddMaterialCodeList
(
c
,
23995346
)
aux
.
AddMaterialCodeList
(
c
,
23995346
)
-- common Ritual‐monster filter: 「カオス」儀式モンスター
local
ritual_filter
=
function
(
mc
,
tc
)
if
not
mc
:
IsAllTypes
(
TYPE_MONSTER
|
TYPE_RITUAL
)
then
return
false
end
return
mc
:
IsFusionSetCard
(
0xcf
)
end
Fusion
.
AddFusionProcedure
(
c
,{
variants
=
{
-- Variant A: 1 × 青眼の究極竜 + 1 × 「カオス」儀式モンスター
{
slots
=
{
Fusion
.
Slot
.
Code
(
23995346
),
Fusion
.
Slot
.
Filter
(
ritual_filter
),
}
},
-- Variant B: 3 × 「ブルーアイズ」モンスター + 1 × 「カオス」儀式モンスター
{
slots
=
{
Fusion
.
Slot
.
Group
({
min
=
3
,
max
=
3
,
filter
=
function
(
mc
,
tc
)
return
mc
:
IsFusionSetCard
(
0xdd
)
end
,
}),
Fusion
.
Slot
.
Filter
(
ritual_filter
),
}
}
}
})
c
:
EnableReviveLimit
()
c
:
EnableReviveLimit
()
--summon procedure
--summon procedure
local
e0
=
Effect
.
CreateEffect
(
c
)
local
e0
=
Effect
.
CreateEffect
(
c
)
...
@@ -10,13 +37,13 @@ function s.initial_effect(c)
...
@@ -10,13 +37,13 @@ function s.initial_effect(c)
e0
:
SetCode
(
EFFECT_SPSUMMON_CONDITION
)
e0
:
SetCode
(
EFFECT_SPSUMMON_CONDITION
)
e0
:
SetValue
(
aux
.
fuslimit
)
e0
:
SetValue
(
aux
.
fuslimit
)
c
:
RegisterEffect
(
e0
)
c
:
RegisterEffect
(
e0
)
local
e1
=
Effect
.
CreateEffect
(
c
)
--
local e1=Effect.CreateEffect(c)
e1
:
SetType
(
EFFECT_TYPE_SINGLE
)
--
e1:SetType(EFFECT_TYPE_SINGLE)
e1
:
SetProperty
(
EFFECT_FLAG_CANNOT_DISABLE
+
EFFECT_FLAG_UNCOPYABLE
)
--
e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE)
e1
:
SetCode
(
EFFECT_FUSION_MATERIAL
)
--
e1:SetCode(EFFECT_FUSION_MATERIAL)
e1
:
SetCondition
(
s
.
fcondition
)
--
e1:SetCondition(s.fcondition)
e1
:
SetOperation
(
s
.
foperation
)
--
e1:SetOperation(s.foperation)
c
:
RegisterEffect
(
e1
)
--
c:RegisterEffect(e1)
--negate
--negate
local
e2
=
Effect
.
CreateEffect
(
c
)
local
e2
=
Effect
.
CreateEffect
(
c
)
e2
:
SetDescription
(
aux
.
Stringid
(
id
,
1
))
e2
:
SetDescription
(
aux
.
Stringid
(
id
,
1
))
...
...
c71143015.lua
View file @
d97d98da
...
@@ -11,7 +11,14 @@ function s.initial_effect(c)
...
@@ -11,7 +11,14 @@ function s.initial_effect(c)
{
[
0xff
]
=
FusionSpell
.
FUSION_OPERATION_SHUFFLE
}
{
[
0xff
]
=
FusionSpell
.
FUSION_OPERATION_SHUFFLE
}
},
},
stage_x_operation
=
s
.
stage_x_operation
,
stage_x_operation
=
s
.
stage_x_operation
,
locked_codes
=
{
89631139
,
23995346
}
locked_codes
=
function
(
tc
)
if
aux
.
IsMaterialListCode
(
tc
,
89631139
)
==
true
then
return
{
89631139
}
elseif
aux
.
IsMaterialListCode
(
tc
,
23995346
)
==
true
then
return
{
23995346
}
end
return
{}
end
})
})
e1
:
SetCategory
(
CATEGORY_SPECIAL_SUMMON
+
CATEGORY_FUSION_SUMMON
+
CATEGORY_GRAVE_ACTION
)
e1
:
SetCategory
(
CATEGORY_SPECIAL_SUMMON
+
CATEGORY_FUSION_SUMMON
+
CATEGORY_GRAVE_ACTION
)
e1
:
SetHintTiming
(
0
,
TIMINGS_CHECK_MONSTER
+
TIMING_MAIN_END
)
e1
:
SetHintTiming
(
0
,
TIMINGS_CHECK_MONSTER
+
TIMING_MAIN_END
)
...
...
procedure.lua
View file @
d97d98da
...
@@ -2255,7 +2255,7 @@ FusionSpell = {}
...
@@ -2255,7 +2255,7 @@ FusionSpell = {}
--- Whether skip the location count check, default false, used for 叛逆の堕天使, only works for target function
--- Whether skip the location count check, default false, used for 叛逆の堕天使, only works for target function
--- @field skip_location_count_check? boolean
--- @field skip_location_count_check? boolean
--- Locked code, material code that can not use substitutes
--- Locked code, material code that can not use substitutes
--- @field locked_codes?
integer[]
--- @field locked_codes?
(integer[]|fun(tc:Card):integer[])
--- 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
...
@@ -2407,7 +2407,7 @@ end
...
@@ -2407,7 +2407,7 @@ end
---@param fusion_spell_matfilter FUSION_SPELL_MATFILTER_FUNCTION a material must pass this to be legal as material come from fusion spell
---@param fusion_spell_matfilter FUSION_SPELL_MATFILTER_FUNCTION a material must pass this to be legal as material come from fusion spell
---@param skip_summon_check boolean whether skip the IsCanBeSpecialSummoned check, for クロック・リザード
---@param skip_summon_check boolean whether skip the IsCanBeSpecialSummoned check, for クロック・リザード
---@param skip_location_count_check boolean Whether skip the location count check, default false, used for 叛逆の堕天使
---@param skip_location_count_check boolean Whether skip the location count check, default false, used for 叛逆の堕天使
---@param locked_codes
integer[]
Locked code, material code that can not use substitutes, used for 烙印融合
---@param locked_codes
(integer[]|fun(tc:Card):integer[])
Locked code, material code that can not use substitutes, used for 烙印融合
function
FusionSpell
.
GetSummonTarget
(
function
FusionSpell
.
GetSummonTarget
(
fusfilter
,
fusfilter
,
matfilter
,
matfilter
,
...
@@ -2460,7 +2460,7 @@ function FusionSpell.GetSummonTarget(
...
@@ -2460,7 +2460,7 @@ function FusionSpell.GetSummonTarget(
end
end
-- --- check for chain material targets
-- --- check for chain material targets
if
sumtype
&
SUMMON_TYPE_FUSION
~=
0
then
if
sumtype
&
SUMMON_TYPE_FUSION
~=
0
then
local
ce_sg
=
FusionSpell
.
IsExistsChainMaterialSummonTargets
(
e
,
tp
,
fusfilter
,
matfilter
,
additional_fcheck
,
additional_fgoalcheck
,
fuslocation
,
sumtype
,
sumpos
,
gc
,
skip_summon_check
,
skip_location_count_check
)
local
ce_sg
=
FusionSpell
.
IsExistsChainMaterialSummonTargets
(
e
,
tp
,
fusfilter
,
matfilter
,
additional_fcheck
,
additional_fgoalcheck
,
fuslocation
,
sumtype
,
sumpos
,
gc
,
skip_summon_check
,
skip_location_count_check
,
locked_codes
)
if
ce_sg
==
true
then
if
ce_sg
==
true
then
return
true
return
true
end
end
...
@@ -2488,7 +2488,7 @@ end
...
@@ -2488,7 +2488,7 @@ end
---@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 FUSION_SPELL_MATFILTER_FUNCTION a material must pass this to be legal as material come from fusion spell
---@param fusion_spell_matfilter FUSION_SPELL_MATFILTER_FUNCTION a material must pass this to be legal as material come from fusion spell
---@param skip_summon_check boolean whether skip the IsCanBeSpecialSummoned check, for クロック・リザード
---@param skip_summon_check boolean whether skip the IsCanBeSpecialSummoned check, for クロック・リザード
---@param locked_codes
integer[]
Locked code, material code that can not use substitutes, used for 烙印融合
---@param locked_codes
(integer[]|fun(tc:Card):integer[])
Locked code, material code that can not use substitutes, used for 烙印融合
function
FusionSpell
.
GetSummonOperation
(
function
FusionSpell
.
GetSummonOperation
(
fusfilter
,
fusfilter
,
matfilter
,
matfilter
,
...
@@ -2597,7 +2597,11 @@ function FusionSpell.GetSummonOperation(
...
@@ -2597,7 +2597,11 @@ function FusionSpell.GetSummonOperation(
e
,
e
,
mat_operation_code_map
)
mat_operation_code_map
)
aux
.
FGoalCheckAdditional
=
FusionSpell
.
GetFusionSpellFGoalCheckAdditionalFunction
(
additional_fgoalcheck
,
tp
,
tc
,
pre_select_mat_location
,
e
)
aux
.
FGoalCheckAdditional
=
FusionSpell
.
GetFusionSpellFGoalCheckAdditionalFunction
(
additional_fgoalcheck
,
tp
,
tc
,
pre_select_mat_location
,
e
)
Fusion
.
LockedCodes
=
locked_codes
if
type
(
locked_codes
)
==
'function'
then
Fusion
.
LockedCodes
=
locked_codes
(
tc
)
else
Fusion
.
LockedCodes
=
locked_codes
end
materials
=
Duel
.
SelectFusionMaterial
(
tp
,
tc
,
mg
,
gc
(
e
),
tp
)
materials
=
Duel
.
SelectFusionMaterial
(
tp
,
tc
,
mg
,
gc
(
e
),
tp
)
aux
.
FCheckAdditional
=
nil
aux
.
FCheckAdditional
=
nil
aux
.
FGoalCheckAdditional
=
nil
aux
.
FGoalCheckAdditional
=
nil
...
@@ -2610,7 +2614,11 @@ function FusionSpell.GetSummonOperation(
...
@@ -2610,7 +2614,11 @@ function FusionSpell.GetSummonOperation(
assert
(
#
chain_mg
>
0
,
"we are trying to apply a chain material, but it has no possible material"
)
assert
(
#
chain_mg
>
0
,
"we are trying to apply a chain material, but it has no possible material"
)
aux
.
FCheckAdditional
=
FusionSpell
.
GetFusionSpellFCheckAdditionalFunctionForChainMaterial
(
additional_fcheck
,
e
)
aux
.
FCheckAdditional
=
FusionSpell
.
GetFusionSpellFCheckAdditionalFunctionForChainMaterial
(
additional_fcheck
,
e
)
aux
.
FGoalCheckAdditional
=
FusionSpell
.
GetFusionSpellFGoalCheckAdditionalFunctionForChainMaterial
(
additional_fgoalcheck
,
e
)
aux
.
FGoalCheckAdditional
=
FusionSpell
.
GetFusionSpellFGoalCheckAdditionalFunctionForChainMaterial
(
additional_fgoalcheck
,
e
)
Fusion
.
LockedCodes
=
locked_codes
if
type
(
locked_codes
)
==
'function'
then
Fusion
.
LockedCodes
=
locked_codes
(
tc
)
else
Fusion
.
LockedCodes
=
locked_codes
end
materials
=
Duel
.
SelectFusionMaterial
(
tp
,
tc
,
chain_mg
,
gc
(
e
),
tp
)
materials
=
Duel
.
SelectFusionMaterial
(
tp
,
tc
,
chain_mg
,
gc
(
e
),
tp
)
aux
.
FCheckAdditional
=
nil
aux
.
FCheckAdditional
=
nil
aux
.
FGoalCheckAdditional
=
nil
aux
.
FGoalCheckAdditional
=
nil
...
@@ -2879,7 +2887,7 @@ end
...
@@ -2879,7 +2887,7 @@ end
---@param fusion_spell_matfilter fun(c:Card):boolean a material must pass this to be legal as material come from fusion spell
---@param fusion_spell_matfilter fun(c:Card):boolean a material must pass this to be legal as material come from fusion spell
---@param skip_summon_check boolean whether skip the IsCanBeSpecialSummoned check, for クロック・リザード
---@param skip_summon_check boolean whether skip the IsCanBeSpecialSummoned check, for クロック・リザード
---@param skip_location_count_check boolean Whether skip the location count check, default false, used for 叛逆の堕天使
---@param skip_location_count_check boolean Whether skip the location count check, default false, used for 叛逆の堕天使
---@param locked_codes
integer[]
Locked code, material code that can not use substitutes, used for 烙印融合
---@param locked_codes
(integer[]|fun(tc:Card):integer[])
Locked code, material code that can not use substitutes, used for 烙印融合
function
FusionSpell
.
SummonTargetFilter
(
function
FusionSpell
.
SummonTargetFilter
(
c
,
c
,
fusfilter
,
fusfilter
,
...
@@ -2932,7 +2940,11 @@ function FusionSpell.SummonTargetFilter(
...
@@ -2932,7 +2940,11 @@ function FusionSpell.SummonTargetFilter(
e
,
e
,
mat_operation_code_map
)
mat_operation_code_map
)
aux
.
FGoalCheckAdditional
=
FusionSpell
.
GetFusionSpellFGoalCheckAdditionalFunction
(
additional_fgoalcheck
,
tp
,
c
,
pre_select_mat_location
,
e
)
aux
.
FGoalCheckAdditional
=
FusionSpell
.
GetFusionSpellFGoalCheckAdditionalFunction
(
additional_fgoalcheck
,
tp
,
c
,
pre_select_mat_location
,
e
)
Fusion
.
LockedCodes
=
locked_codes
if
type
(
locked_codes
)
==
'function'
then
Fusion
.
LockedCodes
=
locked_codes
(
c
)
else
Fusion
.
LockedCodes
=
locked_codes
end
local
chkf
=
FusionSpell
.
GetCheckFieldPlayer
(
tp
,
skip_location_count_check
)
local
chkf
=
FusionSpell
.
GetCheckFieldPlayer
(
tp
,
skip_location_count_check
)
local
res
=
c
:
CheckFusionMaterial
(
mg
,
gc
(
e
),
chkf
)
local
res
=
c
:
CheckFusionMaterial
(
mg
,
gc
(
e
),
chkf
)
aux
.
FCheckAdditional
=
nil
aux
.
FCheckAdditional
=
nil
...
@@ -2973,8 +2985,9 @@ end
...
@@ -2973,8 +2985,9 @@ end
---@param gc fun(e:Effect):Card|nil
---@param gc fun(e:Effect):Card|nil
---@param skip_summon_check boolean whether skip the IsCanBeSpecialSummoned check, for クロック・リザード
---@param skip_summon_check boolean whether skip the IsCanBeSpecialSummoned check, for クロック・リザード
---@param skip_location_count_check boolean Whether skip the location count check, default false, used for 叛逆の堕天使
---@param skip_location_count_check boolean Whether skip the location count check, default false, used for 叛逆の堕天使
---@param locked_codes (integer[]|fun(tc:Card):integer[]) Locked code, material code that can not use substitutes, used for 烙印融合
---@return boolean res return whether there is a valid target for any chain material effect
---@return boolean res return whether there is a valid target for any chain material effect
function
FusionSpell
.
IsExistsChainMaterialSummonTargets
(
e
,
tp
,
fusfilter
,
matfilter
,
additional_fcheck
,
additional_fgoalcheck
,
fuslocation
,
sumtype
,
sumpos
,
gc
,
skip_summon_check
,
skip_location_count_check
)
function
FusionSpell
.
IsExistsChainMaterialSummonTargets
(
e
,
tp
,
fusfilter
,
matfilter
,
additional_fcheck
,
additional_fgoalcheck
,
fuslocation
,
sumtype
,
sumpos
,
gc
,
skip_summon_check
,
skip_location_count_check
,
locked_codes
)
local
chain_material_effects
=
{
Duel
.
IsPlayerAffectedByEffect
(
tp
,
EFFECT_CHAIN_MATERIAL
)}
local
chain_material_effects
=
{
Duel
.
IsPlayerAffectedByEffect
(
tp
,
EFFECT_CHAIN_MATERIAL
)}
---@type {[Effect]:Group}
---@type {[Effect]:Group}
for
_
,
ce
in
ipairs
(
chain_material_effects
)
do
for
_
,
ce
in
ipairs
(
chain_material_effects
)
do
...
@@ -2984,7 +2997,7 @@ function FusionSpell.IsExistsChainMaterialSummonTargets(e,tp,fusfilter,matfilter
...
@@ -2984,7 +2997,7 @@ function FusionSpell.IsExistsChainMaterialSummonTargets(e,tp,fusfilter,matfilter
if
#
chain_mg
>
0
then
if
#
chain_mg
>
0
then
local
ce_fusfilter
=
ce
:
GetValue
()
local
ce_fusfilter
=
ce
:
GetValue
()
local
res
=
Duel
.
IsExistingMatchingCard
(
function
(
c
)
local
res
=
Duel
.
IsExistingMatchingCard
(
function
(
c
)
return
FusionSpell
.
ChainMaterialSummonTargetFilter
(
c
,
aux
.
AND
(
ce_fusfilter
,
fusfilter
or
aux
.
TRUE
),
e
,
tp
,
chain_mg
,
additional_fcheck
,
additional_fgoalcheck
,
sumtype
,
sumpos
,
gc
,
skip_summon_check
,
skip_location_count_check
)
return
FusionSpell
.
ChainMaterialSummonTargetFilter
(
c
,
aux
.
AND
(
ce_fusfilter
,
fusfilter
or
aux
.
TRUE
),
e
,
tp
,
chain_mg
,
additional_fcheck
,
additional_fgoalcheck
,
sumtype
,
sumpos
,
gc
,
skip_summon_check
,
skip_location_count_check
,
locked_codes
)
end
,
end
,
tp
,
fuslocation
,
0
,
1
,
nil
)
tp
,
fuslocation
,
0
,
1
,
nil
)
if
res
==
true
then
if
res
==
true
then
...
@@ -3000,6 +3013,7 @@ end
...
@@ -3000,6 +3013,7 @@ end
---@param gc fun(e:Effect):Card|nil
---@param gc fun(e:Effect):Card|nil
---@param skip_summon_check boolean whether skip the IsCanBeSpecialSummoned check, for クロック・リザード
---@param skip_summon_check boolean whether skip the IsCanBeSpecialSummoned check, for クロック・リザード
---@param skip_location_count_check boolean Whether skip the location count check, default false, used for 叛逆の堕天使
---@param skip_location_count_check boolean Whether skip the location count check, default false, used for 叛逆の堕天使
---@param locked_codes (integer[]|fun(tc:Card):integer[]) Locked code, material code that can not use substitutes, used for 烙印融合
---@return boolean result Whether c could be fusion summoned by this chain material effect
---@return boolean result Whether c could be fusion summoned by this chain material effect
function
FusionSpell
.
ChainMaterialSummonTargetFilter
(
c
,
fusfilter
,
e
,
tp
,
mg
,
additional_fcheck
,
additional_fgoalcheck
,
sumtype
,
sumpos
,
gc
,
skip_summon_check
,
skip_location_count_check
,
locked_codes
)
function
FusionSpell
.
ChainMaterialSummonTargetFilter
(
c
,
fusfilter
,
e
,
tp
,
mg
,
additional_fcheck
,
additional_fgoalcheck
,
sumtype
,
sumpos
,
gc
,
skip_summon_check
,
skip_location_count_check
,
locked_codes
)
if
not
c
:
IsType
(
TYPE_FUSION
)
or
fusfilter
(
c
,
e
,
tp
)
==
false
then
if
not
c
:
IsType
(
TYPE_FUSION
)
or
fusfilter
(
c
,
e
,
tp
)
==
false
then
...
@@ -3012,7 +3026,11 @@ function FusionSpell.ChainMaterialSummonTargetFilter(c,fusfilter,e,tp,mg,additio
...
@@ -3012,7 +3026,11 @@ function FusionSpell.ChainMaterialSummonTargetFilter(c,fusfilter,e,tp,mg,additio
end
end
aux
.
FCheckAdditional
=
FusionSpell
.
GetFusionSpellFCheckAdditionalFunctionForChainMaterial
(
additional_fcheck
,
e
)
aux
.
FCheckAdditional
=
FusionSpell
.
GetFusionSpellFCheckAdditionalFunctionForChainMaterial
(
additional_fcheck
,
e
)
aux
.
FGoalCheckAdditional
=
FusionSpell
.
GetFusionSpellFGoalCheckAdditionalFunctionForChainMaterial
(
additional_fgoalcheck
,
e
)
aux
.
FGoalCheckAdditional
=
FusionSpell
.
GetFusionSpellFGoalCheckAdditionalFunctionForChainMaterial
(
additional_fgoalcheck
,
e
)
Fusion
.
LockedCodes
=
locked_codes
if
type
(
locked_codes
)
==
'function'
then
Fusion
.
LockedCodes
=
locked_codes
(
c
)
else
Fusion
.
LockedCodes
=
locked_codes
end
local
chkf
=
FusionSpell
.
GetCheckFieldPlayer
(
tp
,
skip_location_count_check
)
local
chkf
=
FusionSpell
.
GetCheckFieldPlayer
(
tp
,
skip_location_count_check
)
local
res
=
c
:
CheckFusionMaterial
(
mg
,
gc
(
e
),
chkf
)
local
res
=
c
:
CheckFusionMaterial
(
mg
,
gc
(
e
),
chkf
)
aux
.
FCheckAdditional
=
nil
aux
.
FCheckAdditional
=
nil
...
@@ -3400,57 +3418,61 @@ Fusion={}
...
@@ -3400,57 +3418,61 @@ Fusion={}
Fusion
.
LockedCodes
=
nil
Fusion
.
LockedCodes
=
nil
function
Fusion
.
AddFusionProcedure
(
c
,
opts
)
-- Refactored Fusion.AddFusionProcedure using the above helpers
local
slots
=
opts
.
slots
function
Fusion
.
AddFusionProcedure
(
c
,
opts
)
local
mat_filter
=
opts
.
mat_filter
or
nil
local
patterns
=
Fusion
.
BuildPatterns
(
opts
)
local
fgoalcheck
=
opts
.
fgoalcheck
or
aux
.
TRUE
--=== Metadata registration ===--
-- Register metadata
if
c
:
IsStatus
(
STATUS_COPYING_EFFECT
)
then
return
end
if
c
:
IsStatus
(
STATUS_COPYING_EFFECT
)
then
return
end
-- collect all fusion codes and compute global min/max across patterns
local
mat
=
{}
local
code_set
=
{}
local
min_req
=
0
local
global_min
,
global_max
=
math.huge
,
0
local
max_req
=
0
for
_
,
pat
in
ipairs
(
patterns
)
do
for
_
,
slot
in
ipairs
(
slots
)
do
local
pmin
,
pmax
=
0
,
0
if
slot
.
match_code
then
for
_
,
slot
in
ipairs
(
pat
.
slots
)
do
mat
[
slot
.
match_code
]
=
true
if
slot
.
match_code
then
min_req
=
min_req
+
1
code_set
[
slot
.
match_code
]
=
true
max_req
=
max_req
+
1
pmin
=
pmin
+
1
elseif
slot
.
match_codes
then
pmax
=
pmax
+
1
for
_
,
code
in
ipairs
(
slot
.
match_codes
)
do
elseif
slot
.
match_codes
then
mat
[
code
]
=
true
for
_
,
cd
in
ipairs
(
slot
.
match_codes
)
do
end
code_set
[
cd
]
=
true
min_req
=
min_req
+
1
end
max_req
=
max_req
+
1
pmin
=
pmin
+
1
elseif
slot
.
filter
then
pmax
=
pmax
+
1
local
prev
=
slot
.
filter
elseif
slot
.
group
then
slot
.
filter
=
function
(
mc
,
p_tc
)
return
prev
(
mc
,
p_tc
)
and
not
mc
:
IsHasEffect
(
6205579
)
end
pmin
=
pmin
+
slot
.
group
.
min
min_req
=
min_req
+
1
pmax
=
pmax
+
slot
.
group
.
max
max_req
=
max_req
+
1
else
elseif
slot
.
group
then
-- generic filter-slot
local
prev
=
slot
.
group
.
filter
pmin
=
pmin
+
1
slot
.
group
.
filter
=
function
(
mc
,
p_tc
)
return
prev
(
mc
,
p_tc
)
and
not
mc
:
IsHasEffect
(
6205579
)
end
pmax
=
pmax
+
1
min_req
=
min_req
+
slot
.
group
.
min
end
max_req
=
max_req
+
slot
.
group
.
max
end
end
global_min
=
math.min
(
global_min
,
pmin
)
end
global_max
=
math.max
(
global_max
,
pmax
)
local
mt
=
getmetatable
(
c
)
end
if
mt
.
material
==
nil
then
mt
.
material
=
mat
local
mt
=
getmetatable
(
c
)
end
if
mt
.
material
==
nil
then
if
mt
.
material_count
==
nil
then
mt
.
material
=
code_set
mt
.
material_count
=
{
min_req
,
max_req
}
end
end
if
mt
.
material_count
==
nil
then
for
index
,
_
in
pairs
(
mat
)
do
mt
.
material_count
=
{
global_min
,
global_max
}
Auxiliary
.
AddCodeList
(
c
,
index
)
end
end
for
cd
,
_
in
pairs
(
code_set
)
do
-- Register effect
Auxiliary
.
AddCodeList
(
c
,
cd
)
local
e
=
Effect
.
CreateEffect
(
c
)
end
e
:
SetType
(
EFFECT_TYPE_SINGLE
)
e
:
SetProperty
(
EFFECT_FLAG_CANNOT_DISABLE
+
EFFECT_FLAG_UNCOPYABLE
)
--=== Effect registration ===--
e
:
SetCode
(
EFFECT_FUSION_MATERIAL
)
local
e
=
Effect
.
CreateEffect
(
c
)
e
:
SetCondition
(
Fusion
.
FusionCondition
(
c
,
slots
,
mat_filter
,
fgoalcheck
,
true
))
e
:
SetType
(
EFFECT_TYPE_SINGLE
)
e
:
SetOperation
(
Fusion
.
FusionOperation
(
c
,
slots
,
mat_filter
,
fgoalcheck
))
e
:
SetProperty
(
EFFECT_FLAG_CANNOT_DISABLE
+
EFFECT_FLAG_UNCOPYABLE
)
e
:
SetDescription
(
1379
)
--- 启用扩展卡包调试模式
e
:
SetCode
(
EFFECT_FUSION_MATERIAL
)
c
:
RegisterEffect
(
e
)
e
:
SetCondition
(
Fusion
.
MultiCondition
(
c
,
patterns
,
true
))
e
:
SetOperation
(
Fusion
.
MultiOperation
(
c
,
patterns
))
e
:
SetDescription
(
1379
)
c
:
RegisterEffect
(
e
)
end
end
---@param allow_extras boolean whether to allow extra materials for checking propose
---@param allow_extras boolean whether to allow extra materials for checking propose
...
@@ -3503,7 +3525,6 @@ function Fusion.FusionCondition(tc,slots,mat_filter,fgoalcheck,allow_extras,sele
...
@@ -3503,7 +3525,6 @@ function Fusion.FusionCondition(tc,slots,mat_filter,fgoalcheck,allow_extras,sele
for
idx
,
slot
in
ipairs
(
single_slots
)
do
for
idx
,
slot
in
ipairs
(
single_slots
)
do
-- lock slot if its match_code equals code
-- lock slot if its match_code equals code
if
slot
.
match_code
==
code
then
if
slot
.
match_code
==
code
then
Debug
.
Message
(
string.format
(
"locked %d, slot %d"
,
code
,
idx
))
locked_slots
[
idx
]
=
true
locked_slots
[
idx
]
=
true
break
break
end
end
...
@@ -3773,92 +3794,6 @@ function Fusion.MatchSlot(mc,slot,tc)
...
@@ -3773,92 +3794,6 @@ function Fusion.MatchSlot(mc,slot,tc)
return
false
,
false
return
false
,
false
end
end
--- Generator: operation from named slots
---@param slots table[]
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
(
tc
,
slots
,
mat_filter
,
fgoalcheck
,
false
)
-- precompute minimum materials required
local
min_req
=
0
local
max_req
=
0
for
_
,
slot
in
ipairs
(
slots
)
do
if
slot
.
group
then
min_req
=
min_req
+
slot
.
group
.
min
max_req
=
max_req
+
slot
.
group
.
max
else
min_req
=
min_req
+
1
max_req
=
max_req
+
1
end
end
max_req
=
math.min
(
max_req
,
eg
:
GetCount
())
-- prompt player
Duel
.
Hint
(
HINT_SELECTMSG
,
tp
,
HINTMSG_FMATERIAL
)
local
sg
=
Group
.
CreateGroup
()
while
true
do
-- can we finish right now?
local
finishable
=
(
sg
:
GetCount
()
>=
min_req
)
and
strict_cond
(
e
,
sg
,
gc
,
chkf
)
-- build “addable” via exhaustive mapping + completion test
local
addable
=
Group
.
CreateGroup
()
local
candidates
=
{}
for
mc
in
aux
.
Next
(
eg
)
do
if
not
sg
:
IsContains
(
mc
)
then
table.insert
(
candidates
,
mc
)
end
end
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
(
mc
)
end
if
addable
:
GetCount
()
==
0
then
assert
(
finishable
==
true
)
Duel
.
SetFusionMaterial
(
sg
)
return
end
-- UI: let the player pick or finalize
local
picked
=
Group
.
SelectUnselect
(
addable
,
sg
,
tp
,
finishable
,
true
,
min_req
,
max_req
)
if
not
picked
then
if
finishable
then
Duel
.
SetFusionMaterial
(
sg
)
return
-- user clicked “OK”
else
Duel
.
SetFusionMaterial
(
Group
.
CreateGroup
())
return
-- user clicked “Cancel” on invalid selection
end
end
assert
(
picked
~=
nil
)
-- toggle selection
if
sg
:
IsContains
(
picked
)
then
sg
:
RemoveCard
(
picked
)
else
sg
:
AddCard
(
picked
)
end
end
end
end
-- Slot constructors
-- Slot constructors
Fusion
.
Slot
=
{}
Fusion
.
Slot
=
{}
--- Create a slot for a single code (default allow_sub = true)
--- Create a slot for a single code (default allow_sub = true)
...
@@ -3950,7 +3885,11 @@ function Fusion.FindAllMappings(cards_sel,slots,tc)
...
@@ -3950,7 +3885,11 @@ function Fusion.FindAllMappings(cards_sel,slots,tc)
local
all_maps
=
{}
local
all_maps
=
{}
local
mapping
=
{}
-- mapping[idx_in_cards_sel] = slot_index
local
mapping
=
{}
-- mapping[idx_in_cards_sel] = slot_index
local
function
dfs
(
idx
)
local
function
dfs
(
idx
,
sub_count
)
-- prune: no more than 1 substitute
if
sub_count
>
1
then
return
end
if
idx
>#
cards_sel
then
if
idx
>#
cards_sel
then
-- Before recording, run unique_by on each group‐slot that has one
-- Before recording, run unique_by on each group‐slot that has one
for
i
,
slot
in
ipairs
(
slots
)
do
for
i
,
slot
in
ipairs
(
slots
)
do
...
@@ -3988,14 +3927,17 @@ function Fusion.FindAllMappings(cards_sel,slots,tc)
...
@@ -3988,14 +3927,17 @@ function Fusion.FindAllMappings(cards_sel,slots,tc)
if
not
slot
.
group
and
not
filled
[
i
]
then
if
not
slot
.
group
and
not
filled
[
i
]
then
local
match
,
is_sub
=
Fusion
.
MatchSlot
(
mc
,
slot
,
tc
)
local
match
,
is_sub
=
Fusion
.
MatchSlot
(
mc
,
slot
,
tc
)
if
match
then
if
match
then
-- skip
substitute if
slot is locked
-- skip
if substitute and this
slot is locked
if
not
(
is_sub
and
locked_slots
[
i
])
then
if
not
(
is_sub
and
locked_slots
[
i
])
then
any_match
=
true
local
new_sub
=
sub_count
+
(
is_sub
and
1
or
0
)
filled
[
i
]
=
true
if
new_sub
<=
1
then
mapping
[
idx
]
=
i
any_match
=
true
dfs
(
idx
+
1
)
filled
[
i
]
=
true
filled
[
i
]
=
false
mapping
[
idx
]
=
i
mapping
[
idx
]
=
nil
dfs
(
idx
+
1
,
new_sub
)
filled
[
i
]
=
false
mapping
[
idx
]
=
nil
end
end
end
end
end
end
end
...
@@ -4050,7 +3992,7 @@ function Fusion.FindAllMappings(cards_sel,slots,tc)
...
@@ -4050,7 +3992,7 @@ function Fusion.FindAllMappings(cards_sel,slots,tc)
any_match
=
true
any_match
=
true
group_assigned
[
i
]
=
assigned
+
1
group_assigned
[
i
]
=
assigned
+
1
mapping
[
idx
]
=
i
mapping
[
idx
]
=
i
dfs
(
idx
+
1
)
dfs
(
idx
+
1
,
sub_count
)
group_assigned
[
i
]
=
assigned
group_assigned
[
i
]
=
assigned
mapping
[
idx
]
=
nil
mapping
[
idx
]
=
nil
end
end
...
@@ -4065,7 +4007,7 @@ function Fusion.FindAllMappings(cards_sel,slots,tc)
...
@@ -4065,7 +4007,7 @@ function Fusion.FindAllMappings(cards_sel,slots,tc)
end
end
end
end
dfs
(
1
)
dfs
(
1
,
0
)
return
all_maps
return
all_maps
end
end
...
@@ -4366,3 +4308,168 @@ function Fusion.MakeExcludeFilter(orig_filter,key_func,used_keys)
...
@@ -4366,3 +4308,168 @@ function Fusion.MakeExcludeFilter(orig_filter,key_func,used_keys)
return
true
return
true
end
end
end
end
-- Helper: build patterns list (single or variants)
function
Fusion
.
BuildPatterns
(
opts
)
local
patterns
=
{}
if
opts
.
variants
then
for
_
,
v
in
ipairs
(
opts
.
variants
)
do
table.insert
(
patterns
,{
slots
=
v
.
slots
,
mat_filter
=
v
.
mat_filter
,
fgoalcheck
=
v
.
fgoalcheck
or
aux
.
TRUE
,
})
end
else
table.insert
(
patterns
,{
slots
=
opts
.
slots
,
mat_filter
=
opts
.
mat_filter
,
fgoalcheck
=
opts
.
fgoalcheck
or
aux
.
TRUE
,
})
end
return
patterns
end
-- Helper: combine multiple patterns into one condition function (no goto)
function
Fusion
.
MultiCondition
(
tc
,
patterns
,
allow_extras
)
return
function
(
e
,
g
,
gc
,
chkf
)
if
not
g
then
return
false
end
local
locked
=
Fusion
.
LockedCodes
for
_
,
pat
in
ipairs
(
patterns
)
do
-- skip patterns that don't include all locked codes
local
ok
=
true
if
locked
then
for
_
,
code
in
ipairs
(
locked
)
do
if
not
Fusion
.
PatternIncludesCode
(
pat
,
code
)
then
ok
=
false
break
end
end
end
if
ok
then
local
cond
=
Fusion
.
FusionCondition
(
tc
,
pat
.
slots
,
pat
.
mat_filter
,
pat
.
fgoalcheck
,
allow_extras
)
if
cond
(
e
,
g
,
gc
,
chkf
)
then
return
true
end
end
end
return
false
end
end
-- Helper: compute the minimal and maximal material counts across patterns
function
Fusion
.
PatternsMinMax
(
patterns
)
local
min_req
=
math.huge
local
max_req
=
0
for
_
,
pat
in
ipairs
(
patterns
)
do
local
lo
,
hi
=
0
,
0
for
_
,
slot
in
ipairs
(
pat
.
slots
)
do
if
slot
.
group
then
lo
=
lo
+
slot
.
group
.
min
hi
=
hi
+
slot
.
group
.
max
else
lo
=
lo
+
1
hi
=
hi
+
1
end
end
min_req
=
math.min
(
min_req
,
lo
)
max_req
=
math.max
(
max_req
,
hi
)
end
return
min_req
,
max_req
end
-- Helper: combine patterns into one operation function
function
Fusion
.
MultiOperation
(
tc
,
patterns
)
return
function
(
e
,
tp
,
eg
,
ep
,
ev
,
re
,
rp
,
gc
,
chkf
)
-- filter patterns by any locked codes, once per operation
local
locked
=
Fusion
.
LockedCodes
local
active_patterns
=
{}
if
locked
then
for
_
,
pat
in
ipairs
(
patterns
)
do
local
ok
=
true
for
_
,
code
in
ipairs
(
locked
)
do
if
not
Fusion
.
PatternIncludesCode
(
pat
,
code
)
then
ok
=
false
break
end
end
if
ok
then
table.insert
(
active_patterns
,
pat
)
end
end
else
-- no locked codes: all patterns active
active_patterns
=
patterns
end
-- compute min/max over active patterns
local
min_req
,
max_req
=
Fusion
.
PatternsMinMax
(
active_patterns
)
max_req
=
math.min
(
max_req
,
eg
:
GetCount
())
-- strict condition uses only active patterns
local
strict_cond
=
Fusion
.
MultiCondition
(
tc
,
active_patterns
,
false
)
Duel
.
Hint
(
HINT_SELECTMSG
,
tp
,
HINTMSG_FMATERIAL
)
local
sg
=
Group
.
CreateGroup
()
--- arraify eg
local
eg_arr
=
{}
for
mc
in
aux
.
Next
(
eg
)
do
table.insert
(
eg_arr
,
mc
)
end
while
true
do
local
finishable
=
sg
:
GetCount
()
>=
min_req
and
strict_cond
(
e
,
sg
,
gc
,
chkf
)
local
addable
=
Group
.
CreateGroup
()
for
_
,
mc
in
ipairs
(
eg_arr
)
do
if
not
sg
:
IsContains
(
mc
)
then
sg
:
AddCard
(
mc
)
-- completion test against active patterns
for
_
,
pat
in
ipairs
(
active_patterns
)
do
if
Fusion
.
CanCompleteFromMappings
(
e
,
sg
,
eg
,
pat
.
slots
,
pat
.
mat_filter
,
pat
.
fgoalcheck
,
tc
,
gc
,
chkf
)
then
addable
:
AddCard
(
mc
)
break
end
end
sg
:
RemoveCard
(
mc
)
end
end
if
addable
:
GetCount
()
==
0
then
assert
(
finishable
)
Duel
.
SetFusionMaterial
(
sg
)
return
end
local
picked
=
Group
.
SelectUnselect
(
addable
,
sg
,
tp
,
finishable
,
true
,
min_req
,
max_req
)
if
not
picked
then
if
finishable
then
Duel
.
SetFusionMaterial
(
sg
)
else
Duel
.
SetFusionMaterial
(
Group
.
CreateGroup
())
end
return
end
if
sg
:
IsContains
(
picked
)
then
sg
:
RemoveCard
(
picked
)
else
sg
:
AddCard
(
picked
)
end
end
end
end
-- Helper: detect if a pattern has a slot for a given code
function
Fusion
.
PatternIncludesCode
(
pat
,
code
)
for
_
,
slot
in
ipairs
(
pat
.
slots
)
do
if
slot
.
match_code
==
code
then
return
true
end
if
slot
.
match_codes
then
for
_
,
c
in
ipairs
(
slot
.
match_codes
)
do
if
c
==
code
then
return
true
end
end
end
end
return
false
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment