>>> LackeyCCG Tutorial: Plugin Creation - How to make a plugininfo.txt

 


This page explains how to create the most important (and only required) file of your plugin: plugininfo.txt.

The Structure of plugininfo.txt

The structure of plugininfo.txt is very similar to XML format if you are familiar with that. There are blocks of data that start with <VALUE> and end with </VALUE>, for example, <plugin></plugin>. Everything between those tags is a data entry of that block (of the "plugin" block, in that example). Each data member can in turn have subsections and it's own data entries. Below you can see a plugin entry which includes within it 2 gamezone entries. Each gamezone entry has sub-entries of it's own. This sort of data definition hierarchy is used throughout the creation of a plugin.

<plugin>

<gamezone>
      <label>Hand</label>
     <visibletoowner>yes</visibletoowner>
     <visibletoothers>no</visibletoothers>
</gamezone>

<gamezone>
      <label>Deck</label>
      <visibletoowner>no</visibletoowner>
      <visibletoothers>no</visibletoothers>
</gamezone>

</plugin>

 

The white space (i.e., tabs, spaces, new lines) within blocks is optional. You can indent however you want, or not at all. You could even include your entire plugininfo.txt contents on a single line if you wanted to, but that would be really difficult to parse while you are reading it, so I wouldn't advise that.
If you look at the example above, the lines in red can be omitted because the default visibility setting for any zone is that it is not visible. The above example could also be done like:

<plugin>
<gamezone><label>Hand</label> <visibletoowner>yes</visibletoowner></gamezone>
<gamezone><label>Deck</label></gamezone>
</plugin>

//This is a note. You can do anything you want outside of the data blocks, including writing notes if you want to.

 

Those two examples are functionally identical. You may find it is easier to read your plugininfo.txt if you indent it based on the tags, with the indentation reflecting the data definition hierarchy. Do whatever style makes sense to you. Typcially, only you will be seeing this file.

The data that defines how your plugin works typically is put in this order in plugininfo.txt:

Global Stats

Players Stats

DeckZones

GameZones

Phases (of the turn)

General Functions

Card Functions

All other defintions

I made sections for each of those subcategories.


Global Stats

A global stat is a stat that some games have that keeps track of some communal value. In contrast to player stats where every player gets a copy of the stat, a global stat is shared by all players. (The red part is a default value and can be omitted.)

<globalstat><label>Chaos</label><initialvalue>0</initialvalue></globalstat>
<globalstat><label>Plague</label><initialvalue>10</initialvalue></globalstat>

The preceding is a definition of two global stats. A globalstat has two data members: name and initial value. The default value for the name is "Stat 1", "Stat 2" and so forth. The default initial value for a global stat is 0, so the initial value of the Chaos stat in that example could have been omitted.


Player Stats

Every player gets their own copy of each player stat. Player stats are defined exactly the same as global stats. Here is an example of two player stats representing each player's Health and Energy. (The red part is a default value and can be omitted.)

<playerstat><label>Health</label><initialvalue>20</initialvalue></playerstat>
<playerstat><label>Energy</label><initialvalue>0</initialvalue></playerstat>


DeckZones

A deckzone is used to represent a pile of cards you bring to a game. The most common deckzone is the main deck, and many CCGs only have this one deckzone. Deckzones are also commonly used for sideboards, starting cards, adventure decks, and so on. Deckzones are defined in contrast to gamezones, which are areas where cards go during the game. Typically, when a game starts, a deckzone is loaded to a gamezone. When you are editting a deck, you are editting a deckzone. When you are playing a game, you are using gamezones.

<deckzone>
     <label>Deck</label>

     <gamezonetoloadto>Deck</gamezonetoloadto>
     <shuffle>yes</shuffle>
</deckzone>

<deckzone>
     <label>Starting</label>
     <gamezonetoloadto>Starting</gamezonetoloadto>
     <shuffle>no</shuffle>
</deckzone>

The preceding example shows the definition of 2 deckzones. The first is the main deck. The data members for a deckzone are:
A. The name of that deckzone, which will appear in the deck editor.
B. The gamezone that the deckzone gets loaded to when you load a deck. The default is for the deckzone to be loaded to a gamezone of the same name, so if the the corresponding gamezone is the same name, you can omit this.
C. Whether or not the gamezone should be shuffled after it is loaded from a deckzone. The default value is that there will be no implicit shuffle.


GameZones

