Functions for "Choose a Creature Type"
Now updated to work with official Deck Pack 3
I made these functions while working on Patriarch's Bidding for my mod. Those who have downloaded and are using my mod v1.0 already have these functions and should be able to use them without problem. I have posted this here for people who either want to include my functions in their mod (without requiring mine) or for people who want to analyze them without downloading/unpacking my mod. I have also added the permanent text for these functions in an attachment.
Constants:
Edit: Since I have now added creature types for 4 more partially implemented creature types (Hippogriff, Siren, Surrakar, Townsfolk) I have included the new spec (adds types to game so they can be used with filters) and text files (required for my above code to show proper text) for this all to work.
The new types were added after the other partially implemented type of Germ (which was added after Werewolf) so these should not conflict with any existing mod that I am aware of.
Edit 2: Added RSN_FindPlayerCreatureTypesInZones() to make getting creature types from multiple zones for a player easier.
Edit 3: Added ChooseCreatureTypeFiles.zip to the post which contains all of the above code (except the example card Patriarch's Bidding) into a single downloadable package to getting all of this somewhat easier than copying and pasting it all one block at a time.
Edit 4: Added two more missing types (These were completely missing from the game): Hyena, Noggle
I updated the code somewhat to make adding new types take less time (though hopefully we won't need to add any more) by adding _CREATURE_TYPE_FIRST, _CREATURE_TYPE_LAST, and _CREATURE_TYPE_COUNT constants and updating the code to use them where appropriate. I've also updated both the attachments so there should be no old code here.
Edit 5: The official game was updated to support the Surrakar type for a card in Deck Pack 3, this meant that Germ and those I had above Surrakar had to be shifted down 1. The only changes here are in the Constants and string table.
I made these functions while working on Patriarch's Bidding for my mod. Those who have downloaded and are using my mod v1.0 already have these functions and should be able to use them without problem. I have posted this here for people who either want to include my functions in their mod (without requiring mine) or for people who want to analyze them without downloading/unpacking my mod. I have also added the permanent text for these functions in an attachment.
Constants:
- Code: Select all
-- /////////////////////////////////////////////////////////////////////////////
-- Creature Types
CREATURE_TYPE_GERM = SIZE_OF_TYPE_BAND * CARD_TYPE_CREATURE + 222
CREATURE_TYPE_HIPPOGRIFF = SIZE_OF_TYPE_BAND * CARD_TYPE_CREATURE + 223
CREATURE_TYPE_SIREN = SIZE_OF_TYPE_BAND * CARD_TYPE_CREATURE + 224
CREATURE_TYPE_TOWNSFOLK = SIZE_OF_TYPE_BAND * CARD_TYPE_CREATURE + 225
CREATURE_TYPE_HYENA = SIZE_OF_TYPE_BAND * CARD_TYPE_CREATURE + 226
CREATURE_TYPE_NOGGLE = SIZE_OF_TYPE_BAND * CARD_TYPE_CREATURE + 227
_CREATURE_TYPE_COUNT = 228
_CREATURE_TYPE_FIRST = CREATURE_TYPE_HUMAN
_CREATURE_TYPE_LAST = CREATURE_TYPE_NOGGLE
-- /////////////////////////////////////////////////////////////////////////////
-- Constants for Creature Type Selection
REGISTER_SELECTION_COUNT = 0
REGISTER_SELECTION_BEST_TYPE_INDEX = 1000
REGISTER_SELECTION_WORST_TYPE_INDEX = 1001
REGISTER_SELECTION_SELECTED_INDEX = 1002
REGISTER_SELECTION_SELECTED_TYPE = 1003
REGISTER_SELECTION_FIRST_TIME_INDICATOR = 2000
REGISTER_SELECTION_FORCE_FULL_LIST = 2001
- Code: Select all
-- /////////////////////////////////////////////////////////////////////////////
-- Asking Player for a Choice //////////////////////////////////////////////////
-- NOTE: This function must be used from within an iterating action block,
-- preferrably as the only major action in that action block.
RSN_ChooseCreatureType = function( oPlayer, oChest )
local nChoice = Object():GetMultipleChoiceResult()
local nCurrentType = oChest:Int_Get( REGISTER_SELECTION_SELECTED_TYPE )
local nMin = _CREATURE_TYPE_FIRST
local nMax = _CREATURE_TYPE_LAST
if (oChest:Int_Get( REGISTER_SELECTION_FIRST_TIME_INDICATOR ) == 0) then
-- We don't check the choice the first time through, but we need to
-- indicate that we've already gone through the first time for
-- subsequent iterations.
oChest:Int_Dec( REGISTER_SELECTION_FIRST_TIME_INDICATOR )
if (oPlayer:IsAI() ~= 0) then
-- We don't present the creature type choice to AIs and instead
-- just have them choose the default.
return false
end
else
-- Not our first time through so do operations based on choice.
if (nChoice == 0) then
-- Go back one type.
nCurrentType = nCurrentType - 1
if (nCurrentType < nMin) then
-- We went below our minimum so wrap around.
nCurrentType = nMax
end
elseif (nChoice == 1) then
-- Player made their choice so go on to next action.
return false
else
-- Go forward one type.
nCurrentType = nCurrentType + 1
if (nCurrentType > nMax) then
-- We went above our maximum so wrap around.
nCurrentType = nMin
end
end
-- This makes sure the type persists.
oChest:Int_Set( REGISTER_SELECTION_SELECTED_TYPE, nCurrentType )
end
-- We made it this far which means we need to give the player a choice.
oPlayer:BeginNewMultipleChoice()
oPlayer:AddMultipleChoiceAnswer( "CARD_QUERY_OPTION_PREVIOUS" )
oPlayer:AddMultipleChoiceAnswer( "CARD_QUERY_OPTION_CREATURE_TYPE_"..nCurrentType )
oPlayer:AddMultipleChoiceAnswer( "CARD_QUERY_OPTION_NEXT" )
oPlayer:AskMultipleChoiceQuestion( "CARD_QUERY_MC_CREATURE_TYPE" )
return true
end
-- NOTE: This function must be used from within an iterating action block,
-- preferrably as the only major action in that action block.
RSN_ChooseCreatureTypeFromDC = function( oPlayer, oChest )
local nForceFullList = oChest:Int_Get( REGISTER_SELECTION_FORCE_FULL_LIST )
if (nForceFullList > 0) then
return RSN_ChooseCreatureType( oPlayer, oChest )
else
local nChoice = Object():GetMultipleChoiceResult()
local nCurrentIndex = oChest:Int_Get( REGISTER_SELECTION_SELECTED_INDEX )
local nCurrentType = oChest:Int_Get( nCurrentIndex )
local nMinIndex = 1
local nMaxIndex = oChest:Int_Get( REGISTER_SELECTION_COUNT )
if (oChest:Int_Get( REGISTER_SELECTION_FIRST_TIME_INDICATOR ) == 0) then
-- We don't check the choice the first time through, but we need to
-- indicate that we've already gone through the first time for
-- subsequent iterations.
oChest:Int_Dec( REGISTER_SELECTION_FIRST_TIME_INDICATOR )
if (oPlayer:IsAI() ~= 0) then
-- We don't present the creature type choice to AIs and instead
-- just have them choose the default.
return false
end
-- Now we add an option allowing them to use choose from full list
-- instead of just the recommended list.
local nNewOption = oChest:Int_Get( REGISTER_SELECTION_COUNT ) + 1
oChest:Int_Set( nNewOption, -1 )
oChest:Int_Set( REGISTER_SELECTION_COUNT, nNewOption )
else
-- Not our first time through so do operations based on choice.
if (nChoice == 0) then
-- Go back one index.
nCurrentIndex = nCurrentIndex - 1
if (nCurrentIndex < nMinIndex) then
-- We went below our first index so wrap around.
nCurrentIndex = nMaxIndex
end
nCurrentType = oChest:Int_Get( nCurrentIndex )
elseif (nChoice == 1) then
-- Player made their choice so go on to next action.
if (nCurrentType == -1) then
-- Player actually asked to choose from Full List.
-- Reset first time indicator due to list change.
oChest:Int_Inc( REGISTER_SELECTION_FIRST_TIME_INDICATOR )
-- Start them off at top of list.
oChest:Int_Set( REGISTER_SELECTION_SELECTED_TYPE, CREATURE_TYPE_HUMAN )
-- Flip on Forced Full List.
oChest:Int_Set( REGISTER_SELECTION_FORCE_FULL_LIST, 1 )
-- Go ahead and give them a choice this iteration.
return RSN_ChooseCreatureType( oPlayer, oChest )
else
return false
end
else
-- Go forward one index.
nCurrentIndex = nCurrentIndex + 1
if (nCurrentIndex > nMaxIndex) then
-- We went above our maximum index so wrap around.
nCurrentIndex = nMinIndex
end
nCurrentType = oChest:Int_Get( nCurrentIndex )
end
-- This makes sure the index persists.
oChest:Int_Set( REGISTER_SELECTION_SELECTED_INDEX, nCurrentIndex )
end
-- We made it this far which means we need to give the player a choice.
oPlayer:BeginNewMultipleChoice()
oPlayer:AddMultipleChoiceAnswer( "CARD_QUERY_OPTION_PREVIOUS" )
oPlayer:AddMultipleChoiceAnswer( "CARD_QUERY_OPTION_CREATURE_TYPE_"..nCurrentType )
oPlayer:AddMultipleChoiceAnswer( "CARD_QUERY_OPTION_NEXT" )
oPlayer:AskMultipleChoiceQuestion( "CARD_QUERY_MC_CREATURE_TYPE" )
return true
end
end
-- /////////////////////////////////////////////////////////////////////////////
-- Retrieving Choices //////////////////////////////////////////////////////////
RSN_GetChosenCreatureType = function( oChest )
local nIndex = oChest:Int_Get( REGISTER_SELECTION_SELECTED_INDEX )
local nType = oChest:Int_Get( nIndex )
if (nType == -1) then
nType = oChest:Int_Get( REGISTER_SELECTION_SELECTED_TYPE )
end
return nType
end
- Code: Select all
-- We will find all creature types that a player has in a particular zone (though it
-- may not work for Changeling, I don't know) and put the creature type of which the
-- player has the most creatures in this zone into int REGISTER_SELECTION_BEST_TYPE.
RSN_FindPlayerCreatureTypesInZone = function( oChest, oPlayer, nZone )
local nMaxFound = 0
local nMinFound = 999
local nBestTypeIndex = -1
local nWorstTypeIndex = -1
local nTypesFound = 0
for i=_CREATURE_TYPE_FIRST,_CREATURE_TYPE_LAST do
local nCount = RSN_CountPlayerCardsOfTypeAndSubTypeInZone( oPlayer, CARD_TYPE_CREATURE, i, nZone )
if (nCount > 0) then
nTypesFound = nTypesFound + 1
oChest:Int_Set( nTypesFound, i )
if (nCount > nMaxFound) then
nMaxFound = nCount
nBestTypeIndex = nTypesFound
end
if (nCount < nMinFound) then
nMinFound = nCount
nWorstTypeIndex = nTypesFound
end
end
end
oChest:Int_Set( REGISTER_SELECTION_COUNT, nTypesFound )
oChest:Int_Set( REGISTER_SELECTION_BEST_TYPE_INDEX, nBestTypeIndex )
oChest:Int_Set( REGISTER_SELECTION_WORST_TYPE_INDEX, nWorstTypeIndex )
end
-- We will find all creature types that a player has in multiple zones (though it
-- may not work for Changeling, I don't know) and put the creature type of which the
-- player has the most creatures in this zone into int REGISTER_SELECTION_BEST_TYPE.
RSN_FindPlayerCreatureTypesInZones = function( oChest, oPlayer, ... )
local nMaxFound = 0
local nMinFound = 999
local nBestTypeIndex = -1
local nWorstTypeIndex = -1
local nTypesFound = 0
for i=_CREATURE_TYPE_FIRST,_CREATURE_TYPE_LAST do
local nCount = 0
for _, nZone in ipairs(arg) do
nCount = nCount + RSN_CountPlayerCardsOfTypeAndSubTypeInZone( oPlayer, CARD_TYPE_CREATURE, i, nZone )
end
if (nCount > 0) then
nTypesFound = nTypesFound + 1
oChest:Int_Set( nTypesFound, i )
if (nCount > nMaxFound) then
nMaxFound = nCount
nBestTypeIndex = nTypesFound
end
if (nCount < nMinFound) then
nMinFound = nCount
nWorstTypeIndex = nTypesFound
end
end
end
oChest:Int_Set( REGISTER_SELECTION_COUNT, nTypesFound )
oChest:Int_Set( REGISTER_SELECTION_BEST_TYPE_INDEX, nBestTypeIndex )
oChest:Int_Set( REGISTER_SELECTION_WORST_TYPE_INDEX, nWorstTypeIndex )
end
- Code: Select all
RSN_CountPlayerCardsOfTypeAndSubTypeInZone = function( oPlayer, nType, nSubType, nZone )
local oFilter = Object():GetFilter()
oFilter:Clear()
oFilter:SetZone( nZone )
oFilter:AddCardType( nType )
oFilter:AddSubType( nSubType )
oFilter:SetController( oPlayer )
oFilter:NotTargetted()
return oFilter:Count()
end
- Code: Select all
<?xml version='1.0'?>
<CARD_V2>
<FILENAME text="PATRIARCHS_BIDDING_26747" />
<CARDNAME text="PATRIARCHS_BIDDING" />
<TITLE>
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Patriarch's Bidding]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Ordre du patriarche]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Órdenes del Patriarca]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Gebot des Patriarchen]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Comando del Patriarca]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[Patriarch's Bidding]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[Patriarch's Bidding]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Patriarch's Bidding]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Comando do Patriarca]]></LOCALISED_TEXT>
</TITLE>
<MULTIVERSEID value="26747" />
<ARTID value="RSN26747" />
<ARTIST name="Ben Thompson" />
<CASTING_COST cost="{3}{B}{B}" />
<FLAVOURTEXT>
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA["Family plots are so convenient."
—Cabal Patriarch]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[« Les complots de famille sont si distrayants. »
—Le patriarche de la Coterie]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="es-ES"><![CDATA["Las parcelas familiares en los cementerios son muy prácticas".
Patriarca de la Cábala]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[„Es ist bequem, wenn alles in der Familie bleibt."
—Patriarch der Kabbalisten]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="it-IT"><![CDATA["Gli intrighi di famiglia sono davvero utili".
—Patriarca della Cabala]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA["Family plots are so convenient."
—Cabal Patriarch]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA["Family plots are so convenient."
—Cabal Patriarch]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA["Family plots are so convenient."
—Cabal Patriarch]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA["As intrigas familiares são tão convenientes."
— Patriarca da Cabala]]></LOCALISED_TEXT>
</FLAVOURTEXT>
<TYPE metaname="Sorcery" />
<EXPANSION value="ONS" />
<RARITY metaname="R" />
<SPELL_ABILITY filter_zone="ZONE_IN_PLAY">
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Each player chooses a creature type. Each player returns all creature cards of a type chosen this way from his or her graveyard to play.]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Chaque joueur choisit un type de créature. Chaque joueur renvoie en jeu toutes les cartes de créature du type choisi se trouvant dans son cimetière.]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Cada jugador elige un tipo de criatura. Cada jugador regresa al juego todas las cartas de criatura del tipo elegido de esta manera de su cementerio.]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Jeder Spieler bestimmt einen Kreaturentyp. Jeder Spieler bringt alle Kreaturenkarten, die mindestens einen der so bestimmten Kreaturentypen haben, aus seinem Friedhof ins Spiel zurück.]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Ogni giocatore sceglie un tipo di creatura. Ogni giocatore rimette in gioco tutte le carte creatura di un tipo scelto presenti nel proprio cimitero.]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[Each player chooses a creature type. Each player returns all creature cards of a type chosen this way from his or her graveyard to play.]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[Each player chooses a creature type. Each player returns all creature cards of a type chosen this way from his or her graveyard to play.]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Each player chooses a creature type. Each player returns all creature cards of a type chosen this way from his or her graveyard to play.]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Cada jogador escolhe um tipo de criatura. Cada jogador devolve todos os cards de criatura de um dos tipos escolhidos desta maneira de seu cemitério para o jogo.]]></LOCALISED_TEXT>
<RESOLUTION_TIME_ACTION>
-- Set things up here.
for i=0,MTG():GetNumberOfPlayers()-1 do
local oPlayer = MTG():GetNthPlayer( i )
EffectDC():Make_Chest( i )
-- Look-up creature types in player's graveyard.
RSN_FindPlayerCreatureTypesInZone( EffectDC():Get_Chest( i ), oPlayer, ZONE_GRAVEYARD )
-- Set the best type as default
local nBestIndex = EffectDC():Get_Chest( i ):Int_Get( REGISTER_SELECTION_BEST_TYPE_INDEX )
EffectDC():Get_Chest( i ):Int_Set( REGISTER_SELECTION_SELECTED_INDEX, nBestIndex )
end
-- This is so we know where we are at each step.
EffectDC():Int_Set( 10, -1 )
</RESOLUTION_TIME_ACTION>
<!-- Unfortunately, I am unable to have all players choose a type in the same action
so it must be separated into different play time actions for each player. -->
<RESOLUTION_TIME_ACTION repeating="1">
return RSN_ChooseCreatureTypeFromDC( MTG():GetNthPlayer( 0 ), EffectDC():Get_Chest( 0 ) )
</RESOLUTION_TIME_ACTION>
<RESOLUTION_TIME_ACTION repeating="1">
return RSN_ChooseCreatureTypeFromDC( MTG():GetNthPlayer( 1 ), EffectDC():Get_Chest( 1 ) )
</RESOLUTION_TIME_ACTION>
<RESOLUTION_TIME_ACTION repeating="1">
if (MTG():GetNumberOfPlayers() > 2) then
return RSN_ChooseCreatureTypeFromDC( MTG():GetNthPlayer( 2 ), EffectDC():Get_Chest( 2 ) )
else
return false
end
</RESOLUTION_TIME_ACTION>
<RESOLUTION_TIME_ACTION repeating="1">
if (MTG():GetNumberOfPlayers() > 3) then
return RSN_ChooseCreatureTypeFromDC( MTG():GetNthPlayer( 3 ), EffectDC():Get_Chest( 3 ) )
else
return false
end
</RESOLUTION_TIME_ACTION>
<!-- Now all players have had a chance to choose a creature type so now comes the easy
part, putting the creatures of the chosen type onto the battlefield. -->
<RESOLUTION_TIME_ACTION>
for i=0,MTG():GetNumberOfPlayers()-1 do
local oPlayer = MTG():GetNthPlayer( i )
local nChosenType = RSN_GetChosenCreatureType( EffectDC():Get_Chest( i ) )
local oFilter = Object():GetFilter()
oFilter:Clear()
oFilter:SetZone( ZONE_GRAVEYARD )
oFilter:SetPlayer( oPlayer )
oFilter:AddCardType( CARD_TYPE_CREATURE )
oFilter:AddSubType( nChosenType )
local nCount = oFilter:EvaluateObjects()
if (nCount > 0) then
for j=0,nCount-1 do
local oCard = oFilter:GetNthEvaluatedObject( j )
if (oCard ~= nil) then
oCard:PutIntoPlay( oPlayer )
end
end
end
end
</RESOLUTION_TIME_ACTION>
</SPELL_ABILITY>
</CARD_V2>
Edit: Since I have now added creature types for 4 more partially implemented creature types (Hippogriff, Siren, Surrakar, Townsfolk) I have included the new spec (adds types to game so they can be used with filters) and text files (required for my above code to show proper text) for this all to work.
The new types were added after the other partially implemented type of Germ (which was added after Werewolf) so these should not conflict with any existing mod that I am aware of.
Edit 2: Added RSN_FindPlayerCreatureTypesInZones() to make getting creature types from multiple zones for a player easier.
Edit 3: Added ChooseCreatureTypeFiles.zip to the post which contains all of the above code (except the example card Patriarch's Bidding) into a single downloadable package to getting all of this somewhat easier than copying and pasting it all one block at a time.
Edit 4: Added two more missing types (These were completely missing from the game): Hyena, Noggle
I updated the code somewhat to make adding new types take less time (though hopefully we won't need to add any more) by adding _CREATURE_TYPE_FIRST, _CREATURE_TYPE_LAST, and _CREATURE_TYPE_COUNT constants and updating the code to use them where appropriate. I've also updated both the attachments so there should be no old code here.
Edit 5: The official game was updated to support the Surrakar type for a card in Deck Pack 3, this meant that Germ and those I had above Surrakar had to be shifted down 1. The only changes here are in the Constants and string table.