name: Saffira,
card_text: You can discard this card; send 1 Ritual Spell from your Deck to the GY, then you can add 1 LIGHT Ritual Monster (Warrior or Dragon) from your Deck or GY to your hand. You can banish this card from your GY; Ritual Summon 1 LIGHT Ritual Monster (Warrior or Dragon) from your hand, by Tributing monsters from your hand or field whose total Levels equal or exceed the Level of the Ritual Monster. You can only use each effect of "Saffira, Dragon Queen of the Voiceless Voice" once per turn.
lua: local s, id, o = GetID()
  function s.initial_effect(c)
  	--to grave search
  	local e1 = Effect.CreateEffect(c)
  	e1:SetDescription(aux.Stringid(id, 0))
  	e1:SetCategory(CATEGORY_TOHAND + CATEGORY_SEARCH + CATEGORY_TOGRAVE + CATEGORY_GRAVE_ACTION)
  	e1:SetType(EFFECT_TYPE_IGNITION)
  	e1:SetRange(LOCATION_HAND)
  	e1:SetCountLimit(1, id)
  	e1:SetCost(s.tscost)
  	e1:SetTarget(s.tstg)
  	e1:SetOperation(s.tsop)
  	c:RegisterEffect(e1)
  	--Ritual Summon
  	local e2 = aux.AddRitualProcGreater2(c, s.filter, LOCATION_HAND, nil, nil, true)
  	e2:SetType(EFFECT_TYPE_IGNITION)
  	e2:SetRange(LOCATION_GRAVE)
  	e2:SetCountLimit(1, id + o)
  	e2:SetCost(aux.bfgcost)
  	c:RegisterEffect(e2)
  end
  function s.tscost(e, tp, eg, ep, ev, re, r, rp, chk)
  	local c = e:GetHandler()
  	if chk == 0 then
  		return c:IsDiscardable()
  	end
  	Duel.SendtoGrave(c, REASON_COST + REASON_DISCARD)
  end
  function s.tsfilter(c)
  	return c:IsType(TYPE_RITUAL) and c:IsType(TYPE_SPELL) and c:IsAbleToGrave()
  end
  function s.tstg(e, tp, eg, ep, ev, re, r, rp, chk)
  	if chk == 0 then
  		return Duel.IsExistingMatchingCard(s.tsfilter, tp, LOCATION_DECK, 0, 1, nil)
  	end
  	Duel.SetOperationInfo(0, CATEGORY_TOGRAVE, nil, 1, tp, LOCATION_DECK)
  end
  function s.thfilter(c)
  	return c:IsRace(RACE_DRAGON + RACE_WARRIOR) and c:IsType(TYPE_RITUAL) and c:IsAttribute(ATTRIBUTE_LIGHT) and c:IsAbleToHand()
  end
  function s.tsop(e, tp, eg, ep, ev, re, r, rp, chk)
  	Duel.Hint(HINT_SELECTMSG, tp, HINTMSG_TOGRAVE)
  	local g = Duel.SelectMatchingCard(tp, s.tsfilter, tp, LOCATION_DECK, 0, 1, 1, nil)
  	if
  		g:GetCount() > 0
  		and Duel.SendtoGrave(g, REASON_EFFECT) > 0
  		and g:GetFirst():IsLocation(LOCATION_GRAVE)
  		and Duel.IsExistingMatchingCard(aux.NecroValleyFilter(s.thfilter), tp, LOCATION_GRAVE + LOCATION_DECK, 0, 1, nil)
  		and Duel.SelectYesNo(tp, aux.Stringid(id, 1))
  	then
  		Duel.BreakEffect()
  		Duel.Hint(HINT_SELECTMSG, tp, HINTMSG_ATOHAND)
  		local sg = Duel.SelectMatchingCard(tp, aux.NecroValleyFilter(s.thfilter), tp, LOCATION_GRAVE + LOCATION_DECK, 0, 1, 1, nil)
  		Duel.SendtoHand(sg, nil, REASON_EFFECT)
  		Duel.ConfirmCards(1 - tp, sg)
  	end
  end
  function s.filter(c, e, tp, chk)
  	return c:IsRace(RACE_DRAGON + RACE_WARRIOR) and c:IsType(TYPE_RITUAL) and c:IsAttribute(ATTRIBUTE_LIGHT) and (not chk or c ~= e:GetHandler())
  end
  
  
