Commit f5ac4633 authored by Vury Leo's avatar Vury Leo

Add Genomix Fighter

parent 14eb7b05
......@@ -70,6 +70,13 @@ function s.decop(e,tp,eg,ep,ev,re,r,rp)
e1:SetReset(RESET_EVENT+RESETS_STANDARD+RESET_PHASE+PHASE_END)
e1:SetLabel(rc)
c:RegisterEffect(e1)
local e2=Effect.CreateEffect(c)
e2:SetProperty(EFFECT_FLAG_CANNOT_DISABLE)
e2:SetType(EFFECT_TYPE_SINGLE)
e2:SetCode(id)
e2:SetReset(RESET_EVENT+RESETS_STANDARD+RESET_PHASE+PHASE_END)
e2:SetLabel(rc)
c:RegisterEffect(e2)
end
end
function s.syncheck(e,c)
......
--ヘル・ツイン・コップ
function c86137485.initial_effect(c)
local s,id,o=GetID()
function s.initial_effect(c)
--synchro summon
Synchro.AddSynchroProcedure(c,{
tuner_race=RACE_FIEND,
})
aux.AddSynchroProcedure(c,aux.FilterBoolFunction(Card.IsRace,RACE_FIEND),aux.NonTuner(nil),1)
c:EnableReviveLimit()
--chain attack
local e1=Effect.CreateEffect(c)
e1:SetDescription(aux.Stringid(86137485,0))
e1:SetDescription(aux.Stringid(id,0))
e1:SetType(EFFECT_TYPE_SINGLE+EFFECT_TYPE_TRIGGER_O)
e1:SetCode(EVENT_BATTLE_DESTROYING)
e1:SetCondition(c86137485.atcon1)
e1:SetOperation(c86137485.atop1)
e1:SetCondition(s.atcon1)
e1:SetOperation(s.atop1)
c:RegisterEffect(e1)
local e2=Effect.CreateEffect(c)
e2:SetDescription(aux.Stringid(86137485,0))
e2:SetDescription(aux.Stringid(id,0))
e2:SetType(EFFECT_TYPE_SINGLE+EFFECT_TYPE_TRIGGER_O)
e2:SetCode(EVENT_BATTLE_DESTROYING)
e2:SetCondition(c86137485.atcon2)
e2:SetOperation(c86137485.atop2)
e2:SetCondition(s.atcon2)
e2:SetOperation(s.atop2)
c:RegisterEffect(e2)
end
function c86137485.atcon1(e,tp,eg,ep,ev,re,r,rp)
function s.atcon1(e,tp,eg,ep,ev,re,r,rp)
local c=e:GetHandler()
local bc=c:GetBattleTarget()
return Duel.GetTurnPlayer()==tp and bc:IsLocation(LOCATION_GRAVE) and bc:IsType(TYPE_MONSTER)
and c:IsChainAttackable() and c:IsStatus(STATUS_OPPO_BATTLE)
end
function c86137485.atop1(e,tp,eg,ep,ev,re,r,rp)
function s.atop1(e,tp,eg,ep,ev,re,r,rp)
local c=e:GetHandler()
if not c:IsRelateToEffect(e) or c:IsFacedown() then return end
local e1=Effect.CreateEffect(c)
......@@ -36,13 +40,13 @@ function c86137485.atop1(e,tp,eg,ep,ev,re,r,rp)
c:RegisterEffect(e1)
Duel.ChainAttack()
end
function c86137485.atcon2(e,tp,eg,ep,ev,re,r,rp)
function s.atcon2(e,tp,eg,ep,ev,re,r,rp)
local c=e:GetHandler()
local bc=c:GetBattleTarget()
return Duel.GetTurnPlayer()~=tp and c:IsRelateToBattle() and c:IsStatus(STATUS_OPPO_BATTLE)
and bc:IsLocation(LOCATION_GRAVE) and bc:IsType(TYPE_MONSTER)
end
function c86137485.atop2(e,tp,eg,ep,ev,re,r,rp)
function s.atop2(e,tp,eg,ep,ev,re,r,rp)
local c=e:GetHandler()
if not c:IsRelateToEffect(e) or c:IsFacedown() then return end
local e1=Effect.CreateEffect(c)
......
......@@ -3382,7 +3382,9 @@ Synchro.Infinite=math.huge
--- @param params? table -- parameters table with keys: f1,f2,minc,maxc
function Synchro.AddSynchroProcedure(c,params)
params=params or {}
local tuner_race=params.tuner_race or RACE_ALL
local tuner_filter=params.tuner_filter or function(mc,tc) return mc:IsType(TYPE_TUNER) end
local non_tuner_race=params.non_tuner_race or RACE_ALL
local non_tuner_filter=params.non_tuner_filter or function(mc,tc) return not mc:IsType(TYPE_TUNER) end
local tuner_min=params.tuner_min or 1
local tuner_max=params.tuner_max or 1
......@@ -3397,8 +3399,8 @@ function Synchro.AddSynchroProcedure(c,params)
e1:SetCode(EFFECT_SPSUMMON_PROC)
e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE)
e1:SetRange(LOCATION_EXTRA)
e1:SetCondition(Synchro.SynCondition(tuner_filter,non_tuner_filter,tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper))
e1:SetTarget(Synchro.SynTarget(tuner_filter,non_tuner_filter,tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper))
e1:SetCondition(Synchro.SynCondition(tuner_race,tuner_filter,non_tuner_race,non_tuner_filter,tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper))
e1:SetTarget(Synchro.SynTarget(tuner_race,tuner_filter,non_tuner_race,non_tuner_filter,tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper))
e1:SetOperation(Synchro.SynOperation())
e1:SetValue(SUMMON_TYPE_SYNCHRO)
c:RegisterEffect(e1)
......@@ -3406,14 +3408,15 @@ end
-- Entry point: prepares and invokes the DFS
function Synchro.FindValidSelection(candidates,target_level,
tuner_filter,non_tuner_filter,tc,
tuner_race,tuner_filter,
non_tuner_race,non_tuner_filter,tc,
tuner_min,tuner_max,
non_tuner_min,non_tuner_max,
base_mapper,pre_select,state)
Synchro.SortMaterials(candidates,tc,tuner_filter)
-- 2) Find the index of the last level card
-- Find the index of the last level card
local level_prune_index=0
for i, c in ipairs(candidates) do
if Synchro.IsLevelAlter(c) then
......@@ -3421,7 +3424,7 @@ function Synchro.FindValidSelection(candidates,target_level,
end
end
-- 3) Find the index of the last hand card
-- Find the index of the last hand card
local hand_prune_index=0
for i, c in ipairs(candidates) do
if Synchro.IsHandAlter(c) then
......@@ -3429,10 +3432,19 @@ function Synchro.FindValidSelection(candidates,target_level,
end
end
-- Find the index of the last race card
local race_prune_index=0
for i, c in ipairs(candidates) do
if Synchro.IsRaceAlter(c) then
race_prune_index=i
end
end
-- 3) Invoke the core DFS, passing last_dyn along
return Synchro.CanCompleteSelection(
candidates,target_level,
tuner_filter,non_tuner_filter,tc,
tuner_race,tuner_filter,
non_tuner_race,non_tuner_filter,tc,
tuner_min,tuner_max,
non_tuner_min,non_tuner_max,
base_mapper,
......@@ -3446,10 +3458,12 @@ function Synchro.FindValidSelection(candidates,target_level,
level_mapper_priority=0,
hand_count_limit=0,
hand_count=0,
genomix_race=nil,
},
{
level_prune_index=level_prune_index,
hand_prune_index=hand_prune_index,
race_prune_index=race_prune_index,
}
)
end
......@@ -3459,8 +3473,10 @@ end
---
--- @param candidates Card[] -- Array of candidate material cards.
--- @param target_level integer -- Required total level for Synchro Summon.
--- @param tuner_race integer -- race requirement for tuner
--- @param tuner_filter fun(card:Card,tc:Card):boolean
--- -- Function to identify tuner materials.
--- @param non_tuner_race integer -- race requirement for non tuner
--- @param non_tuner_filter fun(card:Card,tc:Card):boolean
--- -- Function to identify non-tuner materials.
--- @param tc Card -- The Synchro monster being summoned.
......@@ -3478,7 +3494,7 @@ end
--- -- non_tuner_count (integer): current non-tuner count.
--- @param prune_indexes table
--- @return boolean -- True if a valid selection exists, false otherwise.
function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_tuner_filter,tc,
function Synchro.CanCompleteSelection(candidates,target_level,tuner_race,tuner_filter,non_tuner_race,non_tuner_filter,tc,
tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper,selected,index,state,prune_indexes)
if state.tuner_count>tuner_max then return false end
......@@ -3501,18 +3517,31 @@ function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_t
prune_level=math.huge -- infinity
end
local prune_tuner_filter=tuner_filter
local prune_non_tuner_filter=non_tuner_filter
if index>prune_indexes.race_prune_index then
if state.genomix_race~=nil then
prune_tuner_filter=aux.AND(function() return state.genomix_race&tuner_race~=0 end,tuner_filter)
prune_non_tuner_filter=aux.AND(function() return state.genomix_race&tuner_race~=0 end,non_tuner_filter)
else
prune_tuner_filter=aux.AND(function(c) return c:IsRace(tuner_race) end,tuner_filter)
prune_non_tuner_filter=aux.AND(function(c) return c:IsRace(tuner_race) end,non_tuner_filter)
end
end
local mc=candidates[index]
for _,diff in ipairs(Synchro.GenerateVariantForCard(
state,mc,#selected+1,tc,tuner_filter,non_tuner_filter
state,mc,#selected+1,tc,prune_tuner_filter,prune_non_tuner_filter
)) do
-- apply diff
local branch_state=Synchro.ApplyVariantState(
state,mc,diff,tuner_filter,non_tuner_filter,tc,prune_level
state,mc,diff,tuner_race,prune_tuner_filter,non_tuner_race,prune_non_tuner_filter,tc,prune_level
)
table.insert(selected,mc)
if Synchro.CanCompleteSelection(
candidates,target_level,
tuner_filter,non_tuner_filter,tc,
tuner_race,tuner_filter,
non_tuner_race,non_tuner_filter,tc,
tuner_min,tuner_max,non_tuner_min,non_tuner_max,
base_mapper,selected,index+1,branch_state,prune_indexes
) then
......@@ -3523,7 +3552,7 @@ function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_t
end
-- exclude branch
if Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_tuner_filter,tc,
if Synchro.CanCompleteSelection(candidates,target_level,tuner_race,tuner_filter,non_tuner_race,non_tuner_filter,tc,
tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper,selected,index+1,state,prune_indexes) then
return true
end
......@@ -3532,7 +3561,7 @@ function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_t
end
--- Synchro condition generator using tuner/non-tuner min/max counts and filters
function Synchro.SynCondition(tuner_filter,non_tuner_filter,tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper)
function Synchro.SynCondition(tuner_race,tuner_filter,non_tuner_race,non_tuner_filter,tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper)
return function(e,c,smat,mg,min,max)
if c==nil then return true end
if c:IsType(TYPE_PENDULUM) and c:IsFaceup() then return false end
......@@ -3551,11 +3580,11 @@ function Synchro.SynCondition(tuner_filter,non_tuner_filter,tuner_min,tuner_max,
table.insert(candidates,mc)
end
return Synchro.FindValidSelection(candidates,target_level,tuner_filter,non_tuner_filter,c,tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper)
return Synchro.FindValidSelection(candidates,target_level,tuner_race,tuner_filter,non_tuner_race,non_tuner_filter,c,tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper)
end
end
function Synchro.SynTarget(tuner_filter,non_tuner_filter,tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper)
function Synchro.SynTarget(tuner_race,tuner_filter,non_tuner_race,non_tuner_filter,tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper)
return function(e,tp,eg,ep,ev,re,r,rp,chk,tc,smat,mg,min,max)
mg=mg or Duel.GetMatchingGroup(function(mc) return mc:IsCanBeSynchroMaterial(mc,tc) end,tc:GetOwner(),LOCATION_MZONE+LOCATION_HAND,0,nil)
local sg=Group.CreateGroup()
......@@ -3575,7 +3604,8 @@ function Synchro.SynTarget(tuner_filter,non_tuner_filter,tuner_min,tuner_max,non
local selected_level_min=target_level
local selected_states=Synchro.BuildStatesFromSelection(
sg_arr,
tuner_filter,non_tuner_filter,
tuner_race,tuner_filter,
non_tuner_race,non_tuner_filter,
base_mapper,
tc,math.huge
)
......@@ -3604,7 +3634,8 @@ function Synchro.SynTarget(tuner_filter,non_tuner_filter,tuner_min,tuner_max,non
local base_states=Synchro.BuildStatesFromSelection(
test_selection,
tuner_filter,non_tuner_filter,
tuner_race,tuner_filter,
non_tuner_race,non_tuner_filter,
base_mapper,
tc,math.huge
)
......@@ -3612,7 +3643,8 @@ function Synchro.SynTarget(tuner_filter,non_tuner_filter,tuner_min,tuner_max,non
for _,init_state in ipairs(base_states) do
if Synchro.FindValidSelection(
rest_candidates,target_level,
tuner_filter,non_tuner_filter,tc,
tuner_race,tuner_filter,
non_tuner_race,non_tuner_filter,tc,
tuner_min,tuner_max,non_tuner_min,non_tuner_max,
base_mapper,test_selection,init_state)
then
......@@ -3626,7 +3658,7 @@ function Synchro.SynTarget(tuner_filter,non_tuner_filter,tuner_min,tuner_max,non
break
end
local finishable=Synchro.IsSelectionValid(sg_arr,target_level,tuner_filter,non_tuner_filter,tc,tuner_min,tuner_max,non_tuner_min,non_tuner_max)
local finishable=Synchro.IsSelectionValid(sg_arr,target_level,tuner_race,tuner_filter,non_tuner_race,non_tuner_filter,tc,tuner_min,tuner_max,non_tuner_min,non_tuner_max)
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SMATERIAL)
local picked=Group.SelectUnselect(addable,sg,tp,finishable,true,selected_level_min,target_level)
......@@ -3664,12 +3696,13 @@ function Synchro.SynOperation()
end
end
function Synchro.IsSelectionValid(selection,target_level,tuner_filter,non_tuner_filter,tc,tuner_min,tuner_max,non_tuner_min,non_tuner_max)
function Synchro.IsSelectionValid(selection,target_level,tuner_race,tuner_filter,non_tuner_race,non_tuner_filter,tc,tuner_min,tuner_max,non_tuner_min,non_tuner_max)
local states=Synchro.BuildStatesFromSelection(
selection,
tuner_filter,non_tuner_filter,
tuner_race,tuner_filter,
non_tuner_race,non_tuner_filter,
Synchro.LevelMapper,
tc,math.huge
tc,target_level
)
for _,state in ipairs(states) do
if state.tuner_count<=tuner_max
......@@ -3734,7 +3767,7 @@ function Synchro.UpdatepossibleSums(possible_sums,card_levels,prune_level)
return new_sums
end
function Synchro.BuildStatesFromSelection(selection,tuner_filter,non_tuner_filter,base_mapper,tc,prune_level)
function Synchro.BuildStatesFromSelection(selection,tuner_race,tuner_filter,non_tuner_race,non_tuner_filter,base_mapper,tc,prune_level)
local states={
{
possible_sums={[0]=true},
......@@ -3744,6 +3777,7 @@ function Synchro.BuildStatesFromSelection(selection,tuner_filter,non_tuner_filte
level_mapper_priority=0,
hand_count_limit=0,
hand_count=0,
genomix_race=nil,
}
}
......@@ -3754,11 +3788,11 @@ function Synchro.BuildStatesFromSelection(selection,tuner_filter,non_tuner_filte
for _,st in ipairs(states) do
for _,diff in ipairs(Synchro.GenerateVariantForCard(
st,card,idx,tc,tuner_filter,non_tuner_filter
st,card,idx,tc,tuner_race,tuner_filter,non_tuner_race,non_tuner_filter
)) do
-- merge diff into full state
local new_state = Synchro.ApplyVariantState(
st,card,diff,tuner_filter,non_tuner_filter,tc,prune_level
st,card,diff,tuner_race,tuner_filter,non_tuner_race,non_tuner_filter,tc,prune_level
)
table.insert(next_states,new_state)
end
......@@ -3789,6 +3823,11 @@ function Synchro.IsTatsunoko(c)
return c:IsHasEffect(55863245)~=nil
end
--- @param c Card
function Synchro.IsGenomix(c)
return c:IsHasEffect(42155488)~=nil
end
function Synchro.SortMaterials(materials,tc,tuner_filter)
table.sort(materials,function(a,b)
if Synchro.IsMono(a)~=Synchro.IsMono(b) then
......@@ -3797,6 +3836,9 @@ function Synchro.SortMaterials(materials,tc,tuner_filter)
if Synchro.IsFlower(a)~=Synchro.IsFlower(b) then
return Synchro.IsFlower(a) -- then flowers
end
if Synchro.IsGenomix(a)~=Synchro.IsGenomix(b) then
return Synchro.IsGenomix(a) -- then Genomix
end
if Synchro.IsTatsunoko(a)~=Synchro.IsTatsunoko(b) then
return Synchro.IsTatsunoko(a) -- then tatsunoko
end
......@@ -3816,8 +3858,20 @@ function Synchro.IsHandAlter(c)
return Synchro.IsTatsunoko(c)
end
function Synchro.IsRaceAlter(c)
return Synchro.IsGenomix(c)
end
function Synchro.IsMandatory(c)
return Synchro.IsMono(c) or Synchro.IsGenomix(c)
end
function Synchro.IsNoHarm(c)
return Synchro.IsTatsunoko(c)
end
-- Helper to generate only the variant-specific diffs for a card
function Synchro.GenerateVariantForCard(st,card,selected_count,tc,tuner_filter,non_tuner_filter)
function Synchro.GenerateVariantForCard(st,card,selected_count,tc,tuner_race,tuner_filter,non_tuner_race,non_tuner_filter)
local variants = {}
-- MonoSynchron first/second
if Synchro.IsMono(card) then
......@@ -3838,8 +3892,18 @@ function Synchro.GenerateVariantForCard(st,card,selected_count,tc,tuner_filter,n
end
end
if Synchro.IsGenomix(card) then
local declared_race=card:IsHasEffect(42155488):GetLabel()
if st.genomix_race~=nil then
assert(declared_race==st.genomix_race,"we activated 2 Genomix Fighter with 2 different races but we still have monster to summon")
table.insert(variants,{})
else
table.insert(variants,{genomix_race=declared_race})
end
end
-- Normal branch
if not (Synchro.IsMono(card) or Synchro.IsTatsunoko(card)) then
if not (Synchro.IsMandatory(card) or Synchro.IsNoHarm(card)) then
table.insert(variants,{})
end
......@@ -3864,7 +3928,7 @@ end
-- Helper to apply a diff to a base state
function Synchro.ApplyVariantState(st,card,diff,tuner_filter,non_tuner_filter,tc,prune_level)
function Synchro.ApplyVariantState(st,card,diff,tuner_race,tuner_filter,non_tuner_race,non_tuner_filter,tc,prune_level)
-- compute increments using provided filters
local tuner_inc=tuner_filter(card,tc) and 1 or 0
local non_tuner_inc=non_tuner_filter(card,tc) and 1 or 0
......@@ -3882,5 +3946,6 @@ function Synchro.ApplyVariantState(st,card,diff,tuner_filter,non_tuner_filter,tc
level_mapper_priority=diff.level_mapper_priority or st.level_mapper_priority,
hand_count_limit=diff.hand_count_limit or st.hand_count_limit,
hand_count=st.hand_count+hand_inc,
genomix_race=diff.genomix_race or st.genomix_race
}
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