diff --git a/official/c18486927.lua b/official/c18486927.lua index fcec4e3b6e..7eda838b00 100644 --- a/official/c18486927.lua +++ b/official/c18486927.lua @@ -2,20 +2,21 @@ --Ancient Gear Gadget local s,id=GetID() function s.initial_effect(c) - --declare card + --If this card is Normal or Special Summoned: You can declare 1 card type (Monster, Spell, or Trap); this turn, if your monster attacks, your opponent cannot activate Spell/Trap Cards or monster effects (whichever was declared) until the end of the Damage Step local e1=Effect.CreateEffect(c) + e1:SetDescription(aux.Stringid(id,0)) e1:SetType(EFFECT_TYPE_SINGLE+EFFECT_TYPE_TRIGGER_O) - e1:SetCode(EVENT_SUMMON_SUCCESS) e1:SetProperty(EFFECT_FLAG_DELAY) + e1:SetCode(EVENT_SUMMON_SUCCESS) e1:SetTarget(s.dectg) e1:SetOperation(s.decop) c:RegisterEffect(e1) local e2=e1:Clone() e2:SetCode(EVENT_SPSUMMON_SUCCESS) c:RegisterEffect(e2) - --name change + --Once per turn: You can declare 1 "Gadget" monster's card name; until the End Phase, this card's name becomes that name local e3=Effect.CreateEffect(c) - e3:SetDescription(aux.Stringid(id,0)) + e3:SetDescription(aux.Stringid(id,1)) e3:SetType(EFFECT_TYPE_IGNITION) e3:SetRange(LOCATION_MZONE) e3:SetCountLimit(1) @@ -27,59 +28,43 @@ s.listed_series={SET_GADGET} function s.dectg(e,tp,eg,ep,ev,re,r,rp,chk) if chk==0 then return true end Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_CARDTYPE) - e:SetLabel(Duel.SelectOption(tp,70,71,72)) + e:GetChainData().choice=Duel.SelectOption(tp,70,71,72) end function s.decop(e,tp,eg,ep,ev,re,r,rp) - local c=e:GetHandler() - local opt=e:GetLabel() - local ct=nil - if opt==0 then - ct=TYPE_MONSTER - elseif opt==1 then - ct=TYPE_SPELL - else - ct=TYPE_TRAP - end - local e1=Effect.CreateEffect(c) + local cd=e:GetChainData() + local typ=1<-2 and #rg1>0 and #rg2>0 - and aux.SelectUnselectGroup(rg,e,tp,2,2,s.rescon,0) + local rg=Duel.GetMatchingGroup(s.spfilter,tp,LOCATION_MZONE,0,nil) + return aux.SelectUnselectGroup(rg,e,tp,2,2,s.rescon,0) end function s.sptg(e,tp,eg,ep,ev,re,r,rp,c) - local rg=Duel.GetMatchingGroup(s.spfilter,tp,LOCATION_MZONE,0,nil,RACE_FAIRY|RACE_DRAGON) + local rg=Duel.GetMatchingGroup(s.spfilter,tp,LOCATION_MZONE,0,nil) local g=aux.SelectUnselectGroup(rg,e,tp,2,2,s.rescon,1,tp,HINTMSG_TOGRAVE) if #g>0 then - g:KeepAlive() e:SetLabelObject(g) return true end @@ -63,55 +50,46 @@ function s.spop(e,tp,eg,ep,ev,re,r,rp,c) local g=e:GetLabelObject() if not g then return end Duel.SendtoGrave(g,REASON_COST) - g:DeleteGroup() end -function s.anctg(e,tp,eg,ep,ev,re,r,rp,chk) - if chk==0 then - if not Duel.IsPlayerCanDiscardDeck(tp,3) then return false end - local g=Duel.GetDecktopGroup(tp,3) - return g:FilterCount(Card.IsAbleToHand,nil)>0 +function s.exctg(e,tp,eg,ep,ev,re,r,rp,chk) + if chk==0 then return Duel.IsPlayerCanDiscardDeck(tp,3) + and Duel.GetDecktopGroup(tp,3):IsExists(Card.IsAbleToHand,1,nil) end + local codes={} + for i=1,3 do + table.insert(codes,Duel.AnnounceCard(tp,DF.IsMainDeckCard())) end - s.announce_filter={TYPE_EXTRA,OPCODE_ISTYPE,OPCODE_NOT} - Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_CODE) - local ac1=Duel.AnnounceCard(tp,table.unpack(s.announce_filter)) - Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_CODE) - local ac2=Duel.AnnounceCard(tp,table.unpack(s.announce_filter)) - Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_CODE) - local ac3=Duel.AnnounceCard(tp,table.unpack(s.announce_filter)) - e:SetOperation(s.retop(ac1,ac2,ac3)) + e:GetChainData().announced_card=codes +end +function s.thfilter(c,...) + return c:IsCode(...) and c:IsAbleToHand() end -function s.hfilter(c,code1,code2,code3) - return c:IsCode(code1,code2,code3) and c:IsAbleToHand() +function s.excop(e,tp,eg,ep,ev,re,r,rp) + if not Duel.IsPlayerCanDiscardDeck(tp,3) then return end + local cd=e:GetChainData() + Duel.ConfirmDecktop(tp,3) + local g=Duel.GetDecktopGroup(tp,3) + local hg,gg=g:Split(s.thfilter,nil,table.unpack(cd.announced_card)) + if #hg>0 then + Duel.DisableShuffleCheck() + Duel.SendtoHand(hg,nil,REASON_EFFECT) + Duel.ConfirmCards(1-tp,hg) + Duel.ShuffleHand(tp) + end + if #gg>0 then + Duel.DisableShuffleCheck() + Duel.SendtoGrave(gg,REASON_EFFECT|REASON_EXCAVATE) + end + local c=e:GetHandler() + if c:IsRelateToEffect(e) then + --This card's ATK and DEF each become equal to the number of cards added to your hand by this effect x 1000 + local e1=Effect.CreateEffect(c) + e1:SetType(EFFECT_TYPE_SINGLE) + e1:SetCode(EFFECT_SET_ATTACK_FINAL) + e1:SetValue(#hg*1000) + e1:SetReset(RESET_EVENT|RESETS_STANDARD_DISABLE) + c:RegisterEffect(e1) + local e2=e1:Clone() + e2:SetCode(EFFECT_SET_DEFENSE_FINAL) + c:RegisterEffect(e2) + end end -function s.retop(code1,code2,code3) - return - function (e,tp,eg,ep,ev,re,r,rp) - if not Duel.IsPlayerCanDiscardDeck(tp,3) then return end - local c=e:GetHandler() - Duel.ConfirmDecktop(tp,3) - local g=Duel.GetDecktopGroup(tp,3) - local hg=g:Filter(s.hfilter,nil,code1,code2,code3) - g:Sub(hg) - if #hg~=0 then - Duel.DisableShuffleCheck() - Duel.SendtoHand(hg,nil,REASON_EFFECT) - Duel.ConfirmCards(1-tp,hg) - Duel.ShuffleHand(tp) - end - if #g~=0 then - Duel.DisableShuffleCheck() - Duel.SendtoGrave(g,REASON_EFFECT|REASON_EXCAVATE) - end - if c:IsRelateToEffect(e) then - local e1=Effect.CreateEffect(c) - e1:SetType(EFFECT_TYPE_SINGLE) - e1:SetCode(EFFECT_SET_ATTACK_FINAL) - e1:SetValue(#hg*1000) - e1:SetReset(RESET_EVENT|RESETS_STANDARD_DISABLE) - c:RegisterEffect(e1) - local e2=e1:Clone() - e2:SetCode(EFFECT_SET_DEFENSE_FINAL) - c:RegisterEffect(e2) - end - end -end \ No newline at end of file diff --git a/official/c50078320.lua b/official/c50078320.lua index 7570664db7..2a134db720 100644 --- a/official/c50078320.lua +++ b/official/c50078320.lua @@ -2,7 +2,7 @@ --Engraver of the Mark local s,id=GetID() function s.initial_effect(c) - --Declare 1 other card name + --When your opponent activates a card or effect by declaring exactly 1 card name (Quick Effect): You can send this card from your hand to the GY; declare 1 other card name. local e1=Effect.CreateEffect(c) e1:SetDescription(aux.Stringid(id,0)) e1:SetType(EFFECT_TYPE_QUICK_O) @@ -12,7 +12,7 @@ function s.initial_effect(c) e1:SetCost(Cost.SelfToGrave) e1:SetOperation(s.declop) c:RegisterEffect(e1) - --Destroy 1 face-up card on the field during the End Phase of the next turn + --Once per turn (Quick Effect): You can target 1 face-up card on the field; destroy it during the End Phase of the next turn local e2=Effect.CreateEffect(c) e2:SetDescription(aux.Stringid(id,1)) e2:SetCategory(CATEGORY_DESTROY) @@ -27,19 +27,22 @@ function s.initial_effect(c) c:RegisterEffect(e2) end function s.declcon(e,tp,eg,ep,ev,re,r,rp) - local ex,cg,ct,cp,cv=Duel.GetOperationInfo(ev,CATEGORY_ANNOUNCE) - return rp==1-tp and ex and (cv&ANNOUNCE_CARD+ANNOUNCE_CARD_FILTER)~=0 + local ac=re:GetChainData(ev).announced_card + return rp==1-tp and ac and (type(ac)=="number" or #ac==1) end function s.declop(e,tp,eg,ep,ev,re,r,rp) - local ex,cg,ct,cp,cv=Duel.GetOperationInfo(ev,CATEGORY_ANNOUNCE) - local ac=0 + local rcd=re:GetChainData(ev) Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_CODE) - if (cv&ANNOUNCE_CARD)~=0 then - ac=Duel.AnnounceCard(tp,cv) + if rcd.announce_filter then + local announce_filter=type(rcd.announce_filter)=="function" + and rcd.announce_filter(e,tp,eg,ep,ev,re,r,rp) + or rcd.announce_filter + --can't exclude the announced name since we can't guarantee there'll be a declarable name left, + --and having a card declaration prompt with no valid options leads to a soft lock + rcd.announced_card=Duel.AnnounceCard(tp,announce_filter) else - ac=Duel.AnnounceCard(tp,table.unpack(re:GetHandler().announce_filter)) + rcd.announced_card=Duel.AnnounceCard(tp,~DF.IsCode(rcd.announced_card)) end - Duel.ChangeTargetParam(ev,ac) end function s.destg(e,tp,eg,ep,ev,re,r,rp,chk,chkc) if chkc then return chkc:IsOnField() and chkc:IsFaceup() end @@ -62,4 +65,4 @@ function s.desop(e,tp,eg,ep,ev,re,r,rp) nil,2,aux.Stringid(id,2) ) end -end \ No newline at end of file +end diff --git a/official/c65681983.lua b/official/c65681983.lua index f1014fd5e4..9001e0cc20 100644 --- a/official/c65681983.lua +++ b/official/c65681983.lua @@ -3,8 +3,9 @@ --Scripted by AlphaKretin local s,id=GetID() function s.initial_effect(c) - --Activate + --Declare 1 card name; banish 1 of that declared card from your Main Deck, and if you do, negate its effects, as well as the activated effects and effects on the field of cards with the same original name, until the end of this turn local e1=Effect.CreateEffect(c) + e1:SetDescription(aux.Stringid(id,0)) e1:SetCategory(CATEGORY_REMOVE) e1:SetType(EFFECT_TYPE_ACTIVATE) e1:SetCode(EVENT_FREE_CHAIN) @@ -15,52 +16,38 @@ function s.initial_effect(c) end function s.rmtg(e,tp,eg,ep,ev,re,r,rp,chk) if chk==0 then return Duel.IsExistingMatchingCard(Card.IsAbleToRemove,tp,LOCATION_DECK,0,1,nil) end - local g=Duel.GetMatchingGroup(Card.IsAbleToRemove,tp,LOCATION_DECK,0,nil) - local ids={} - for tc in aux.Next(g) do - ids[tc:GetCode()]=true - end - s.announce_filter={} - for code,i in pairs(ids) do - if #s.announce_filter==0 then - table.insert(s.announce_filter,code) - table.insert(s.announce_filter,OPCODE_ISCODE) - else - table.insert(s.announce_filter,code) - table.insert(s.announce_filter,OPCODE_ISCODE) - table.insert(s.announce_filter,OPCODE_OR) - end - end - local ac=Duel.AnnounceCard(tp,table.unpack(s.announce_filter)) - Duel.SetTargetParam(ac) + local ids=Duel.GetMatchingGroup(Card.IsAbleToRemove,tp,LOCATION_DECK,0,nil):GetClass(Card.GetCode) + local announce_filter=DF.IsCode(ids) + Duel.AnnounceCard(tp,announce_filter) Duel.SetOperationInfo(0,CATEGORY_REMOVE,nil,1,tp,LOCATION_DECK) - Duel.SetOperationInfo(0,CATEGORY_ANNOUNCE,nil,0,tp,ANNOUNCE_CARD_FILTER) + --if the opponent tries to overwrite the announced name, + --they should be able to announce any Main Deck card's name, + --since they don't know what cards are in the player's Deck + e:GetChainData().announce_filter=function(_,p) return p==tp and announce_filter or DF.IsMainDeckCard() end end function s.rmfilter(c,ac) return c:IsCode(ac) and c:IsAbleToRemove() end function s.rmop(e,tp,eg,ep,ev,re,r,rp) - local ac=Duel.GetChainInfo(0,CHAININFO_TARGET_PARAM) + local cd=e:GetChainData() Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_REMOVE) - local g=Duel.SelectMatchingCard(tp,s.rmfilter,tp,LOCATION_DECK,0,1,1,nil,ac) - local tc=g:GetFirst() - if tc and Duel.Remove(tc,POS_FACEUP,REASON_EFFECT)~=0 and tc:IsLocation(LOCATION_REMOVED) then + local tc=Duel.SelectMatchingCard(tp,s.rmfilter,tp,LOCATION_DECK,0,1,1,nil,cd.announced_card):GetFirst() + if tc and Duel.Remove(tc,POS_FACEUP,REASON_EFFECT)>0 and tc:IsLocation(LOCATION_REMOVED) then local c=e:GetHandler() local code=tc:GetOriginalCodeRule() + --Negate its effects, as well as the activated effects and effects on the field of cards with the same original name, until the end of this turn local e1=Effect.CreateEffect(c) e1:SetType(EFFECT_TYPE_FIELD) e1:SetCode(EFFECT_DISABLE) e1:SetTargetRange(LOCATION_ONFIELD,LOCATION_ONFIELD) - e1:SetLabel(code) - e1:SetTarget(s.distg) + e1:SetTarget(function(e,c) return c:IsOriginalCodeRule(code) end) e1:SetReset(RESET_PHASE|PHASE_END) Duel.RegisterEffect(e1,tp) local e2=Effect.CreateEffect(c) e2:SetType(EFFECT_TYPE_FIELD+EFFECT_TYPE_CONTINUOUS) e2:SetCode(EVENT_CHAIN_SOLVING) - e2:SetLabel(code) - e2:SetCondition(s.discon) - e2:SetOperation(s.disop) + e2:SetCondition(function(e,tp,eg,ep,ev,re,r,rp) return re:GetHandler():IsOriginalCodeRule(code) end) + e2:SetOperation(function(e,tp,eg,ep,ev,re,r,rp) Duel.NegateEffect(ev) end) e2:SetReset(RESET_PHASE|PHASE_END) Duel.RegisterEffect(e2,tp) local e3=e1:Clone() @@ -69,12 +56,3 @@ function s.rmop(e,tp,eg,ep,ev,re,r,rp) Duel.RegisterEffect(e3,tp) end end -function s.distg(e,c) - return c:IsOriginalCodeRule(e:GetLabel()) -end -function s.discon(e,tp,eg,ep,ev,re,r,rp) - return re:GetHandler():IsOriginalCodeRule(e:GetLabel()) -end -function s.disop(e,tp,eg,ep,ev,re,r,rp) - Duel.NegateEffect(ev) -end \ No newline at end of file diff --git a/official/c74733322.lua b/official/c74733322.lua index cf457cfc60..965ed37df0 100644 --- a/official/c74733322.lua +++ b/official/c74733322.lua @@ -8,7 +8,7 @@ function s.initial_effect(c) e0:SetType(EFFECT_TYPE_ACTIVATE) e0:SetCode(EVENT_FREE_CHAIN) c:RegisterEffect(e0) - --During your Main Phase, you can Normal Summon 1 "Medius the Pure" in addition to your Normal Summon/Set + --During your Main Phase, you can Normal Summon 1 "Medius the Pure", in addition to your Normal Summon/Set (you can only gain this effect once per turn) local e1=Effect.CreateEffect(c) e1:SetDescription(aux.Stringid(id,0)) e1:SetType(EFFECT_TYPE_FIELD) @@ -17,7 +17,7 @@ function s.initial_effect(c) e1:SetTargetRange(LOCATION_HAND|LOCATION_MZONE,0) e1:SetTarget(aux.TargetBoolFunction(Card.IsCode,CARD_MEDIUS_THE_PURE)) c:RegisterEffect(e1) - --Add 1 declared "Artmage" monster from your Deck to your hand + --You can discard 1 Spell/Trap, and declare 1 "Artmage" Monster Card name that is not among the monsters you control and has not been declared for "Artmage Academic Arcane Arts Acropolis" this turn; add that monster from your Deck to your hand, also you cannot Special Summon for the rest of this turn, except "Artmage" monsters, "Medius the Pure", or from the Extra Deck local e2=Effect.CreateEffect(c) e2:SetDescription(aux.Stringid(id,1)) e2:SetCategory(CATEGORY_TOHAND+CATEGORY_SEARCH) @@ -43,43 +43,36 @@ s.listed_names={CARD_MEDIUS_THE_PURE} s.listed_series={SET_ARTMAGE} function s.declfilter(c,exc1,exc2) return c:IsSetCard(SET_ARTMAGE) and c:IsMonster() and c:IsAbleToHand() - and (#exc1==0 or not c:IsCode(table.unpack(exc1))) and (#exc2==0 or not c:IsCode(table.unpack(exc2))) + and (#exc1==0 or not c:IsCode(table.unpack(exc1))) + and (#exc2==0 or not c:IsCode(table.unpack(exc2))) end function s.thtg(e,tp,eg,ep,ev,re,r,rp,chk) local fcs=Duel.GetMatchingGroup(aux.FaceupFilter(Card.IsSetCard,SET_ARTMAGE),tp,LOCATION_MZONE,0,nil):GetClass(Card.GetCode) local g=Duel.GetMatchingGroup(s.declfilter,tp,LOCATION_DECK,0,nil,fcs,s.declared_names[tp]) if chk==0 then return #g>0 end - s.announce_filter={} - for _,code in ipairs(g:GetClass(Card.GetCode)) do - if #s.announce_filter==0 then - table.insert(s.announce_filter,code) - table.insert(s.announce_filter,OPCODE_ISCODE) - else - table.insert(s.announce_filter,code) - table.insert(s.announce_filter,OPCODE_ISCODE) - table.insert(s.announce_filter,OPCODE_OR) - end - end - local ac=Duel.AnnounceCard(tp,table.unpack(s.announce_filter)) - table.insert(s.declared_names[tp],ac) - Duel.SetTargetParam(ac) + local announce_filter=DF.IsCode(g:GetClass(Card.GetCode)) + local announced_card=Duel.AnnounceCard(tp,announce_filter) + table.insert(s.declared_names[tp],announced_card) Duel.SetOperationInfo(0,CATEGORY_TOHAND,nil,1,tp,LOCATION_DECK) - Duel.SetOperationInfo(0,CATEGORY_ANNOUNCE,nil,0,tp,ANNOUNCE_CARD_FILTER) + --if the opponent tries to overwrite the announced name, they don't know what cards are in the player's Deck, + --so they should be able to announce any "Artmage" Main Deck monster that the player did not control and had not announced yet + local opp_announce_filter=DF.IsMainDeckMonster() & DF.IsSetCard(SET_ARTMAGE) & ~DF.IsCode(fcs) & ~DF.IsCode(s.declared_names[tp]) + e:GetChainData().announce_filter=function(_,p) return p==tp and announce_filter or opp_announce_filter end end function s.thfilter(c,code) return c:IsCode(code) and c:IsMonster() and c:IsAbleToHand() end function s.thop(e,tp,eg,ep,ev,re,r,rp) - local code=Duel.GetChainInfo(0,CHAININFO_TARGET_PARAM) + local cd=e:GetChainData() Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_ATOHAND) - local g=Duel.SelectMatchingCard(tp,s.thfilter,tp,LOCATION_DECK,0,1,1,nil,code) + local g=Duel.SelectMatchingCard(tp,s.thfilter,tp,LOCATION_DECK,0,1,1,nil,cd.announced_card) if #g>0 then Duel.SendtoHand(g,nil,REASON_EFFECT) Duel.ConfirmCards(1-tp,g) end if not Duel.HasFlagEffect(tp,id) then Duel.RegisterFlagEffect(tp,id,RESET_PHASE|PHASE_END,0,1) - --Cannot Special Summon from outside the Extra Deck for the rest of this turn, except "Artmage" monsters and "Medius the Pure" + --You cannot Special Summon for the rest of this turn, except "Artmage" monsters, "Medius the Pure", or from the Extra Deck. local e1=Effect.CreateEffect(e:GetHandler()) e1:SetDescription(aux.Stringid(id,2)) e1:SetType(EFFECT_TYPE_FIELD) @@ -90,4 +83,4 @@ function s.thop(e,tp,eg,ep,ev,re,r,rp) e1:SetReset(RESET_PHASE|PHASE_END) Duel.RegisterEffect(e1,tp) end -end \ No newline at end of file +end diff --git a/official/c92501449.lua b/official/c92501449.lua index c1c14837e6..18a32479aa 100644 --- a/official/c92501449.lua +++ b/official/c92501449.lua @@ -3,7 +3,7 @@ --scripted by Naim local s,id=GetID() function s.initial_effect(c) - --Prevent battle destruction and Special Summon 1 Normal Monster + --Pay 2000 LP, then declare 1 Normal Monster Card name; the declared Normal Monsters and "Primite" monsters you control cannot be destroyed by battle (until the end of your opponent's turn), then if you control no monsters, you can Special Summon 1 declared Normal Monster from your Deck in Defense Position local e1=Effect.CreateEffect(c) e1:SetDescription(aux.Stringid(id,0)) e1:SetCategory(CATEGORY_SPECIAL_SUMMON) @@ -14,7 +14,7 @@ function s.initial_effect(c) e1:SetTarget(s.target) e1:SetOperation(s.activate) c:RegisterEffect(e1) - --Banish 1 monster on the field + --If your opponent Normal Summons a monster: You can banish this card from your GY, then target 1 Normal Monster you control or in your GY; banish 1 monster from the field with less ATK than that monster local e2=Effect.CreateEffect(c) e2:SetDescription(aux.Stringid(id,1)) e2:SetCategory(CATEGORY_REMOVE) @@ -31,10 +31,7 @@ end s.listed_series={SET_PRIMITE} function s.target(e,tp,eg,ep,ev,re,r,rp,chk) if chk==0 then return true end - s.announce_filter={TYPE_NORMAL,OPCODE_ISTYPE} - local code=Duel.AnnounceCard(tp,s.announce_filter) - Duel.SetTargetParam(code) - Duel.SetOperationInfo(0,CATEGORY_ANNOUNCE,nil,0,tp,ANNOUNCE_CARD_FILTER) + Duel.AnnounceCard(tp,DF.IsType(TYPE_NORMAL)) Duel.SetPossibleOperationInfo(0,CATEGORY_SPECIAL_SUMMON,nil,1,tp,LOCATION_DECK) end function s.spfilter(c,e,tp,code) @@ -42,8 +39,8 @@ function s.spfilter(c,e,tp,code) end function s.activate(e,tp,eg,ep,ev,re,r,rp) local c=e:GetHandler() - local code=Duel.GetChainInfo(0,CHAININFO_TARGET_PARAM) - --Your Normal Monsters with the declared name and "Primite" monsters cannot be destroyed by battle + local code=e:GetChainData().announced_card + --The declared Normal Monsters and "Primite" monsters you control cannot be destroyed by battle (until the end of your opponent's turn) local e1=Effect.CreateEffect(c) e1:SetType(EFFECT_TYPE_FIELD) e1:SetCode(EFFECT_INDESTRUCTABLE_BATTLE) @@ -86,4 +83,4 @@ function s.rmvop(e,tp,eg,ep,ev,re,r,rp) Duel.HintSelection(g) Duel.Remove(g,nil,REASON_EFFECT) end -end \ No newline at end of file +end diff --git a/utility.lua b/utility.lua index a6e823b817..28fd0921c0 100644 --- a/utility.lua +++ b/utility.lua @@ -2897,6 +2897,149 @@ function Auxiliary.DefaultFieldReturnOp(rg) select_field_return_cards(1-turn_p,g1) end + + +DeclareFilter={} +DF=DeclareFilter + +do + local mt={} + + local function create_filter(filter) + return setmetatable(filter,mt) + end + + local function concat(op) + return function(...) + local res={} + + --OPCODE_ALLOW_ALIASES and OPCODE_ALLOW_TOKENS cannot be combined like the other OPCODES: + --they are only applied once, they cannot be negated by OPCODE_NOT, + --and they cannot be partially applied to specific parts of a filter + local aliases=false + local tokens=false + + for i,filter in ipairs({...}) do + local is_empty=true + for _,val in ipairs(filter) do + if val==OPCODE_ALLOW_ALIASES then + aliases=true + elseif val==OPCODE_ALLOW_TOKENS then + tokens=true + else + is_empty=false + table.insert(res,val) + end + end + + if i>1 and not is_empty then + table.insert(res,op) + end + end + + if aliases then table.insert(res,OPCODE_ALLOW_ALIASES) end + if tokens then table.insert(res,OPCODE_ALLOW_TOKENS) end + + return create_filter(res) + end + end + + local function append(op) + --enforces a single filter parameter, so the resulting function + --cannot be accidentally called with more than one table + return function(filter) + return concat(op)({},filter) + end + end + + DF.AND = concat(OPCODE_AND) + DF.OR = concat(OPCODE_OR) + DF.NOT = append(OPCODE_NOT) + + mt.__band = DF.AND + mt.__bor = DF.OR + mt.__bnot = DF.NOT + + local function matches_arg(op) + return function(val) + if type(val)~="number" then + error("Parameter 1 must be a number",2) + end + return create_filter({val,op}) + end + end + + DF.IsType = matches_arg(OPCODE_ISTYPE) + DF.IsRace = matches_arg(OPCODE_ISRACE) + DF.IsAttribute = matches_arg(OPCODE_ISATTRIBUTE) + + local function matches_any_arg(op) + return function(...) + local args={...} + if #args==1 and type(args[1])=="table" then args=args[1] end + + local res={} + for i,val in ipairs(args) do + if type(val)~="number" then + error("Parameter " .. tostring(i) .. " must be a number",2) + end + + table.insert(res,val) + table.insert(res,op) + if i>1 then + table.insert(res,OPCODE_OR) + end + end + + return create_filter(res) + end + end + + DF.IsCode = matches_any_arg(OPCODE_ISCODE) + DF.IsSetCard = matches_any_arg(OPCODE_ISSETCARD) + + DF.WithAliases = append(OPCODE_ALLOW_ALIASES) + DF.WithTokens = append(OPCODE_ALLOW_TOKENS) + + function DF.WithAliasesAndTokens(filter) + return DF.WithAliases(DF.WithTokens(filter)) + end + + function DF.IsExtraDeckCard() + if Duel.IsDuelType(DUEL_MODE_RUSH) then + return DF.WithAliases(DF.IsType(TYPE_EXTRA|TYPE_RITUAL) & DF.IsType(TYPE_MONSTER)) + end + return DF.IsType(TYPE_EXTRA) + end + + function DF.IsMainDeckCard() + return ~DF.IsExtraDeckCard() + end + + function DF.IsMainDeckMonster() + return DF.IsMainDeckCard() & DF.IsType(TYPE_MONSTER) + end + + local old_announce_card=Duel.AnnounceCard + function Duel.AnnounceCard(player,filter) + if filter and getmetatable(filter)~=mt then + error("Parameter 2 must be a DeclareFilter or nil") + end + + Duel.Hint(HINT_SELECTMSG,player,HINTMSG_CODE) + + local ch=Chain.GetCurrentLink() + if ch==0 then return old_announce_card(player,filter) end + + local cd=Chain.GetTriggeringEffect(ch):GetChainData() + cd.announce_filter=filter + cd.announced_card=old_announce_card(player,filter) + + return cd.announced_card + end +end + + Duel.LoadScript("debug_utility.lua") Duel.LoadScript("chain.lua") Duel.LoadScript("cards_specific_functions.lua")