Skip to content

Commit aaf5a26

Browse files
authored
Cost helper functions updates
Grouped them together under the "Cost" table. E.g. "aux.SelfDiscardCost" --> "Cost.SelfDiscard" (old names still usable for now). Added 3 new functions: - Cost.SoftOncePerChain - Cost.HardOncePerChain - Cost.AND Updated aux.dxmcostgen/Cost.Detach: "max" now defaults to be equal to "min" if not provided.
1 parent 26c4207 commit aaf5a26

File tree

4 files changed

+126
-89
lines changed

4 files changed

+126
-89
lines changed

official/c3814632.lua

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,45 @@
22
--Skypalace Gangaridai
33
local s,id=GetID()
44
function s.initial_effect(c)
5-
--Xyz Summon
6-
Xyz.AddProcedure(c,nil,10,2)
75
c:EnableReviveLimit()
8-
--Destroy 1 of opponent's cards, and if you do, inflict 1000 damage
6+
--Xyz Summon procedure: 2 Level 10 monsters
7+
Xyz.AddProcedure(c,nil,10,2)
8+
--Destroy 1 card your opponent controls, and if you do, inflict 1000 damage to them
99
local e1=Effect.CreateEffect(c)
10-
e1:SetCategory(CATEGORY_DESTROY+CATEGORY_DAMAGE)
1110
e1:SetDescription(aux.Stringid(id,0))
11+
e1:SetCategory(CATEGORY_DESTROY+CATEGORY_DAMAGE)
1212
e1:SetType(EFFECT_TYPE_IGNITION)
1313
e1:SetProperty(EFFECT_FLAG_CARD_TARGET)
1414
e1:SetRange(LOCATION_MZONE)
1515
e1:SetCountLimit(1,id)
16-
e1:SetCost(aux.AND(aux.dxmcostgen(1,1,nil),s.cacost))
17-
e1:SetTarget(s.target)
18-
e1:SetOperation(s.operation)
16+
e1:SetCost(Cost.AND(Cost.Detach(1),s.descost))
17+
e1:SetTarget(s.destg)
18+
e1:SetOperation(s.desop)
1919
c:RegisterEffect(e1,false,REGISTER_FLAG_DETACH_XMAT)
2020
end
21-
function s.cacost(e,tp,eg,ep,ev,re,r,rp,chk)
21+
function s.descost(e,tp,eg,ep,ev,re,r,rp,chk)
2222
local c=e:GetHandler()
2323
if chk==0 then return c:GetAttackAnnouncedCount()==0 end
24-
--Cannot attack
24+
--Cannot attack the turn you activate this effect
2525
local e1=Effect.CreateEffect(c)
2626
e1:SetDescription(3206)
2727
e1:SetType(EFFECT_TYPE_SINGLE)
28-
e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_CLIENT_HINT)
28+
e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_OATH+EFFECT_FLAG_CLIENT_HINT)
2929
e1:SetCode(EFFECT_CANNOT_ATTACK)
30-
e1:SetReset(RESET_EVENT+RESETS_STANDARD+RESET_PHASE+PHASE_END)
30+
e1:SetReset(RESETS_STANDARD_PHASE_END)
3131
c:RegisterEffect(e1)
3232
end
33-
function s.target(e,tp,eg,ep,ev,re,r,rp,chk,chkc)
33+
function s.destg(e,tp,eg,ep,ev,re,r,rp,chk,chkc)
3434
if chkc then return chkc:IsOnField() and chkc:IsControler(1-tp) end
3535
if chk==0 then return Duel.IsExistingTarget(nil,tp,0,LOCATION_ONFIELD,1,nil) end
3636
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_DESTROY)
3737
local g=Duel.SelectTarget(tp,nil,tp,0,LOCATION_ONFIELD,1,1,nil)
38-
Duel.SetOperationInfo(0,CATEGORY_DESTROY,g,1,0,0)
38+
Duel.SetOperationInfo(0,CATEGORY_DESTROY,g,1,tp,0)
3939
Duel.SetOperationInfo(0,CATEGORY_DAMAGE,nil,0,1-tp,1000)
4040
end
41-
function s.operation(e,tp,eg,ep,ev,re,r,rp)
41+
function s.desop(e,tp,eg,ep,ev,re,r,rp)
4242
local tc=Duel.GetFirstTarget()
43-
if not tc:IsRelateToEffect(e) or Duel.Destroy(tc,REASON_EFFECT)==0 then return end
44-
Duel.Damage(1-tp,1000,REASON_EFFECT)
43+
if tc:IsRelateToEffect(e) and tc:IsControler(1-tp) and Duel.Destroy(tc,REASON_EFFECT)>0 then
44+
Duel.Damage(1-tp,1000,REASON_EFFECT)
45+
end
4546
end