A gamezone is a pile of cards from which cards are moved to and from during a game. When playing with real cards, you place all cards and all piles of cards on the table top. In Lackey, things work a little differently. The "table zone" in Lackey is intended to be where loose cards (or even small temporary piles of cards) are put, i.e., any cards not in one of the designated piles representing a zone of play. A pile of cards (such as your deck or discard pile) should be implemented as gamezones. Treating a pile as a gamezone allows you to do things like shuffle it, or search it, or use a TRANSFERCARD function (defined later on) on it. (In the example below, the red part is a default value and can be omitted.)

<gamezone>
     <label>Hand</label>
     <visibletoowner>yes</visibletoowner>
     <visibletoothers>no</visibletoothers>
</gamezone>

<gamezone>
     <label>Deck</label>
     <visibletoowner>no</visibletoowner>
     <visibletoothers>no</visibletoothers>
</gamezone>

<gamezone>
     <label>Discard</label>
     <visibletoowner>yes</visibletoowner>
     <visibletoothers>yes</visibletoothers>
</gamezone>

<gamezone>
     <label>Removed</label>
     <visibletoowner>yes</visibletoowner>
     <visibletoothers>yes</visibletoothers>
</gamezone>

<gamezone>
     <label>Starting</label>
     <visibletoowner>yes</visibletoowner>
     <visibletoothers>no</visibletoothers>
</gamezone>

The data members for a gamezone are:
A. The name of the gamezone.
B. Whether or not the gamezone is initially visible to it's owner. The default is for it not to be visible.
C. Whether or not the gamezone is initially visible to players other than it's owner. The default is for it not to be visible.

Take a look at the previous example of a deckzone. The "Deck" deckzone was set to load to the "Deck" zone, and the "Starting" deckzone was set to load to the "Starting" zone. A deckzone and a gamezone that it gets loaded into don't need to have the same name, but they usually do.

Shared zones are special kinds of game zones that are handled differently. Every player gets a copy of every regular game zone. But if a game zone is marked as a shared zone, only one copy of it is in the game, and all players share it.
An example of a game zone you would want to make shared would be the 52 card deck in a game of poker. No one owns it and it is shared among all players, so it should be a shared zone in LackeyCCG.
To turn a regular game zone into a Shared zone, include <isshared>yes</isshared> in that gamezone's definition (somewhere between <gamezone> and </gamezone>).


Phases of the Turn

The phases of the turn are defined with just the name of the phase. If you omit the label, as a default, Lackey will label them Phase 1, Phase 2, and so on.

<phase><label>Ready</label></phase>
<phase><label>Upkeep</label></phase>
<phase><label>Draw</label></phase>
<phase><label>Action</label></phase>
<phase><label>Combat</label></phase>
<phase><label>Discard</label></phase>
<phase><label>End</label></phase>

 


General Functions

General functions are functions that you can use while playing a game, such as drawing a card or flipping a coin. In contrast to Card Functions, explained after this section, General Functions don't require cards to be selected to be performed. A General Function may perform actions on cards (like turning all cards you control), but if a card needs to be selected for a function to be performed, then you will use a Card Function.You can include any number of general functions. Here is an example of what the General Functions section of your plugininfo.txt file might look like:

<generalfunction><label>Ready All</label><kind>ALLYOURCARDSMAKERIGHT0DEGREES</kind><includeasbutton>yes</includeasbutton></generalfunction>
<generalfunction><label>Draw</label><kind>DRAWCARD</kind><includeasbutton>yes</includeasbutton></generalfunction>
<generalfunction><label>Previous Phase</label><kind>PREVIOUSPHASE</kind></generalfunction>
<generalfunction><label>Next Phase</label><kind>NEXTPHASE</kind></generalfunction>
<generalfunction>
     <label>Deplete Deck</label><kind>TRANSFERCARD</kind>
     <sourceowner>performer</sourceowner><sourcegamezone>Deck</sourcegamezone><sourceposition>top</sourceposition>
     <destinationowner>performer</destinationowner><destinationgamezone>Discard</destinationgamezone><destinationposition>top</destinationposition>
</generalfunction>
<generalfunction><label>Roll</label><kind>ROLLD6</kind><includeasbutton>yes</includeasbutton></generalfunction>
<generalfunction><label>Spawn Card</label><kind>SPAWNCARD</kind></generalfunction>
<generalfunction><label>Roll D20</label><kind>ROLLD20</kind></generalfunction>
<generalfunction><label>Spend All</label><kind>ALLYOURCARDSMAKERIGHT90DEGREES</kind></generalfunction>
<generalfunction><label>Previous Turn</label><kind>PEREVIOUSTURN</kind></generalfunction>
<generalfunction><label>Next Turn</label><kind>NEXTTURN</kind></generalfunction>
<generalfunction><label>Flip Coin</label><kind>FLIPCOIN</kind></generalfunction>

