|
2 | 2 | --Double Spell (Anime) |
3 | 3 | local s,id=GetID() |
4 | 4 | function s.initial_effect(c) |
5 | | - --Copy spell |
| 5 | + --Activate |
6 | 6 | local e1=Effect.CreateEffect(c) |
| 7 | + e1:SetDescription(aux.Stringid(id,0)) |
7 | 8 | e1:SetType(EFFECT_TYPE_ACTIVATE) |
8 | | - e1:SetCode(EVENT_FREE_CHAIN) |
9 | 9 | e1:SetProperty(EFFECT_FLAG_CARD_TARGET) |
| 10 | + e1:SetCode(EVENT_FREE_CHAIN) |
| 11 | + e1:SetHintTiming(TIMING_CHAIN_END,TIMING_CHAIN_END|TIMING_STANDBY_PHASE|TIMING_MAIN_END|TIMINGS_CHECK_MONSTER_E) |
10 | 12 | e1:SetTarget(s.target) |
11 | | - e1:SetOperation(s.operation) |
| 13 | + e1:SetOperation(s.activate) |
12 | 14 | c:RegisterEffect(e1) |
| 15 | + --Keep track of Spell Card activations |
| 16 | + aux.GlobalCheck(s,function() |
| 17 | + local ge1=Effect.CreateEffect(c) |
| 18 | + ge1:SetType(EFFECT_TYPE_FIELD+EFFECT_TYPE_CONTINUOUS) |
| 19 | + ge1:SetCode(EVENT_CHAINING) |
| 20 | + ge1:SetOperation(s.checkop) |
| 21 | + Duel.RegisterEffect(ge1,0) |
| 22 | + end) |
13 | 23 | end |
14 | | -function s.filter(c,e,tp,eg,ep,ev,re,r,rp,tid) |
15 | | - local te=c:CheckActivateEffect(false,false,false) |
16 | | - if c:GetTurnID()~=tid-1 or not c:IsPreviousPosition(POS_FACEUP) then return false end |
17 | | - if c:IsSpell() and te then |
18 | | - if c:IsSetCard(0x95) then |
19 | | - local tg=te:GetTarget() |
20 | | - return not tg or tg(e,tp,eg,ep,ev,re,r,rp,0) |
21 | | - else |
22 | | - return true |
23 | | - end |
| 24 | +function s.checkop(e,tp,eg,ep,ev,re,r,rp) |
| 25 | + if re:IsSpellEffect() then |
| 26 | + re:GetHandler():RegisterFlagEffect(id+1,RESETS_STANDARD_PHASE_END&~(RESET_TOGRAVE|RESET_LEAVE),0,1) |
24 | 27 | end |
25 | | - return false |
26 | 28 | end |
27 | | -function s.target(e,tp,eg,ep,ev,re,r,rp,chk,chkc) |
28 | | - local tid=Duel.GetTurnCount() |
29 | | - if chkc then return chkc:IsLocation(LOCATION_GRAVE) and chkc:IsControler(1-tp) and s.filter(chkc,e,tp,eg,ep,ev,re,r,rp,tid) end |
30 | | - if chk==0 then |
31 | | - local b=e:GetHandler():IsLocation(LOCATION_HAND) |
32 | | - local ft=Duel.GetLocationCount(tp,LOCATION_SZONE) |
33 | | - if (b and ft>1) or (not b and ft>0) then |
34 | | - return Duel.IsExistingTarget(s.filter,tp,0,LOCATION_GRAVE,1,e:GetHandler(),e,tp,eg,ep,ev,re,r,rp,tid) |
35 | | - else |
36 | | - return false |
| 29 | +function s.tgfilter(c,tp,szone_adjustment) |
| 30 | + if not c:IsSpell() or c:IsCode(id) or not c:HasFlagEffect(id+1) then return false end |
| 31 | + if c:GetTurnID()~=Duel.GetTurnCount() then return false end |
| 32 | + local te=c:GetActivateEffect() |
| 33 | + --Check for HOPT |
| 34 | + if not (te and te:CheckCountLimit(tp)) then return false end |
| 35 | + --Check for "cannot activate" restrictions |
| 36 | + if c:IsHasEffect(EFFECT_CANNOT_TRIGGER) then return false end |
| 37 | + local cannot_act_restrictions={Duel.GetPlayerEffect(tp,EFFECT_CANNOT_ACTIVATE)} |
| 38 | + if cannot_act_restrictions[1] then |
| 39 | + for _,eff in ipairs(cannot_act_restrictions) do |
| 40 | + local eff_value=eff:GetValue() |
| 41 | + if type(eff_value)~='function' or eff_value(eff,te,tp) then return false end |
37 | 42 | end |
38 | 43 | end |
39 | | - local ft=Duel.GetLocationCount(tp,LOCATION_SZONE) |
40 | | - Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_TARGET) |
41 | | - Duel.SelectTarget(tp,s.filter,tp,0,LOCATION_GRAVE,1,ft,nil,e,tp,eg,ep,ev,re,r,rp,tid) |
| 44 | + local res,ceg,cep,cev,cre,cr,crp |
| 45 | + if not Duel.IsChainSolving() then |
| 46 | + --Check using the returned values of "Duel.CheckEvent" only for the activation check |
| 47 | + local te_effect_code=te:GetCode() |
| 48 | + res,ceg,cep,cev,cre,cr,crp=Duel.CheckEvent(te_effect_code,true) |
| 49 | + --If it's "EVENT_FREE_CHAIN" then "res" will always be false |
| 50 | + if not res and te_effect_code~=EVENT_FREE_CHAIN then return false end |
| 51 | + else |
| 52 | + local eff=c:IsHasEffect(id) |
| 53 | + local t=eff:GetLabelObject() |
| 54 | + ceg,cep,cev,cre,cr,crp=table.unpack(t) |
| 55 | + end |
| 56 | + local condition=te:GetCondition() |
| 57 | + local cost=te:GetCost() |
| 58 | + local target=te:GetTarget() |
| 59 | + --Check if the card can be activated |
| 60 | + if condition and not condition(te,tp,ceg,cep,cev,cre,cr,crp) then return false end |
| 61 | + if cost and not cost(te,tp,ceg,cep,cev,cre,cr,crp,0) then return false end |
| 62 | + if target and not target(te,tp,ceg,cep,cev,cre,cr,crp,0) then return false end |
| 63 | + --Don't need to check for zones for a Field Card |
| 64 | + if c:IsType(TYPE_FIELD) then return true end |
| 65 | + --Check for cards that can only be activated in certain zones |
| 66 | + local zones=0xff |
| 67 | + if te:IsHasProperty(EFFECT_FLAG_LIMIT_ZONE) then |
| 68 | + zones=te:GetValue()(te,tp,eg,ep,ev,re,r,rp) |
| 69 | + end |
| 70 | + return Duel.GetLocationCount(tp,LOCATION_SZONE,tp,LOCATION_REASON_TOFIELD,zones)-szone_adjustment>0 |
42 | 71 | end |
43 | | -function s.operation(e,tp,eg,ep,ev,re,r,rp) |
44 | | - local tgg=Duel.GetTargetCards(e) |
45 | | - local tc=tgg:GetFirst() |
46 | | - while tc and Duel.GetLocationCount(tp,LOCATION_MZONE)>0 do |
47 | | - local tpe=tc:GetType() |
| 72 | +function s.target(e,tp,eg,ep,ev,re,r,rp,chk) |
| 73 | + local c=e:GetHandler() |
| 74 | + local szone_adjustment=c:IsLocation(LOCATION_SZONE) and 0 or 1 |
| 75 | + if chk==0 then return Duel.IsExistingMatchingCard(s.tgfilter,tp,0,LOCATION_GRAVE,1,c,tp,szone_adjustment) end |
| 76 | + local g=Duel.GetMatchingGroup(Card.HasFlagEffect,tp,0,LOCATION_GRAVE,c,id+1) |
| 77 | + for tc in g:Iter() do |
48 | 78 | local te=tc:GetActivateEffect() |
49 | | - local tg=te:GetTarget() |
50 | | - local co=te:GetCost() |
51 | | - local op=te:GetOperation() |
52 | | - e:SetCategory(te:GetCategory()) |
53 | | - e:SetProperty(te:GetProperty()) |
54 | | - Duel.ClearTargetCard() |
55 | | - local loc=LOCATION_SZONE |
56 | | - if (tpe&TYPE_FIELD)~=0 then |
57 | | - loc=LOCATION_FZONE |
58 | | - local of=Duel.GetFieldCard(1-tp,LOCATION_FZONE,0) |
59 | | - if of then Duel.Destroy(of,REASON_RULE) end |
60 | | - of=Duel.GetFieldCard(tp,LOCATION_FZONE,0) |
61 | | - if of and Duel.Destroy(of,REASON_RULE)==0 then Duel.SendtoGrave(tc,REASON_RULE) end |
62 | | - end |
63 | | - Duel.MoveToField(tc,tp,tp,loc,POS_FACEUP,true) |
64 | | - Duel.Hint(HINT_CARD,0,tc:GetCode()) |
65 | | - tc:CreateEffectRelation(te) |
66 | | - if (tpe&TYPE_EQUIP+TYPE_CONTINUOUS+TYPE_FIELD)==0 then |
67 | | - tc:CancelToGrave(false) |
| 79 | + local te_effect_code=te:GetCode() |
| 80 | + local res,ceg,cep,cev,cre,cr,crp=Duel.CheckEvent(te_effect_code,true) |
| 81 | + local t={ceg,cep,cev,cre,cr,crp} |
| 82 | + --Dummy effect to save each card's event parameters |
| 83 | + local e1=Effect.CreateEffect(c) |
| 84 | + e1:SetType(EFFECT_TYPE_SINGLE) |
| 85 | + e1:SetCode(id) |
| 86 | + e1:SetLabelObject(t) |
| 87 | + tc:RegisterEffect(e1) |
| 88 | + end |
| 89 | + Duel.SetOperationInfo(0,CATEGORY_LEAVE_GRAVE,nil,1,1-tp,0) |
| 90 | +end |
| 91 | +function s.activate(e,tp,eg,ep,ev,re,r,rp) |
| 92 | + local c=e:GetHandler() |
| 93 | + local g=Duel.GetMatchingGroup(s.tgfilter,tp,0,LOCATION_GRAVE,c,tp,0) |
| 94 | + if #g==0 then return end |
| 95 | + repeat |
| 96 | + Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_EFFECT) |
| 97 | + local sc=g:Select(tp,1,1,nil):GetFirst() |
| 98 | + if sc then |
| 99 | + s.place_and_activate(sc,e,tp,eg,ep,ev,re,r,rp) |
68 | 100 | end |
69 | | - if co then co(te,tp,eg,ep,ev,re,r,rp,1) end |
70 | | - if tg then tg(te,tp,eg,ep,ev,re,r,rp,1) end |
71 | | - Duel.BreakEffect() |
72 | | - local g=Duel.GetChainInfo(0,CHAININFO_TARGET_CARDS) |
73 | | - if g then |
74 | | - local etc=g:GetFirst() |
75 | | - while etc do |
76 | | - etc:CreateEffectRelation(te) |
77 | | - etc=g:GetNext() |
| 101 | + g=Duel.GetMatchingGroup(s.tgfilter,tp,0,LOCATION_GRAVE,c,tp,0) |
| 102 | + until #g==0 or not Duel.SelectEffectYesNo(tp,c) |
| 103 | +end |
| 104 | +function s.place_and_activate(sc,e,tp,eg,ep,ev,re,r,rp) |
| 105 | + if not s.tgfilter(sc,tp,0) then return end |
| 106 | + local te=sc:GetActivateEffect() |
| 107 | + if not te then return end |
| 108 | + local location=sc:IsType(TYPE_FIELD) and LOCATION_FZONE or LOCATION_SZONE |
| 109 | + --Adjust "zones" for cards that can only be activated in certain zones |
| 110 | + local zones=0xff |
| 111 | + if te:IsHasProperty(EFFECT_FLAG_LIMIT_ZONE) then |
| 112 | + zones=te:GetValue()(te,tp,eg,ep,ev,re,r,rp) |
| 113 | + end |
| 114 | + if not Duel.MoveToField(sc,tp,tp,location,POS_FACEUP,true,zones) then return end |
| 115 | + --Set activated status, show the card, create relation to itself, and use the effect's count limit (if any) |
| 116 | + sc:SetStatus(STATUS_ACTIVATED,true) |
| 117 | + Duel.Hint(HINT_CARD,0,sc:GetCode()) |
| 118 | + sc:CreateEffectRelation(te) |
| 119 | + te:UseCountLimit(tp) |
| 120 | + --Mark the card as "to be sent to the GY" if it's not a card that remains on the field after activation |
| 121 | + if not (sc:IsType(TYPE_FIELD) or sc:IsEquipSpell() or sc:IsContinuousSpellTrap() or sc:IsLinkSpell() |
| 122 | + or sc:IsHasEffect(EFFECT_REMAIN_FIELD) or te:GetCost()==aux.RemainFieldCost) then |
| 123 | + sc:CancelToGrave(false) |
| 124 | + end |
| 125 | + local eff=sc:IsHasEffect(id) |
| 126 | + local t=eff:GetLabelObject() |
| 127 | + eff:Reset() |
| 128 | + local ceg,cep,cev,cre,cr,crp=table.unpack(t) |
| 129 | + --Execute the cost, target, and operation with the designated parameters if the card's effects after it's placed on the field aren't negated |
| 130 | + if not sc:IsDisabled() then |
| 131 | + local cost=te:GetCost() |
| 132 | + local target=te:GetTarget() |
| 133 | + local operation=te:GetOperation() |
| 134 | + --Set the effect's property so that targeted cards are highlighted normally |
| 135 | + e:SetProperty(te:GetProperty()) |
| 136 | + --Activation procedure |
| 137 | + if cost then cost(te,tp,ceg,cep,cev,cre,cr,crp,1) end |
| 138 | + if target then target(te,tp,ceg,cep,cev,cre,cr,crp,1) end |
| 139 | + --Manually create the effect relation for any targeted cards |
| 140 | + local tg=Duel.GetChainInfo(0,CHAININFO_TARGET_CARDS) |
| 141 | + if tg then |
| 142 | + for tc in tg:Iter() do |
| 143 | + tc:CreateEffectRelation(te) |
78 | 144 | end |
79 | 145 | end |
80 | | - if op then op(te,tp,eg,ep,ev,re,r,rp) end |
81 | | - tc:ReleaseEffectRelation(te) |
82 | | - if etc then |
83 | | - etc=g:GetFirst() |
84 | | - while etc do |
85 | | - etc:ReleaseEffectRelation(te) |
86 | | - etc=g:GetNext() |
87 | | - end |
| 146 | + e:SetProperty(EFFECT_FLAG_CARD_TARGET) |
| 147 | + local field_event_eg=Group.FromCards(sc) |
| 148 | + local current_chain_link=Duel.GetCurrentChain() |
| 149 | + --Manually raise the events for activating it |
| 150 | + Duel.RaiseSingleEvent(sc,EVENT_CHAINING,te,0,tp,tp,current_chain_link) |
| 151 | + Duel.RaiseEvent(field_event_eg,EVENT_CHAINING,te,0,tp,tp,current_chain_link) |
| 152 | + --Break to separate the activation and the resolution |
| 153 | + Duel.BreakEffect() |
| 154 | + --Manually raise the events for the start of resolution |
| 155 | + Duel.RaiseSingleEvent(sc,EVENT_CHAIN_SOLVING,te,0,tp,tp,current_chain_link) |
| 156 | + Duel.RaiseEvent(field_event_eg,EVENT_CHAIN_SOLVING,te,0,tp,tp,current_chain_link) |
| 157 | + --Resolution of the effect |
| 158 | + if operation then operation(te,tp,ceg,cep,cev,cre,cr,crp) end |
| 159 | + --Manually raise the events for the end of resolution |
| 160 | + Duel.RaiseSingleEvent(sc,EVENT_CHAIN_SOLVED,te,0,tp,tp,current_chain_link) |
| 161 | + Duel.RaiseEvent(field_event_eg,EVENT_CHAIN_SOLVED,te,0,tp,tp,current_chain_link) |
| 162 | + end |
| 163 | + --Manually release the effect relation for this card and any targeted cards |
| 164 | + sc:ReleaseEffectRelation(te) |
| 165 | + local tg=Duel.GetChainInfo(0,CHAININFO_TARGET_CARDS) |
| 166 | + if tg then |
| 167 | + for tc in tg:Iter() do |
| 168 | + tc:ReleaseEffectRelation(te) |
88 | 169 | end |
89 | | - tc=tgg:GetNext() |
90 | 170 | end |
91 | 171 | end |
0 commit comments