official/c46772449.lua

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,56 +2,51 @@
22
--Evilswarm Exciton Knight
33
local s,id=GetID()
44
function s.initial_effect(c)
5-
--Xyz Summon
6-
Xyz.AddProcedure(c,nil,4,2)
75
c:EnableReviveLimit()
6+
--Xyz Summon procedure: 2 Level 4 monsters
7+
Xyz.AddProcedure(c,nil,4,2)
88
--Destroy all other cards on the field
99
local e1=Effect.CreateEffect(c)
1010
e1:SetDescription(aux.Stringid(id,0))
1111
e1:SetCategory(CATEGORY_DESTROY)
1212
e1:SetType(EFFECT_TYPE_QUICK_O)
13-
e1:SetRange(LOCATION_MZONE)
1413
e1:SetCode(EVENT_FREE_CHAIN)
15-
e1:SetHintTiming(TIMING_SPSUMMON,TIMING_BATTLE_START)
16-
e1:SetCondition(s.condition)
17-
e1:SetCost(aux.AND(aux.dxmcostgen(1,1,nil),s.opccost))
18-
e1:SetTarget(s.target)
19-
e1:SetOperation(s.operation)
14+
e1:SetRange(LOCATION_MZONE)
15+
e1:SetHintTiming(TIMING_SPSUMMON,TIMING_BATTLE_START|TIMING_BATTLE_END)
16+
e1:SetCountLimit(1,0,EFFECT_COUNT_CODE_CHAIN)
17+
e1:SetCondition(s.descon)
18+
e1:SetCost(Cost.Detach(1))
19+
e1:SetTarget(s.destg)
20+
e1:SetOperation(s.desop)
2021
c:RegisterEffect(e1,false,REGISTER_FLAG_DETACH_XMAT)
2122
end
22-
function s.condition(e,tp,eg,ep,ev,re,r,rp)
23-
local ct1=Duel.GetFieldGroupCount(tp,LOCATION_ONFIELD+LOCATION_HAND,0)
24-
local ct2=Duel.GetFieldGroupCount(tp,0,LOCATION_ONFIELD+LOCATION_HAND)
25-
if ct1>=ct2 then return false end
26-
return (Duel.IsTurnPlayer(tp) and Duel.IsMainPhase()) or
27-
(not Duel.IsTurnPlayer(tp) and Duel.IsBattlePhase())
23+
function s.descon(e,tp,eg,ep,ev,re,r,rp)
24+
if not (Duel.IsTurnPlayer(tp) and Duel.IsMainPhase()) or (Duel.IsTurnPlayer(1-tp) and Duel.IsBattlePhase()) then return false end
25+
return Duel.GetFieldGroupCount(tp,0,LOCATION_HAND|LOCATION_ONFIELD)>Duel.GetFieldGroupCount(tp,LOCATION_HAND|LOCATION_ONFIELD,0)
2826
end
29-
function s.opccost(e,tp,eg,ep,ev,re,r,rp,chk)
30-
local c=e:GetHandler()
31-
if chk==0 then return c:GetFlagEffect(id)==0 end
32-
c:RegisterFlagEffect(id,RESET_CHAIN,0,1)
33-
end
34-
function s.target(e,tp,eg,ep,ev,re,r,rp,chk)
35-
local c=e:GetHandler()
36-
if chk==0 then return Duel.IsExistingMatchingCard(nil,tp,LOCATION_ONFIELD,LOCATION_ONFIELD,1,c) end
37-
local g=Duel.GetMatchingGroup(nil,tp,LOCATION_ONFIELD,LOCATION_ONFIELD,c)
38-
Duel.SetOperationInfo(0,CATEGORY_DESTROY,g,#g,0,0)
27+
function s.destg(e,tp,eg,ep,ev,re,r,rp,chk)
28+
local g=Duel.GetMatchingGroup(nil,tp,LOCATION_ONFIELD,LOCATION_ONFIELD,e:GetHandler())
29+
if chk==0 then return #g>0 end
30+
Duel.SetOperationInfo(0,CATEGORY_DESTROY,g,#g,tp,0)
3931
end
40-
function s.operation(e,tp,eg,ep,ev,re,r,rp)
32+
function s.desop(e,tp,eg,ep,ev,re,r,rp)
4133
local c=e:GetHandler()
42-
--Opponent takes no further damage this turn
34+
local exc=c:IsRelateToEffect(e) and c or nil
35+
local g=Duel.GetMatchingGroup(nil,tp,LOCATION_ONFIELD,LOCATION_ONFIELD,exc)
36+
if #g>0 then
37+
Duel.Destroy(g,REASON_EFFECT)
38+
end
39+
--Your opponent takes no damage for the rest of this turn
4340
local e1=Effect.CreateEffect(c)
41+
e1:SetDescription(aux.Stringid(id,1))
4442
e1:SetType(EFFECT_TYPE_FIELD)
43+
e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET+EFFECT_FLAG_CLIENT_HINT)
4544
e1:SetCode(EFFECT_CHANGE_DAMAGE)
46-
e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET)
4745
e1:SetTargetRange(0,1)
4846
e1:SetValue(0)
49-
e1:SetReset(RESET_PHASE+PHASE_END)
47+
e1:SetReset(RESET_PHASE|PHASE_END)
5048
Duel.RegisterEffect(e1,tp)
5149
local e2=e1:Clone()
5250
e2:SetCode(EFFECT_NO_EFFECT_DAMAGE)
53-
e2:SetReset(RESET_PHASE+PHASE_END)
5451
Duel.RegisterEffect(e2,tp)
55-
local g=Duel.GetMatchingGroup(nil,tp,LOCATION_ONFIELD,LOCATION_ONFIELD,c)
56-
Duel.Destroy(g,REASON_EFFECT)
5752
end