The individual syntax for each of these functions is explained below, but what is important to note in the example above is that each is declared between a <generalfunction> and </generalfunction>. All General Functions have a label, which is what they are referred to as in the game. All General Functions must also include a "kind" which tells Lackey what kind of General Function it is. All General Functions can have the entry <includeasbutton>yes</includeasbutton>. That means the function is frequently used and a button for the function will be created for it below the table window. Without that defined, you will need to call the function from the General Function menu above the table (or you can access these functions by right clicking an empty spot on the table). The default value is that the function will not be included as a button, so you could omit it if you want to set it to "no". You could include every General Function as a button below the table, but that might take up a lot of space and clutter the window with infrequently used buttons. Therefore, it is generally a good idea to only include frequently used funtions as buttons below the table.

Below is a complete list of the General Functions you can use, and an example of the syntax. Remember that what is in the syntax column listed here all goes between <generalfunction> and </generalfunction>. Note that the value you define as the label can be anything you want. If you want to call flipping a coin "Press your luck!" instead of "Flip Coin", that's fine. A label can have spaces in it.

General Function Kind Syntax Example Description
DRAWCARD <label>Draw</label><kind>DRAWCARD</kind> This draws a card from the top of the second gamezone to the top of the first gamezone. Those are the default gamezones for the hand and deck, respectively. If you don't use the hand and deck as the first two gamezones, you may need to use TRANSFERCARD instead of DRAWCARD.
DRAWCARDTOTABLE <label>Draw to Table</label><kind>DRAWCARDTOTABLE</kind> This works like DRAWCARD, except instead of the destination being the hand, this will send the card to the table face up. If you want more control, use TRANSFERCARD instead.
FLIPCOIN <label>Flip Coin</label><kind>FLIPCOIN</kind> This flips a coin. The result appears in the chat log.
ROLLD3 <label>Roll D3</label><kind>ROLLD3</kind> Rolls a 3-sided die.
ROLLD4 <label>Roll D4</label><kind>ROLLD4</kind> Rolls a 4-sided die.
ROLLD6 <label>Roll D6</label><kind>ROLLD6</kind> Rolls a 6-sided die.
ROLLD8 <label>Roll D8</label><kind>ROLLD8</kind> Rolls a 8-sided die.
ROLLD10 <label>Roll D10</label><kind>ROLLD10</kind> Rolls a 10-sided die.
ROLLD12 <label>Roll D12</label><kind>ROLLD12</kind> Rolls a 12-sided die.
ROLLD20 <label>Roll D20</label><kind>ROLLD20</kind> Rolls a 20-sided die.
SPAWNCARD <label>Spawn Card</label><kind>SPAWNCARD</kind> This spawns a card to the table.
ALLYOURCARDSMAKERIGHT0DEGREES <label>Ready All</label><kind>ALLYOURCARDSMAKERIGHT0DEGREES</kind> This makes all your cards on the table unturned.
ALLYOURCARDSMAKERIGHT90DEGREES <label>Turn All 90</label><kind>ALLYOURCARDSMAKERIGHT90DEGREES</kind> This makes all your cards on the table turned 90 degrees.
ALLYOURCARDSMAKERIGHT180DEGREES <label>Turn All 180</label><kind>ALLYOURCARDSMAKERIGHT180DEGREES</kind> This makes all your cards on the table turned 180 degrees.
ALLYOURCARDSMAKERIGHT270DEGREES <label>Turn All 270</label><kind>ALLYOURCARDSMAKERIGHT270DEGREES</kind> This makes all your cards on the table turned 270 degrees.
PREVIOUSPHASE <label>Previous Phase</label><kind>PREVIOUSPHASE</kind> This sets the phase of the turn to the previous phase.
NEXTPHASE <label>Next Phase</label><kind>NEXTPHASE</kind> This advances the phase of the turn to the next phase.
PREVIOUSTURN <label>Previous Turn</label><kind>PREVIOUSTURN</kind> This sets the turn to the previous turn.
NEXTTURN <label>Next Turn</label><kind>NEXTTURN</kind> This advances the turn to the next turn.
TRANSFERCARD

<label>Deplete Deck</label><kind>TRANSFERCARD</kind>
<sourceowner>performer</sourceowner>
<sourcegamezone>Deck</sourcegamezone>
<sourceposition>top</sourceposition>