source_text: Saffira,
  You can discard this card; send 1 Ritual Spell from your Deck to the GY, then you can add 1 LIGHT Ritual Monster (Warrior or Dragon) from your Deck or GY to your hand. You can banish this card from your GY; Ritual Summon 1 LIGHT Ritual Monster (Warrior or Dragon) from your hand, by Tributing monsters from your hand or field whose total Levels equal or exceed the Level of the Ritual Monster. You can only use each effect of "Saffira, Dragon Queen of the Voiceless Voice" once per turn.
target_text: -- Saffira,
  local s, id, o = GetID()
  function s.initial_effect(c)
  	--to grave search
  	local e1 = Effect.CreateEffect(c)
  	e1:SetDescription(aux.Stringid(id, 0))
  	e1:SetCategory(CATEGORY_TOHAND + CATEGORY_SEARCH + CATEGORY_TOGRAVE + CATEGORY_GRAVE_ACTION)
  	e1:SetType(EFFECT_TYPE_IGNITION)
  	e1:SetRange(LOCATION_HAND)
  	e1:SetCountLimit(1, id)
  	e1:SetCost(s.tscost)
  	e1:SetTarget(s.tstg)
  	e1:SetOperation(s.tsop)
  	c:RegisterEffect(e1)
  	--Ritual Summon
  	local e2 = aux.AddRitualProcGreater2(c, s.filter, LOCATION_HAND, nil, nil, true)
  	e2:SetType(EFFECT_TYPE_IGNITION)
  	e2:SetRange(LOCATION_GRAVE)
  	e2:SetCountLimit(1, id + o)
  	e2:SetCost(aux.bfgcost)
  	c:RegisterEffect(e2)
  end
  function s.tscost(e, tp, eg, ep, ev, re, r, rp, chk)
  	local c = e:GetHandler()
  	if chk == 0 then
  		return c:IsDiscardable()
  	end
  	Duel.SendtoGrave(c, REASON_COST + REASON_DISCARD)
  end
  function s.tsfilter(c)
  	return c:IsType(TYPE_RITUAL) and c:IsType(TYPE_SPELL) and c:IsAbleToGrave()
  end
  function s.tstg(e, tp, eg, ep, ev, re, r, rp, chk)
  	if chk == 0 then
  		return Duel.IsExistingMatchingCard(s.tsfilter, tp, LOCATION_DECK, 0, 1, nil)
  	end
  	Duel.SetOperationInfo(0, CATEGORY_TOGRAVE, nil, 1, tp, LOCATION_DECK)
  end
  function s.thfilter(c)
  	return c:IsRace(RACE_DRAGON + RACE_WARRIOR) and c:IsType(TYPE_RITUAL) and c:IsAttribute(ATTRIBUTE_LIGHT) and c:IsAbleToHand()
  end
  function s.tsop(e, tp, eg, ep, ev, re, r, rp, chk)
  	Duel.Hint(HINT_SELECTMSG, tp, HINTMSG_TOGRAVE)
  	local g = Duel.SelectMatchingCard(tp, s.tsfilter, tp, LOCATION_DECK, 0, 1, 1, nil)
  	if
  		g:GetCount() > 0
  		and Duel.SendtoGrave(g, REASON_EFFECT) > 0
  		and g:GetFirst():IsLocation(LOCATION_GRAVE)
  		and Duel.IsExistingMatchingCard(aux.NecroValleyFilter(s.thfilter), tp, LOCATION_GRAVE + LOCATION_DECK, 0, 1, nil)
  		and Duel.SelectYesNo(tp, aux.Stringid(id, 1))
  	then
  		Duel.BreakEffect()
  		Duel.Hint(HINT_SELECTMSG, tp, HINTMSG_ATOHAND)
  		local sg = Duel.SelectMatchingCard(tp, aux.NecroValleyFilter(s.thfilter), tp, LOCATION_GRAVE + LOCATION_DECK, 0, 1, 1, nil)
  		Duel.SendtoHand(sg, nil, REASON_EFFECT)
  		Duel.ConfirmCards(1 - tp, sg)
  	end
  end
  function s.filter(c, e, tp, chk)
  	return c:IsRace(RACE_DRAGON + RACE_WARRIOR) and c:IsType(TYPE_RITUAL) and c:IsAttribute(ATTRIBUTE_LIGHT) and (not chk or c ~= e:GetHandler())
  end
  
  