official/c64414267.lua

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,86 +2,77 @@
22
--Darktellarknight Batlamyus
33
local s,id=GetID()
44
function s.initial_effect(c)
5-
--Xyz Summon
6-
Xyz.AddProcedure(c,aux.FilterBoolFunctionEx(Card.IsSetCard,0x9c),4,2)
75
c:EnableReviveLimit()
8-
--Attribute change
6+
--Xyz Summon procedure: 2 Level 4 "tellarknight" monsters
7+
Xyz.AddProcedure(c,aux.FilterBoolFunctionEx(Card.IsSetCard,SET_TELLARKNIGHT),4,2)
8+
--All face-up monsters on the field become DARK
99
local e1=Effect.CreateEffect(c)
1010
e1:SetType(EFFECT_TYPE_FIELD)
1111
e1:SetCode(EFFECT_CHANGE_ATTRIBUTE)
1212
e1:SetRange(LOCATION_MZONE)
1313
e1:SetTargetRange(LOCATION_MZONE,LOCATION_MZONE)
1414
e1:SetValue(ATTRIBUTE_DARK)
1515
c:RegisterEffect(e1)
16-
--Special Summon from Extra Deck
16+
--Special Summon 1 LIGHT "tellarknight" Xyz Monster from your Extra Deck by using this face-up card you control as the Xyz Material
1717
local e2=Effect.CreateEffect(c)
1818
e2:SetDescription(aux.Stringid(id,0))
1919
e2:SetCategory(CATEGORY_SPECIAL_SUMMON)
2020
e2:SetType(EFFECT_TYPE_IGNITION)
2121
e2:SetRange(LOCATION_MZONE)
22-
e2:SetCondition(s.spcon)
23-
e2:SetCost(aux.AND(aux.dxmcostgen(1,1,nil),s.spdiscost))
22+
e2:SetCountLimit(1,0,EFFECT_COUNT_CODE_CHAIN)
23+
e2:SetCondition(aux.NOT(s.quickcon))
24+
e2:SetCost(Cost.AND(Cost.Detach(1),Cost.Discard()))
2425
e2:SetTarget(s.sptg)
2526
e2:SetOperation(s.spop)
2627
c:RegisterEffect(e2,false,REGISTER_FLAG_DETACH_XMAT)
2728
local e3=e2:Clone()
2829
e3:SetType(EFFECT_TYPE_QUICK_O)
2930
e3:SetCode(EVENT_FREE_CHAIN)
30-
e3:SetCondition(aux.NOT(s.spcon))
31+
e3:SetHintTiming(0,TIMING_STANDBY_PHASE|TIMING_MAIN_END|TIMINGS_CHECK_MONSTER_E)
32+
e3:SetCondition(s.quickcon)
3133
c:RegisterEffect(e3)
3234
end
33-
s.listed_series={0x9c}
34-
function s.cfilter(c)
35-
return c:IsSetCard(0x9c) and c:IsMonster()
35+
s.listed_series={SET_TELLARKNIGHT}
36+
function s.quickconfilter(c)
37+
return c:IsSetCard(SET_TELLARKNIGHT) and c:IsMonster()
3638
end
37-
function s.spcon(e,tp,eg,ep,ev,re,r,rp)
38-
local ct=Duel.GetMatchingGroup(s.cfilter,tp,LOCATION_GRAVE,0,nil)
39-
return ct:GetClassCount(Card.GetCode)<7
39+
function s.quickcon(e,tp,eg,ep,ev,re,r,rp)
40+
return Duel.GetMatchingGroup(s.quickconfilter,tp,LOCATION_GRAVE,0,nil):GetClassCount(Card.GetCode)>=7
4041
end
41-
function s.spdiscost(e,tp,eg,ep,ev,re,r,rp,chk)
42-
local c=e:GetHandler()
43-
if chk==0 then
44-
return c:GetFlagEffect(id)==0 and Duel.IsExistingMatchingCard(Card.IsDiscardable,tp,LOCATION_HAND,0,1,nil)
45-
end
46-
c:RegisterFlagEffect(id,RESET_CHAIN,0,1)
47-
Duel.DiscardHand(tp,Card.IsDiscardable,1,1,REASON_COST+REASON_DISCARD)
48-
end
49-
function s.spfilter(c,e,tp,mc,pg)
50-
return c:IsAttribute(ATTRIBUTE_LIGHT) and c:IsSetCard(0x9c) and Duel.GetLocationCountFromEx(tp,tp,mc,c)>0
42+
function s.spfilter(c,e,tp,mc)
43+
return c:IsAttribute(ATTRIBUTE_LIGHT) and c:IsSetCard(SET_TELLARKNIGHT) and c:IsType(TYPE_XYZ) and Duel.GetLocationCountFromEx(tp,tp,mc,c)>0
5144
and mc:IsCanBeXyzMaterial(c,tp) and c:IsCanBeSpecialSummoned(e,SUMMON_TYPE_XYZ,tp,false,false)
5245
end
5346
function s.sptg(e,tp,eg,ep,ev,re,r,rp,chk)
5447
if chk==0 then
5548
local c=e:GetHandler()
5649
local pg=aux.GetMustBeMaterialGroup(tp,Group.FromCards(c),tp,nil,nil,REASON_XYZ)
57-
return (#pg<=0 or (#pg==1 and pg:IsContains(c))) and Duel.IsExistingMatchingCard(s.spfilter,tp,LOCATION_EXTRA,0,1,nil,e,tp,c,pg)
50+
return (#pg<=0 or (#pg==1 and pg:IsContains(c))) and Duel.IsExistingMatchingCard(s.spfilter,tp,LOCATION_EXTRA,0,1,nil,e,tp,c)
5851
end
5952
Duel.SetOperationInfo(0,CATEGORY_SPECIAL_SUMMON,nil,1,tp,LOCATION_EXTRA)
6053
end
6154
function s.spop(e,tp,eg,ep,ev,re,r,rp)
6255
local c=e:GetHandler()
6356
local pg=aux.GetMustBeMaterialGroup(tp,Group.FromCards(c),tp,nil,nil,REASON_XYZ)
64-
if c:IsFaceup() and c:IsRelateToEffect(e) and c:IsControler(tp) and not c:IsImmuneToEffect(e) or #pg>1 or (#pg==1 and not pg:IsContains(tc)) then
57+
if c:IsFaceup() and c:IsRelateToEffect(e) and c:IsControler(tp) and not c:IsImmuneToEffect(e) and (#pg<=0 or (#pg==1 and pg:IsContains(c))) then
6558
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON)
66-
local g=Duel.SelectMatchingCard(tp,s.spfilter,tp,LOCATION_EXTRA,0,1,1,nil,e,tp,c,pg)
67-
local sc=g:GetFirst()
68-
if sc then
69-
sc:SetMaterial(c)
70-
Duel.Overlay(sc,c)
71-
Duel.SpecialSummon(sc,SUMMON_TYPE_XYZ,tp,tp,false,false,POS_FACEUP)
72-
sc:CompleteProcedure()
59+
local xyzc=Duel.SelectMatchingCard(tp,s.spfilter,tp,LOCATION_EXTRA,0,1,1,nil,e,tp,c):GetFirst()
60+
if xyzc then
61+
xyzc:SetMaterial(c)
62+
Duel.Overlay(xyzc,c)
63+
if Duel.SpecialSummon(xyzc,SUMMON_TYPE_XYZ,tp,tp,false,false,POS_FACEUP)>0 then
64+
xyzc:CompleteProcedure()
65+
end
7366
end
7467
end
68+
--You cannot Xyz Summon other monsters for the rest of this turn
7569
local e1=Effect.CreateEffect(c)
70+
e1:SetDescription(aux.Stringid(id,1))
7671
e1:SetType(EFFECT_TYPE_FIELD)
77-
e1:SetCode(EFFECT_CANNOT_SPECIAL_SUMMON)
7872
e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET+EFFECT_FLAG_CLIENT_HINT)
79-
e1:SetDescription(aux.Stringid(id,1))
73+
e1:SetCode(EFFECT_CANNOT_SPECIAL_SUMMON)
8074
e1:SetTargetRange(1,0)
81-
e1:SetTarget(s.splimit)
82-
e1:SetReset(RESET_PHASE+PHASE_END)
75+
e1:SetTarget(function(e,c,sump,sumtype) return (sumtype&SUMMON_TYPE_XYZ)==SUMMON_TYPE_XYZ end)
76+
e1:SetReset(RESET_PHASE|PHASE_END)
8377
Duel.RegisterEffect(e1,tp)
8478
end
85-
function s.splimit(e,c,sump,sumtype,sumpos,targetp,se)
86-
return (sumtype&SUMMON_TYPE_XYZ)==SUMMON_TYPE_XYZ
87-
end

utility.lua

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,6 +1541,7 @@ end
15411541
-- group of just detached materials in order to do some additional handling with
15421542
-- them.
15431543
function Auxiliary.dxmcostgen(min,max,op)
1544+
max=max or min
15441545
do --Perform some sanity checks, simplifies debugging
15451546
local max_type=type(max)
15461547
local op_type=type(op)
@@ -1560,14 +1561,63 @@ function Auxiliary.dxmcostgen(min,max,op)
15601561
local crm=c:CheckRemoveOverlayCard(tp,min,REASON_COST)
15611562
if chk==0 then return (nn and c:IsLocation(LOCATION_MZONE)) or crm end
15621563
if nn and (not crm or Duel.SelectYesNo(tp,aux.Stringid(CARD_NUMERON_NETWORK,1))) then
1563-
Duel.Hint(HINT_CARD,tp,CARD_NUMERON_NETWORK)
1564-
return true --NOTE: Does not execute `op`
1564+
--Do not execute `op`, hint at "Numeron Network" being applied
1565+
return Duel.Hint(HINT_CARD,tp,CARD_NUMERON_NETWORK)
15651566
end
15661567
local m=type(max)=="number" and max or max(e,tp)
15671568
if c:RemoveOverlayCard(tp,min,m,REASON_COST)>0 and op then
15681569
op(e,Duel.GetOperatedGroup())
15691570
end
1570-
return true --NOTE: to use with aux.AND
1571+
end
1572+
end
1573+
1574+
1575+
Cost={}
1576+
1577+
Cost.SelfBanish=aux.bfgcost
1578+
Cost.SelfRelease=aux.selfreleasecost
1579+
Cost.SelfTribute=aux.selfreleasecost
1580+
Cost.SelfToGrave=aux.SelfToGraveCost
1581+
Cost.SelfToHand=aux.SelfToHandCost
1582+
Cost.SelfToDeck=aux.SelfToDeckCost
1583+
Cost.SelfToExtra=aux.SelfToExtraCost
1584+
Cost.SelfDiscard=aux.SelfDiscardCost
1585+
Cost.SelfDiscardToGrave=aux.SelfDiscardToGraveCost
1586+
Cost.SelfRevealCost=aux.SelfRevealCost
1587+
1588+
Cost.Detach=aux.dxmcostgen
1589+
Cost.Discard=aux.DiscardCost
1590+
Cost.PayLP=aux.PayLPCost
1591+
1592+
function Cost.SoftOncePerChain(flag)
1593+
return function(e,tp,eg,ep,ev,re,r,rp,chk)
1594+
local c=e:GetHandler()
1595+
if chk==0 then return not c:HasFlagEffect(flag) end
1596+
c:RegisterFlagEffect(flag,RESET_EVENT|RESETS_STANDARD|RESET_CHAIN,0,1)
1597+
end
1598+
end
1599+
1600+
function Cost.HardOncePerChain(flag)
1601+
return function(e,tp,eg,ep,ev,re,r,rp,chk)
1602+
if chk==0 then return not Duel.HasFlagEffect(tp,id) end
1603+
Duel.RegisterFlagEffect(tp,id,RESET_CHAIN,0,1)
1604+
end
1605+
end
1606+
1607+
function Cost.AND(...)
1608+
local fns={...}
1609+
return function(e,tp,eg,ep,ev,re,r,rp,chk)
1610+
--when checking, stop at the first falsy value
1611+
if chk==0 then
1612+
for _,fn in ipairs(fns) do
1613+
if not fn(e,tp,eg,ep,ev,re,r,rp,0) then return false end
1614+
end
1615+
return true
1616+
end
1617+
--when executing, run all functions regardless of what they return
1618+
for _,fn in ipairs(fns) do
1619+
fn(e,tp,eg,ep,ev,re,r,rp,1)
1620+
end
15711621
end
15721622
end
15731623

0 commit comments

Comments
 (0)