<destinationowner>performer</destinationowner>
<destinationgamezone>Discard</destinationgamezone>
<destinationposition>top</destinationposition>

The above moves the top card of the Deck gamezone of the person who is performing it, to the top of that person's Discard gamezone.

another example:

<label>Play from Deck</label><kind>TRANSFERCARD</kind>
<sourceowner>0</sourceowner>
<sourcegamezone>Deck</sourcegamezone>
<sourceposition>random</sourceposition>
<destinationowner>table</destinationowner>
<destinationposition>faceup</destinationposition>

The second example moves a random card of the person in the first seat to the table face up.

 

The parts in red can be omitted because they define things to be set to default values.

Unlike all of the other General Functions defined so far, TRANSFERCARD uses more data than just a label and kind.

TRANSFERCARD is a general way to move one card from one place to another, whereas DRAWCARD and DRAWCARDTOTABLE were specific cases. You could make a TRANSFERCARD function that did the exact same thing as a DRAWCARD function, but TRANSFERCARD should be used when you need more control.

First, you need to specify the source of the card to be moved. Between <sourceowner> and </sourceowner> you can enter either "performer" or a seat position (starting at seat 0). Between <sourcegamezone> and </sourcegamezone> is where you enter the name of the source gamezone. Between <sourceposition> and </sourceposition> you can enter "top", "bottom", or "random".

Specifying the destination to move the card to is very similar to specifying the source, except the destination can also be the table, in which case you will use different arguments. If the destination of a card is the table, for the destination owner, put "table", and omit the destinationgamezone argument. For a destination of the table, you can specify destinationposition to be "facedown" or "faceup". If you omit destinationposition when transferring a card to the table, faceup will be assumed to be the default argument.

If you omit sourceposition, "top" is the default.


Card Functions

Card Functions are similar to General Functions and they are defined in a similar way. The diference between Card Functions and General Functions is that Card Functions require cards to be selected so thay can be performed. You can either select a card, and perform the Card Function, or you can right click a card and the Card Functions will appear in the menu that pops up. Here is an example of what the Card Functions section of your plugininfo.txt might look like:

<cardfunction><label>Ready</label><kind>MAKERIGHT0DEGREES</kind><includeasbutton>yes</includeasbutton></cardfunction>
<cardfunction><label>Spend</label><kind>MAKERIGHT90DEGREES</kind><includeasbutton>yes</includeasbutton></cardfunction>
<cardfunction><label>Green-1</label><kind>REMOVECOUNTERGREEN</kind><color>green</color><includeasbutton>yes</includeasbutton></cardfunction>
<cardfunction><label>Green+1</label><kind>ADDCOUNTER</kind><color>green</color><includeasbutton>yes</includeasbutton><PositionX>.75</PositionX><PositionY>.04</PositionY></cardfunction>
<cardfunction><label>Red-1</label><kind>REMOVECOUNTER</kind><color>red</color><includeasbutton>yes</includeasbutton></cardfunction>
<cardfunction><label>Red+1</label><kind>ADDCOUNTER</kind><color>red</color><includeasbutton>yes</includeasbutton><PositionX>.5</PositionX><PositionY>.04</PositionY></cardfunction>
<cardfunction><label>Edit Note</label><kind>EDITNOTE</kind><includeasbutton>yes</includeasbutton><PositionX>.4</PositionX><PositionY>.95</PositionY></cardfunction>
<cardfunction><label>Turn Over</label><kind>TURNOVER</kind><includeasbutton>yes</includeasbutton></cardfunction>
<cardfunction><label>Doesn't Turn</label><kind>TOGGLETURNALLIMMUNITY</kind></cardfunction>
<cardfunction><label>Take Control</label><kind>CHANGEOWNER</kind></cardfunction>
<cardfunction><label>Clear</label><kind>CLEARCARD</kind><includeasbutton>yes</includeasbutton></cardfunction>

 

Below is a complete list of the Card Functions you can use, and an example of the syntax. Remember that what is in the syntax column listed here all goes between <cardfunction> and </cardfunction>.

