Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions cards_specific_functions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -290,17 +290,14 @@ function Witchcrafter.CreateCostReplaceEffect(c)
e:SetValue(function(base,extracon,e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then
local c=e:GetHandler()
return c:IsSetCard(SET_WITCHCRAFTER) and c:IsControler(tp) and c:IsLocation(LOCATION_MZONE)
end
local ctrl,loc,setcodes=Duel.GetChainInfo(0,CHAININFO_TRIGGERING_CONTROLER,CHAININFO_TRIGGERING_LOCATION,CHAININFO_TRIGGERING_SETCODES)
if ctrl==1-tp or loc~=LOCATION_MZONE then return false end
for _,setcode in ipairs(setcodes) do
if (SET_WITCHCRAFTER&0xfff)==(setcode&0xfff) and (SET_WITCHCRAFTER&setcode)==SET_WITCHCRAFTER then return true end
return c:IsControler(tp) and c:IsLocation(LOCATION_MZONE) and c:IsSetCard(SET_WITCHCRAFTER)
end
return Chain.IsTriggeringPlayer(0,tp) and Chain.IsTriggeringLocation(0,LOCATION_MZONE) and Chain.IsTriggeringSetcode(0,SET_WITCHCRAFTER)
end)
return e
end


--Special Summon limit for "Evil HERO" Fusion monsters
function Auxiliary.EvilHeroLimit(e,se,sp,st)
return se:GetHandler():IsCode(CARD_DARK_FUSION) or (Duel.IsPlayerAffectedByEffect(e:GetHandlerPlayer(),SKILL_DARK_UNITY) and se:GetHandler():IsCode(CARD_SUPER_POLYMERIZATION))
Expand Down
231 changes: 231 additions & 0 deletions chain.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
Chain={}

local function chaininfo_fn(info)
return function(ch)
return Duel.GetChainInfo(ch or 0,info)
end
end

Chain.GetTargetCards = chaininfo_fn(CHAININFO_TARGET_CARDS)
Chain.GetTargetPlayer = chaininfo_fn(CHAININFO_TARGET_PLAYER)
Chain.GetTargetParam = chaininfo_fn(CHAININFO_TARGET_PARAM)

Chain.GetDisableReason = chaininfo_fn(CHAININFO_DISABLE_REASON)
Chain.GetDisablePlayer = chaininfo_fn(CHAININFO_DISABLE_PLAYER)

Chain.GetID = chaininfo_fn(CHAININFO_CHAIN_ID)

Chain.GetTriggeringEffect = chaininfo_fn(CHAININFO_TRIGGERING_EFFECT)
Chain.GetTriggeringPlayer = chaininfo_fn(CHAININFO_TRIGGERING_PLAYER)
Chain.GetTriggeringControler = chaininfo_fn(CHAININFO_TRIGGERING_CONTROLER)
Chain.GetTriggeringLocation = chaininfo_fn(CHAININFO_TRIGGERING_LOCATION)
Chain.GetTriggeringLocationSymbolic = chaininfo_fn(CHAININFO_TRIGGERING_LOCATION_SYMBOLIC)
Chain.GetTriggeringSequence = chaininfo_fn(CHAININFO_TRIGGERING_SEQUENCE)
Chain.GetTriggeringLocationSymbolic = chaininfo_fn(CHAININFO_TRIGGERING_SEQUENCE_SYMBOLIC)
Chain.GetTriggeringPosition = chaininfo_fn(CHAININFO_TRIGGERING_POSITION)
Chain.GetTriggeringType = chaininfo_fn(CHAININFO_TRIGGERING_TYPE)
Chain.GetTriggeringLevel = chaininfo_fn(CHAININFO_TRIGGERING_LEVEL)
Chain.GetTriggeringRank = chaininfo_fn(CHAININFO_TRIGGERING_RANK)
Chain.GetTriggeringAttribute = chaininfo_fn(CHAININFO_TRIGGERING_ATTRIBUTE)
Chain.GetTriggeringRace = chaininfo_fn(CHAININFO_TRIGGERING_RACE)
Chain.GetTriggeringATK = chaininfo_fn(CHAININFO_TRIGGERING_ATTACK)
Chain.GetTriggeringDEF = chaininfo_fn(CHAININFO_TRIGGERING_DEFENSE)
Chain.GetTriggeringStatus = chaininfo_fn(CHAININFO_TRIGGERING_STATUS)
Chain.GetTriggeringSummonLocation = chaininfo_fn(CHAININFO_TRIGGERING_SUMMON_LOCATION)
Chain.GetTriggeringSummonType = chaininfo_fn(CHAININFO_TRIGGERING_SUMMON_TYPE)
Chain.GetTriggeringSetcodes = chaininfo_fn(CHAININFO_TRIGGERING_SETCODES)

Chain.IsTriggeringCardProperlySummoned = chaininfo_fn(CHAININFO_TRIGGERING_SUMMON_PROC_COMPLETE)

function Chain.GetTriggeringCode(ch)
return Duel.GetChainInfo(ch or 0,CHAININFO_TRIGGERING_CODE,CHAININFO_TRIGGERING_CODE2)
end

-- boolean check versions for chain info functions

local function chaininfo_equals(fn)
return function(ch,val)
return fn(ch)==val
end
end

Chain.IsTriggeringEffect = chaininfo_equals(Chain.GetTriggeringEffect)
Chain.IsTriggeringPlayer = chaininfo_equals(Chain.GetTriggeringPlayer)
Chain.IsDisablePlayer = chaininfo_equals(Chain.GetDisablePlayer)
Chain.IsTriggeringControler = chaininfo_equals(Chain.GetTriggeringControler)
Chain.IsTriggeringATK = chaininfo_equals(Chain.GetTriggeringATK)
Chain.IsTriggeringDEF = chaininfo_equals(Chain.GetTriggeringDEF)

local function chaininfo_includes_bits(fn)
return function(ch,val)
local res=fn(ch)
return res and (res&val)>0
end
end

Chain.IsTriggeringPosition = chaininfo_includes_bits(Chain.GetTriggeringPosition)
Chain.IsTriggeringType = chaininfo_includes_bits(Chain.GetTriggeringType)
Chain.IsTriggeringAttribute = chaininfo_includes_bits(Chain.GetTriggeringAttribute)
Chain.IsTriggeringRace = chaininfo_includes_bits(Chain.GetTriggeringRace)
Chain.IsTriggeringStatus = chaininfo_includes_bits(Chain.GetTriggeringStatus)
Chain.IsTriggeringSummonLocation = chaininfo_includes_bits(Chain.GetTriggeringSummonLocation)
Chain.IsTriggeringSummonType = chaininfo_includes_bits(Chain.GetTriggeringSummonType)

--integrates symbolic locations to be consistent with Card.IsLocation
Chain.IsTriggeringLocation = aux.OR(
chaininfo_includes_bits(Chain.GetTriggeringLocation),
chaininfo_includes_bits(Chain.GetTriggeringLocationSymbolic)
)

local function chaininfo_equals_any(fn)
return function(ch,...)
local res=fn(ch)
for _,val in ipairs({...}) do
if res==val then return true end
end
return false
end
end

Chain.IsTriggeringSequence = chaininfo_equals_any(Chain.GetTriggeringSequence)
Chain.IsTriggeringLevel = chaininfo_equals_any(Chain.GetTriggeringLevel)
Chain.IsTriggeringRank = chaininfo_equals_any(Chain.GetTriggeringRank)

function Chain.IsTriggeringCode(ch,...)
local code1,code2=Chain.GetTriggeringCode(ch)
for _,code in ipairs({...}) do
if code==code1 or code==code2 then return true end
end
return false
end

function Chain.IsTriggeringSetcode(ch,setcodes)
local trig_setcodes=Chain.GetTriggeringSetcodes(ch)
if not trig_setcodes then return false end
if type(setcodes)=="number" then
setcodes={setcodes}
end
for _,setcode in ipairs(setcodes) do
for _,trig_setcode in ipairs(trig_setcodes) do
if (setcode&0xfff)==(trig_setcode&0xfff) and (setcode&trig_setcode)==setcode then return true end
end
end
return false
end

function Chain.IsTriggeringRaceExcept(ch,race)
return Chain.IsTriggeringRace(ch,RACE_ALL&~race)
end

function Chain.IsTriggeringAttributeExcept(ch,attr)
return Chain.IsTriggeringAttribute(ch,ATTRIBUTE_ALL&~attr)
end

-- dynamic chain properties (current properties if the card is still the same copy, otherwise triggering properties)
local function chain_prop(current_fn,triggering_fn)
-- this is counting on the assumption that the additional parameters of the `current_fn` functions
-- won't cause errors with the `triggering_fn` functions, e.g., `Card.GetRace` vs `Chain.GetTriggeringRace`
return function(ch,...)
local eff=Chain.GetTriggeringEffect(ch)
local ec=eff:GetHandler()
if ec:IsRelateToEffect(eff) and ec:IsFaceup() then
return current_fn(ec,...)
end
return triggering_fn(ch,...)
end
end

Chain.GetControler = chain_prop(Card.GetControler, Chain.GetTriggeringControler)
Chain.GetLocation = chain_prop(Card.GetLocation, Chain.GetTriggeringLocation)
Chain.GetSequence = chain_prop(Card.GetSequence, Chain.GetTriggeringSequence)
Chain.GetPosition = chain_prop(Card.GetPosition, Chain.GetTriggeringPosition)
Chain.GetCode = chain_prop(Card.GetCode, Chain.GetTriggeringCode)
Chain.GetType = chain_prop(Card.GetType, Chain.GetTriggeringType)
Chain.GetLevel = chain_prop(Card.GetLevel, Chain.GetTriggeringLevel)
Chain.GetRank = chain_prop(Card.GetRank, Chain.GetTriggeringRank)
Chain.GetAttribute = chain_prop(Card.GetAttribute, Chain.GetTriggeringAttribute)
Chain.GetRace = chain_prop(Card.GetRace, Chain.GetTriggeringRace)
Chain.GetATK = chain_prop(Card.GetAttack, Chain.GetTriggeringATK)
Chain.GetDEF = chain_prop(Card.GetDefense, Chain.GetTriggeringDEF)
Chain.GetSummonLocation = chain_prop(Card.GetSummonLocation, Chain.GetTriggeringSummonLocation)
Chain.GetSummonType = chain_prop(Card.GetSummonType, Chain.GetTriggeringSummonType)
Chain.GetSetcodes = chain_prop(Card.GetSetCard, Chain.GetTriggeringSetcodes)

Chain.IsControler = chain_prop(Card.IsControler, Chain.IsTriggeringControler)
Chain.IsLocation = chain_prop(Card.IsLocation, Chain.IsTriggeringLocation)
Chain.IsSequence = chain_prop(Card.IsSequence, Chain.IsTriggeringSequence)
Chain.IsPosition = chain_prop(Card.IsPosition, Chain.IsTriggeringPosition)
Chain.IsCode = chain_prop(Card.IsCode, Chain.IsTriggeringCode)
Chain.IsType = chain_prop(Card.IsType, Chain.IsTriggeringType)
Chain.IsLevel = chain_prop(Card.IsLevel, Chain.IsTriggeringLevel)
Chain.IsRank = chain_prop(Card.IsRank, Chain.IsTriggeringRank)
Chain.IsAttribute = chain_prop(Card.IsAttribute, Chain.IsTriggeringAttribute)
Chain.IsRace = chain_prop(Card.IsRace, Chain.IsTriggeringRace)
Chain.IsATK = chain_prop(Card.IsAttack, Chain.IsTriggeringATK)
Chain.IsDEF = chain_prop(Card.IsDefense, Chain.IsTriggeringDEF)
Chain.IsSummonLocation = chain_prop(Card.IsSummonLocation, Chain.IsTriggeringSummonLocation)
Chain.IsSummonType = chain_prop(Card.IsSummonType, Chain.IsTriggeringSummonType)
Chain.IsSetcode = chain_prop(Card.IsSetCard, Chain.IsTriggeringSetcode)

function Chain.IsRaceExcept(ch,race)
return Chain.IsRace(ch,RACE_ALL&~race)
end

function Chain.IsAttributeExcept(ch,attr)
return Chain.IsAttribute(ch,ATTRIBUTE_ALL&~attr)
end

-- a mechanism for saving any amount of custom information that is strictly associated to a specific chain link
local data_table={}

do
-- prevent Debug.ReloadFieldBegin from resetting the global effect
local old=Debug.ReloadFieldBegin
function Debug.ReloadFieldBegin(...)
old(...)
local data_reset=Effect.GlobalEffect()
data_reset:SetType(EFFECT_TYPE_FIELD+EFFECT_TYPE_CONTINUOUS)
data_reset:SetCode(EVENT_CHAIN_END)
data_reset:SetCountLimit(1)
data_reset:SetOperation(function() data_table={} end)
Duel.RegisterEffect(data_reset,0)
end
end

local shared_data_key={} -- dummy table to be used as a unique key

function Chain.Data(ch,key)
local current_link=Chain.GetCurrentLink()
if current_link==0 then
return error("Attempted to access Chain Data table while there is currently no Chain",2)
elseif ch and ch>current_link then
return error("Attempted to access Chain Link higher than current Chain",2)
end

if not ch or ch==0 then ch=current_link end

local cid=Chain.GetID(ch)
local chain_link_data=data_table[cid] or {}
data_table[cid]=chain_link_data

-- if no key is supplied, use a default key for shared data table
key=key or shared_data_key

chain_link_data[key]=chain_link_data[key] or {}
return chain_link_data[key]
end

function Effect.GetChainData(e,ch)
return Chain.Data(ch,e)
end

-- aliases for existing chain-related functions (should eventually become the main names)
Chain.ChangeOperation = Duel.ChangeChainOperation
Chain.CanTarget = Duel.CheckChainTarget
Chain.HasUniqueCardNames = Duel.CheckChainUniqueness
Chain.GetCurrentLink = Duel.GetCurrentChain
Chain.IsDisablable = Duel.IsChainDisablable
Chain.IsNegatable = Duel.IsChainNegatable
Chain.IsResolving = Duel.IsChainSolving
Chain.SetLimit = Duel.SetChainLimit
Chain.SetLimitTillEnd = Duel.SetChainLimitTillChainEnd
13 changes: 4 additions & 9 deletions official/c11464648.lua
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,10 @@ function s.immcon(e)
return eqpg and eqpg:IsExists(s.equipfilter,1,nil)
end
function s.immval(e,te)
local tc=te:GetHandler()
local trig_loc,trig_setcodes=Duel.GetChainInfo(0,CHAININFO_TRIGGERING_LOCATION,CHAININFO_TRIGGERING_SETCODES)
if not Duel.IsChainSolving() or (tc:IsRelateToEffect(te) and tc:IsFaceup() and tc:IsLocation(trig_loc)) then
return not tc:IsSetCard(SET_FIENDSMITH)
if Chain.IsResolving() and Chain.GetTriggeringEffect()==te then
return not Chain.IsSetCard(0,SET_FIENDSMITH)
end
for _,setcode in ipairs(trig_setcodes) do
if (SET_FIENDSMITH&0xfff)==(setcode&0xfff) and (SET_FIENDSMITH&setcode)==SET_FIENDSMITH then return false end
end
return true
return not te:GetHandler():IsSetCard(SET_FIENDSMITH)
end
function s.tgcost(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then return Duel.IsExistingMatchingCard(Card.IsDiscardable,tp,LOCATION_HAND,0,1,nil) end
Expand Down Expand Up @@ -96,4 +91,4 @@ function s.thop(e,tp,eg,ep,ev,re,r,rp)
if tc:IsRelateToEffect(e) then
Duel.SendtoHand(tc,nil,REASON_EFFECT)
end
end
end
8 changes: 2 additions & 6 deletions official/c11688916.lua
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,7 @@ function s.immcon(e)
return a and b and ((a:GetScale()+b:GetScale())%2==1)
end
function s.immval(e,ct)
local trig_player,trig_setcodes=Duel.GetChainInfo(ct,CHAININFO_TRIGGERING_PLAYER,CHAININFO_TRIGGERING_SETCODES)
if trig_player==1-e:GetHandlerPlayer() then return false end
for _,setcode in ipairs(trig_setcodes) do
if (SET_SOLFACHORD&0xfff)==(setcode&0xfff) and (SET_SOLFACHORD&setcode)==SET_SOLFACHORD then return true end
end
return Chain.IsTriggeringPlayer(ct,e:GetHandlerPlayer()) and Chain.IsSetcode(ct,SET_SOLFACHORD)
end
function s.deckthfilter(c)
return c:IsSetCard(SET_SOLFACHORD) and not c:IsCode(id) and c:IsAbleToHand()
Expand Down Expand Up @@ -117,4 +113,4 @@ function s.gyedthop(e,tp,eg,ep,ev,re,r,rp)
Duel.SendtoHand(g,nil,REASON_EFFECT)
Duel.ConfirmCards(1-tp,g)
end
end
end
13 changes: 4 additions & 9 deletions official/c1340142.lua
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,10 @@ function s.matcheck(g,lc,sumtype,tp)
return g:IsExists(s.matfilter,1,nil,lc,sumtype,tp)
end
function s.immval(e,te)
local tc=te:GetHandler()
local trig_loc,trig_setcodes=Duel.GetChainInfo(0,CHAININFO_TRIGGERING_LOCATION,CHAININFO_TRIGGERING_SETCODES)
if not Duel.IsChainSolving() or (tc:IsRelateToEffect(te) and tc:IsFaceup() and tc:IsLocation(trig_loc)) then
return not tc:IsSetCard(SET_VAALMONICA)
if Chain.IsResolving() and Chain.GetTriggeringEffect()==te then
return not Chain.IsSetcode(0,SET_VAALMONICA)
end
for _,setcode in ipairs(trig_setcodes) do
if (SET_VAALMONICA&0xfff)==(setcode&0xfff) and (SET_VAALMONICA&setcode)==SET_VAALMONICA then return false end
end
return true
return not te:GetHandler():IsSetCard(SET_VAALMONICA)
end
function s.atkfilter(c)
return c:IsLevel(4) and c:IsSetCard(SET_VAALMONICA) and c:IsFaceup()
Expand All @@ -72,4 +67,4 @@ function s.negsumop(e,tp,eg,ep,ev,re,r,rp)
Duel.BreakEffect()
Duel.RemoveCounter(tp,1,0,COUNTER_RESONANCE,3,REASON_EFFECT)
end
end
end
13 changes: 7 additions & 6 deletions official/c14532163.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,20 @@ function s.destg(e,tp,eg,ep,ev,re,r,rp,chk)
local b1=#g1>0
local b2=#g2>0
if chk==0 then return b1 or b2 end
local op=Duel.SelectEffect(tp,
local cd=e:GetChainData()
cd.choice=Duel.SelectEffect(tp,
{b1,aux.Stringid(id,0)},
{b2,aux.Stringid(id,1)})
e:SetLabel(op)
local g=(op==1 and g1 or g2)
local g=(cd.choice==1 and g1 or g2)
Duel.SetOperationInfo(0,CATEGORY_DESTROY,g,#g,0,0)
end
function s.desop(e,tp,eg,ep,ev,re,r,rp)
if e:GetLabel()==1 then
local cd=e:GetChainData()
if cd.choice==1 then
local g=Duel.GetMatchingGroup(Card.IsAttackPos,tp,0,LOCATION_MZONE,nil)
if #g>0 then Duel.Destroy(g,REASON_EFFECT) end
else
elseif cd.choice==2 then
local g=Duel.GetMatchingGroup(Card.IsSpellTrap,tp,0,LOCATION_ONFIELD,nil)
if #g>0 then Duel.Destroy(g,REASON_EFFECT) end
end
end
end
12 changes: 2 additions & 10 deletions official/c15001940.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,7 @@ function s.initial_effect(c)
end
s.listed_series={SET_RECIPE,SET_NOUVELLES}
function s.regcon(e,tp,eg,ep,ev,re,r,rp)
if not (re and re:IsMonsterEffect()) then return false end
local rc=re:GetHandler()
local trig_loc,trig_setcodes=Duel.GetChainInfo(0,CHAININFO_TRIGGERING_LOCATION,CHAININFO_TRIGGERING_SETCODES)
if not Duel.IsChainSolving() or (rc:IsRelateToEffect(re) and rc:IsFaceup() and rc:IsLocation(trig_loc)) then
return rc:IsSetCard(SET_NOUVELLES)
end
for _,set in ipairs(trig_setcodes) do
if (SET_NOUVELLES&0xfff)==(set&0xfff) and (SET_NOUVELLES&set)==SET_NOUVELLES then return true end
end
return Chain.IsSetcode(0,SET_NOUVELLES) and re:IsMonsterEffect()
end
function s.tdtg(e,tp,eg,ep,ev,re,r,rp,chk,chkc)
if chkc then return chkc:IsLocation(LOCATION_GRAVE) and chkc:IsAbleToDeck() end
Expand Down Expand Up @@ -97,4 +89,4 @@ function s.spop(e,tp,eg,ep,ev,re,r,rp)
Duel.SpecialSummon(g,0,tp,tp,false,true,POS_FACEUP)
end
end
end
end
Loading