Card Function Kind Syntax Example Description
EDITNOTE <label>Edit Note</label><kind>EDITNOTE</kind>
<PositionX>.4</PositionX><PositionY>.95</PositionY>
The selected card(s) get a note on them you can type in. A card with a note has an "N" drawn on the card to indicate that. The .4 and .95 are normalized x,y coordinates telling Lackey where the N should be displayed over the card. 0,0 would mean at the bottom left corner and 1,1 would mean at the top right corner.
TURNOVER <label>Turn Over</label><kind>TURNOVER</kind> Turn selected card(s) face down.
TOGGLETURNALLIMMUNITY <label>Doesn't Turn</label><kind>TOGGLETURNALLIMMUNITY</kind> Selected card(s) not affected by functions like ALLYOURCARDSMAKERIGHT0DEGREES
CHANGEOWNER <label>Take Control</label><kind>CHANGEOWNER</kind> Take control of selected card(s).
MAKERIGHT0DEGREES <label>Ready</label><kind>MAKERIGHT0DEGREES</kind> Set selected card(s) to being turn 0 degrees.
MAKERIGHT90DEGREES <label>Spend</label><kind>MAKERIGHT90DEGREES</kind> Set selected card(s) to being turn 90 degrees.
MAKERIGHT180DEGREES <label>Turn 180</label><kind>MAKERIGHT180DEGREES</kind> Set selected card(s) to being turn 180 degrees.
MAKERIGHT270DEGREES <label>Turn 270</label><kind>MAKERIGHT270DEGREES</kind> Set selected card(s) to being turn 270 degrees.
ADDCOUNTER

<label>Green+1</label><kind>ADDCOUNTER</kind><color>green</color>
<textoverimagecolor>00FF00</textoverimagecolor>
<PositionX>.75</PositionX><PositionY>.04</PositionY>

Add a counter to selected card(s). The PositionX and PositionY are normalized x,y coordinates telling Lackey where that token's number should be displayed over the card. 0,0 would mean at the bottom left corner and 1,1 would mean at the top right corner. The color can be set to black, white, red, orange, yellow, green, blue, indigo, violet. The default color (if you don't specify one) is red. You can specifcy what color the text is when using text over image card counter style. Enter this number in hex as in the example (which is green). The default textoverimagecolor is black, so you can omit that argument if you're fine with that. Default counter images look good with the default value.
REMOVECOUNTER <label>Red-1</label><kind>REMOVECOUNTER</kind><color>green</color> Remove a counter from selected card(s).
CLEARCARD <label>Clear</label><kind>CLEARCARD</kind> Clear selected cards. Remove status changes like counters or turned status.

 


Other Plugin Definitions

This section handles definitions for things that don't fit into one of the other categories. Below is an example of what these other plugin definitions might look like in your plugininfo.txt.

<definition><kind>ISYOURFACEDOWNVISIBLE</kind></definition>
<definition><kind>ISALLOWINGMULTIPLECARDBACKS</kind>
</definition>

Below is a complete list of the plugin definitions you can use, and an example of the syntax. Remember that what is in the syntax column listed here all goes between <definition> and </definition>.

Other Plugin Definitions Syntax Example Description
REUSECARDIMAGES <kind>REUSECARDIMAGES</kind> If you enable this, all card images will be downloaded to a single location. This option will store all card images in a single folder which you can only use if all card image files are uniquely named. The default is for this to be disabled.
ISYOURFACEDOWNVISIBLE <kind>ISYOURFACEDOWNVISIBLE</kind> If you want face down cards to be visible to their owners on mouseover, you can enable this. It is off by default.
ISSTACKEDCARDSFLAT <kind>ISSTACKEDCARDSFLAT</kind> If you want to have cards on top of other cards all flat (in order to mask the exact count of cards in the stack) you can enable this. It is off by default.
GRIDSIZE <kind>GRIDSIZE</kind><value>.2</value> You can select how big the snap-to grid on the table is. A game like chess might want to match this to exactly 1 per square. The default value is ".03".
TABLEITEMSCALE <kind>TABLEITEMSCALE</kind><value>100</value> This allows you to scale the size of cards on the table. The default value is 100%.
ISALLOWINGMULTIPLECARDBACKS <kind>ISALLOWINGMULTIPLECARDBACKS</kind> If you set this option, you can have 2 image files in the ImageFile column of a card, separated by a comma. The second image file will be used for the card back.
MULTIPLECARDBACKSNAMESVISIBLETO <kind>MULTIPLECARDBACKSNAMESVISIBLETO</kind><value>owner</value> If your plugin has cards with different card back images, you have the option to specify if, when face down, who can see the card names of the cards. Use "none", "owner", or "others" as an argument.
NUMDIGITSINSTAT <kind>NUMDIGITSINSTAT</kind><value>6</value> This specifies how many digits wide you want to have player and global stats displayed. You can choose from 1 to 8 digits wide. The default is 4.

 

Back to the LackeyCCG Tutorial Page