Difference between revisions of "Coding-tutorial"
(→Step One: Defining the Element) |
(update the rest of the guide to tpt++) |
||
Line 1: | Line 1: | ||
− | + | This tutorial will give you guidelines on creating an element in The Powder Toy. We will use the heater (HETR) element in this example, which you can find [https://dl.dropboxusercontent.com/u/43784416/PowderToy/HETR.cpp here]. The color will be the same as the HEAT element, and it will be an indestructible solid in the special menu, that transfers heat quickly. If you have any problems please post a thread on the [https://powdertoy.co.uk/Discussions/Categories/Topics.html?Category=5 forums] | |
− | |||
− | |||
− | This tutorial will give you guidelines on creating an element in The Powder Toy. We will use | ||
− | |||
− | |||
It's not as simple as typing the name, color, and features, but it's almost that easy. | It's not as simple as typing the name, color, and features, but it's almost that easy. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== Part One: Defining the Element's Properties == | == Part One: Defining the Element's Properties == | ||
Line 18: | Line 7: | ||
=== Step One: Defining the Element === | === Step One: Defining the Element === | ||
− | Create a new element file, (HETR.cpp for this example, or whatever name your element will be) inside of src/simulation/elements. | + | Create a new element file, (HETR.cpp for this example, or whatever name your element will be) inside of src/simulation/elements. |
After you put this into the /elements folder, you have to add it to the solution. | After you put this into the /elements folder, you have to add it to the solution. | ||
Line 24: | Line 13: | ||
1. Open up your solution file, then go to the Solution Explorer pane. | 1. Open up your solution file, then go to the Solution Explorer pane. | ||
− | 2 | + | 2. Go to src/simulation/elements/ |
− | |||
− | |||
− | 4. | + | 4. Right click the 'elements' folder |
− | 5. | + | 5. Go to Add -> Existing file |
− | 6. | + | 6. Navigate to src/simulation/elements and double click your element file HETR.cpp |
− | Your new element should now be included in the solution! If you don't do this, you | + | Your new element should now be included in the solution! If you don't do this, you will get errors when you try compiling your new mod. |
− | Open ElementClasses.h in the editor of your choice (Visual Studio for windows users). | + | Open ElementClasses.h in the editor of your choice (Visual Studio for windows users). ElementClasses.h is located under Source Files -> generated in the Solution Explorer. Double click it to open it up. |
− | You will see a file that should have a big list of #define PT_XXXX Y. | + | You will see a file that should have a big list of #define PT_XXXX Y. Scroll down until you reach the end of this list of statements that follow this format. Remember this number. You will need to enter a number greater than this one into the .cpp file you create for your new element. Currently, the largest element ID is VRSG, 176. Your element should have an ID of 177. |
− | You | + | You should not edit ElementClasses.h yourself, this file is generated automatically when generator.py is ran. It uses the "//#TPT-Directive" comments to do this, so make sure you have the element fully written before you run it. For Visual Studio you have to run generator.py manually every time you finish making a new element. The Visual Studio compiling guide should have given a good explanation. If you didn't read that, then here is a short version: |
1. Locate the folder where your source code is located. | 1. Locate the folder where your source code is located. | ||
Line 45: | Line 32: | ||
2. In this directory there should be a file named "generator.py" | 2. In this directory there should be a file named "generator.py" | ||
− | 3. Double click it to run it. A black window should appear for a second or so, then disappear. | + | 3. Double click it to run it. A black window should appear for a second or so, then disappear. This means that it worked. You can check to see if ElementClasses.h was updated to confirm. |
=== Step Two: Defining the Element's Primary Properties === | === Step Two: Defining the Element's Primary Properties === | ||
− | Now, open up your new element file. It | + | Now, open up your new element file. It is empty right now, it is recommended you copy from another element, or this template here: https://dl.dropboxusercontent.com/u/43784416/PowderToy/HETR.cpp . The file is entirely commented, you can just change the properties to how you want. Here are all the properties: |
{| | {| | ||
− | ! Property | + | ! Property || Function |
|- | |- | ||
| '''Identifier'''|| Identifier string, used for lua and internal stuff. Formatted like DEFAULT_PT_XXXX | | '''Identifier'''|| Identifier string, used for lua and internal stuff. Formatted like DEFAULT_PT_XXXX | ||
Line 102: | Line 89: | ||
| '''State'''|| What state is this element? Options are ST_NONE, ST_SOLID, ST_LIQUID, ST_GAS. Powders use solid, energy particles and some other random things use none | | '''State'''|| What state is this element? Options are ST_NONE, ST_SOLID, ST_LIQUID, ST_GAS. Powders use solid, energy particles and some other random things use none | ||
|- | |- | ||
− | | '''Properties'''|| Does this element have special properties? Properties are listed in src/simulation/Element.h, you at least need to have the correct state property. | + | | '''Properties'''|| Does this element have special properties? Properties are listed in src/simulation/Element.h, you at least need to have the correct state property. See below for a list of common properties. |
|- | |- | ||
− | | '''Update'''|| The update function | + | | '''Update'''|| The update function. This is what controls how your element reacts with other elements. See below for info on what to put here. |
|- | |- | ||
− | | '''Graphics'''|| The graphics function, | + | | '''Graphics'''|| The graphics function, This controls any fancy effects. If your element is only one solid color, you don't need this. |
|} | |} | ||
Line 118: | Line 105: | ||
<tt>PROP_DEADLY</tt> makes your element kill stickmen. | <tt>PROP_DEADLY</tt> makes your element kill stickmen. | ||
− | <tt>PROP_HOT_GLOW</tt> makes your element glow when hot, like | + | <tt>PROP_HOT_GLOW</tt> makes your element glow when hot, like METL does. |
<tt>PROP_RADIOACTIVE</tt> makes your element radioactive. | <tt>PROP_RADIOACTIVE</tt> makes your element radioactive. | ||
Line 124: | Line 111: | ||
There are a few more properties, you can find out about them in src/simulation/Elements.h | There are a few more properties, you can find out about them in src/simulation/Elements.h | ||
− | This is a lot to handle, and if you feel overwhelmed by some of the choices, try looking at elements similar to what you are creating and | + | This is a lot to handle, and if you feel overwhelmed by some of the choices, try looking at elements similar to what you are creating and copy the values from those. The following values are an example of what your code is supposed to look like. The color of heater will be the same as the HEAT element, and it will be an indestructible solid in the special menu that transfers heat quickly. |
− | === | + | === Step Three: Defining the Element's State Changes === |
− | + | After all the properties above, you will notice some extra ones named LowPressure, LowPressureTransition, etc. These control all state changes for high/low pressure and temperature. It is very easy to edit these and add in transitions. Lets take GAS as an example. In GAS.cpp, you will find this: | |
− | + | <syntaxhighlight lang="c"> | |
− | + | LowPressure = IPL; | |
− | + | LowPressureTransition = NT; | |
− | + | HighPressure = 6.0f; | |
− | + | HighPressureTransition = PT_OIL; | |
+ | LowTemperature = ITL; | ||
+ | LowTemperatureTransition = NT; | ||
+ | HighTemperature = 573.0f; | ||
+ | HighTemperatureTransition = PT_FIRE; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | This makes it change into OIL at higher than 6.0 pressure, and change into FIRE at higher than 573.0K. Note that all temperatures are in Kelvin, so you have to subtract 273.15 to get the temperature in Celcius. In this case it transitions at 299.85C. | |
− | + | For some transitions, there is one more step. If you want it to transition back, you need to add similar code into the other element. Lets say you wanted OIL to change back into GAS once it goes under 6.0 pressure again. You would need to go into OIL.cpp and change the pressure transitions to this: | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | + | LowPressure = PT_GAS; | |
+ | LowPressureTransition = 6.0f; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
NOTE: For an element that does NOT have a transition at high/low pressure/temp, please follow the same format as the others and use IPL,IPH,ITL,ITH and NT. | NOTE: For an element that does NOT have a transition at high/low pressure/temp, please follow the same format as the others and use IPL,IPH,ITL,ITH and NT. | ||
− | + | HETR is very simple and has no transitions, so everything should be IPL,IPH,ITL,ITH and NT. | |
− | |||
− | |||
− | |||
− | |||
+ | === Step Four: Defining initial values === | ||
− | + | Some elements start off with certain properties by default, for example PHOT gets a .life value of 680. This is done inside of Simulation.cpp. Navigate to src/simulation/Simulation.cpp and find the function create_part. If you scroll down in this function, you will eventually find case statements that look like this: | |
− | |||
− | |||
− | |||
− | |||
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | + | case PT_SOAP: | |
− | + | parts[i].tmp = -1; | |
− | + | parts[i].tmp2 = -1; | |
− | + | break; | |
− | + | case PT_ACID: case PT_CAUS: | |
− | + | parts[i].life = 75; | |
+ | break; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | Adding default values is as simple as making a new case statement. HETR doesn't require any default values, but lets pretend we wanted .tmp to start out as "1". We would add a new statement (anywhere in the list, but near the end might be better) that looks like this: | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | + | case PT_HETR: | |
+ | parts[i].tmp = 1; | ||
+ | break; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | Don't forget the "break;", without it wouldn't error, but your element might get some properties you didn't want it to have. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | === Step Five: Defining the Element's Special Properties === | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | This is the part where we actually code what the element does. The HETR.cpp linked above already has an element function, which looks like this: | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | + | //#TPT-Directive ElementHeader Element_HETR static int update(UPDATE_FUNC_ARGS) | |
− | + | int Element_HETR::update(UPDATE_FUNC_ARGS) | |
− | + | { | |
− | + | int r, rx, ry; | |
− | + | for (rx = -1; rx < 2; rx++) | |
− | + | for (ry = -1; ry < 2; ry++) | |
− | + | if (BOUNDS_CHECK) | |
+ | { | ||
+ | r = pmap[y+ry][x+rx]; | ||
+ | if (!r || (r&0xFF) == PT_HETR) | ||
+ | r = sim->photons[y+ry][x+rx]; | ||
+ | if (!r) | ||
+ | continue; | ||
+ | if (parts[r>>8].temp + (parts[r>>8].temp*0.2f) <= MAX_TEMP) | ||
+ | { | ||
+ | parts[r>>8].temp += parts[r>>8].temp*0.2f; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | parts[r>>8].temp = MAX_TEMP; | ||
+ | } | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | This is a model for what most elements should look like. We can break it down line by line. | |
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | + | //#TPT-Directive ElementHeader Element_HETR static int update(UPDATE_FUNC_ARGS) | |
+ | int Element_HETR::update(UPDATE_FUNC_ARGS) | ||
+ | { | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | The first is the line that is read by generator.py and makes it work. Make sure this line is 100% correct or else your element won't compile. If it is not named HETR, you should change Element_HETR to match your element name. | |
− | + | ||
− | |||
− | |||
− | |||
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | + | int r, rx, ry; | |
− | { | + | for (rx = -1; rx < 2; rx++) |
+ | for (ry = -1; ry < 2; ry++) | ||
+ | if (BOUNDS_CHECK) | ||
+ | { | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | + | These lines start a search around the particle of HETR for things to heat up. It searches the 8 spaces directly surrounding HETR. It also searches the location the HETR itself is in, which is almost always unnecessary. You can fix this by changing the BOUNDS_CHECK line to <tt>if (BOUNDS_CHECK && (rx || ry))</tt>. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | + | r = pmap[y+ry][x+rx]; | |
+ | if (!r || (r&0xFF) == PT_HETR) | ||
+ | r = sim->photons[y+ry][x+rx]; | ||
+ | if (!r) | ||
+ | continue; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | These lines get the particle at location (x+rx, y+ry). It first checks if it exists, and then checks whether it isn't another particle of HETR (we don't want HETR heating up other HETR). If there is no particle in that location, it then checks whether any energy particles are in that location. If there isn't an energy particle either, it stops, continue; in C++ skips the entire for loop above and goes onto the next location. | |
− | + | For more information on pmap, photons, r, and i; go to [[Variables]] | |
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | } else { | + | if (parts[r>>8].temp + (parts[r>>8].temp*0.2f) <= MAX_TEMP) |
− | + | { | |
− | + | parts[r>>8].temp += parts[r>>8].temp*0.2f; | |
+ | } | ||
+ | else | ||
+ | { | ||
+ | parts[r>>8].temp = MAX_TEMP; | ||
+ | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | This is the code unique to HETR, the rest was just a base used by almost every element. The temperature of the particle we found is stored in parts[r>>8].temp. We want to multiply this by 1.2. If it's too close to MAX_TEMP, we just want to increase it to MAX_TEMP instead of doing the multiplication though. This code achieves just that. | |
− | |||
− | |||
− | |||
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | + | } | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
return 0; | return 0; | ||
− | + | } | |
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | + | Not much interesting here, except for the return 0; The function returns an int, so you should always have a return 0; at the end. If your particle gets killed during the update function, you should immediately return 1;. This will let the game know it died, and skip the movement code for it since it's already dead and doesn't need to move. | |
− | + | ||
+ | |||
+ | Fore more complicated element functions, check out the list of useful [[Functions]]. | ||
− | |||
== Part Two: Uploading Your Work to GitHub == | == Part Two: Uploading Your Work to GitHub == | ||
'''(NOTE: GitHub is NOT necessary to just add elements, it is for getting code into the official)''' | '''(NOTE: GitHub is NOT necessary to just add elements, it is for getting code into the official)''' | ||
Line 339: | Line 259: | ||
1) Open SmartGit (make sure you've saved your changes in Visual Studio). | 1) Open SmartGit (make sure you've saved your changes in Visual Studio). | ||
− | 2) | + | 2) Simulation.cpp and any other files you may have changed should be listed as "Modified". |
3) Press "Commit" at the top, list the things you have changed in the text box, and press "Commit". | 3) Press "Commit" at the top, list the things you have changed in the text box, and press "Commit". | ||
4) Press "Push" at the top, and press "Push" again. | 4) Press "Push" at the top, and press "Push" again. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
Revision as of 18:59, 10 April 2014
This tutorial will give you guidelines on creating an element in The Powder Toy. We will use the heater (HETR) element in this example, which you can find here. The color will be the same as the HEAT element, and it will be an indestructible solid in the special menu, that transfers heat quickly. If you have any problems please post a thread on the forums
It's not as simple as typing the name, color, and features, but it's almost that easy.
Part One: Defining the Element's Properties
Step One: Defining the Element
Create a new element file, (HETR.cpp for this example, or whatever name your element will be) inside of src/simulation/elements.
After you put this into the /elements folder, you have to add it to the solution.
1. Open up your solution file, then go to the Solution Explorer pane.
2. Go to src/simulation/elements/
4. Right click the 'elements' folder
5. Go to Add -> Existing file
6. Navigate to src/simulation/elements and double click your element file HETR.cpp
Your new element should now be included in the solution! If you don't do this, you will get errors when you try compiling your new mod.
Open ElementClasses.h in the editor of your choice (Visual Studio for windows users). ElementClasses.h is located under Source Files -> generated in the Solution Explorer. Double click it to open it up. You will see a file that should have a big list of #define PT_XXXX Y. Scroll down until you reach the end of this list of statements that follow this format. Remember this number. You will need to enter a number greater than this one into the .cpp file you create for your new element. Currently, the largest element ID is VRSG, 176. Your element should have an ID of 177.
You should not edit ElementClasses.h yourself, this file is generated automatically when generator.py is ran. It uses the "//#TPT-Directive" comments to do this, so make sure you have the element fully written before you run it. For Visual Studio you have to run generator.py manually every time you finish making a new element. The Visual Studio compiling guide should have given a good explanation. If you didn't read that, then here is a short version:
1. Locate the folder where your source code is located.
2. In this directory there should be a file named "generator.py"
3. Double click it to run it. A black window should appear for a second or so, then disappear. This means that it worked. You can check to see if ElementClasses.h was updated to confirm.
Step Two: Defining the Element's Primary Properties
Now, open up your new element file. It is empty right now, it is recommended you copy from another element, or this template here: https://dl.dropboxusercontent.com/u/43784416/PowderToy/HETR.cpp . The file is entirely commented, you can just change the properties to how you want. Here are all the properties:
Property | Function |
---|---|
Identifier | Identifier string, used for lua and internal stuff. Formatted like DEFAULT_PT_XXXX |
Name | Name, it is recommended to use 4 letters, but less works. 5 or more will probably not fit on the buttons |
Colour | Default color, in hexadecimal (RRGGBB). In the deco editor, it will tell you the color in hex, ignore the initial FF, and use the 6 digits after for this |
MenuVisible | If it's visible in the menu, if 0 then it is hidden and can only be produced with reactions or lua |
MenuSection | The menu section it's in, see src/simulation/SimulationData.h for a list, but you can probably guess their names on your own |
Enabled | If 0, it cannot be created or seen in any way, not even lua. It will just disappear if somehow created. Used for removed elements, you should leave this 1 |
Advection | How much the particle is accelerated by moving air. Normally 0 for solids, and up to 1 for other elements. It can be negative, ANAR and DEST do this so it goes towards pressure |
AirDrag | How much air the particle generates in the direction of travel. Generally is very small, 0.04f creates a lot of positive air (- creates negative pressure). |
AirLoss | How much the particle slows down moving air (although not as big an effect as a wall). 1 = no effect, 0 = maximum effect. Solids are generally above 0.90f, along with most other elements too |
Loss | How much velocity the particle loses each frame. 1 = no loss, .5 = half loss. Solids have it at 0. Only a few have it at 1, like energy particles, and old moving sponge. |
Collision | Velocity is multiplied by this when the particle collides with something. Energy particles have it at -0.99f, everything else is -0.01f or 0.0f. This property does not do much at all. |
Gravity | How fast the particle falls. A negative number means it floats. Generally very small, most gasses are negative, everything else is usually less than 0.04f |
Diffusion | How much the particle "wiggles" around (think GAS or HYGN). Set at 0, except for gasses, which is a positive number. Up to 3 (or higher) for a large amount of wiggle, GAS is 0.75f, HYGN is 3.00f |
HotAir | How much the particle increases the pressure by. Another property only for gasses, but VENT/VACU have theirs at (-)0.010f. An extremely small number, sometimes as small as 0.000001f |
Falldown | How does the particle move? 0 = solid, gas, or energy particle, 1 = powder, 2 = liquid. |
Flammable | Does it burn? 0 = no, higher numbers = higher "burnage". Something like 20 is WOOD, while C-4 is 1000. Some are a few thousand for almost instant burning. |
Explosive | Does it explode? 0 = no, 1 = when touching fire, 2 = when touching fire or when pressure > 2.5. Yes, those are the only options, see FIRE.cpp or somewhere in Simulation.cpp to modify how they work |
Meltable | Does it melt? 1 or higher = yes, 0 = no. This is actually only used when heat sim is off, to make it actually melt use element transitions |
Hardness | How much does acid affect it? 0 = no effect, higher numbers = higher effect. Generally goes up to about 50 |
Weight | Heavier elements sink beneath lighter ones. 1 = Gas. 2 = Light, 98 = Heavy (liquids 0-49, powder 50-99). 100 = Solid. -1 is Neutrons and Photons |
Temperature | What temperature does it have when created? Temperature is in Kelvin (Kelvin = degrees C + 273.15). R_TEMP+273.15f gives room temperature |
HeatConduct | 0 - no heat transfer, 255 - maximum heat transfer speed |
Description | A short one sentence description of the element, shown when you mouse over it in-game |
State | What state is this element? Options are ST_NONE, ST_SOLID, ST_LIQUID, ST_GAS. Powders use solid, energy particles and some other random things use none |
Properties | Does this element have special properties? Properties are listed in src/simulation/Element.h, you at least need to have the correct state property. See below for a list of common properties. |
Update | The update function. This is what controls how your element reacts with other elements. See below for info on what to put here. |
Graphics | The graphics function, This controls any fancy effects. If your element is only one solid color, you don't need this. |
Properties: There are 5 properties for the different states:
TYPE_PART(powders), TYPE_LIQUID, TYPE_SOLID, TYPE_GAS, and TYPE_ENERGY. You should pick one of these to use for your element.
If your element conducts electricity, use PROP_CONDUCTS and PROP_LIFE_DEC.
PROP_DEADLY makes your element kill stickmen.
PROP_HOT_GLOW makes your element glow when hot, like METL does.
PROP_RADIOACTIVE makes your element radioactive.
There are a few more properties, you can find out about them in src/simulation/Elements.h
This is a lot to handle, and if you feel overwhelmed by some of the choices, try looking at elements similar to what you are creating and copy the values from those. The following values are an example of what your code is supposed to look like. The color of heater will be the same as the HEAT element, and it will be an indestructible solid in the special menu that transfers heat quickly.
Step Three: Defining the Element's State Changes
After all the properties above, you will notice some extra ones named LowPressure, LowPressureTransition, etc. These control all state changes for high/low pressure and temperature. It is very easy to edit these and add in transitions. Lets take GAS as an example. In GAS.cpp, you will find this:
LowPressure = IPL;
LowPressureTransition = NT;
HighPressure = 6.0f;
HighPressureTransition = PT_OIL;
LowTemperature = ITL;
LowTemperatureTransition = NT;
HighTemperature = 573.0f;
HighTemperatureTransition = PT_FIRE;
This makes it change into OIL at higher than 6.0 pressure, and change into FIRE at higher than 573.0K. Note that all temperatures are in Kelvin, so you have to subtract 273.15 to get the temperature in Celcius. In this case it transitions at 299.85C.
For some transitions, there is one more step. If you want it to transition back, you need to add similar code into the other element. Lets say you wanted OIL to change back into GAS once it goes under 6.0 pressure again. You would need to go into OIL.cpp and change the pressure transitions to this:
LowPressure = PT_GAS;
LowPressureTransition = 6.0f;
NOTE: For an element that does NOT have a transition at high/low pressure/temp, please follow the same format as the others and use IPL,IPH,ITL,ITH and NT.
HETR is very simple and has no transitions, so everything should be IPL,IPH,ITL,ITH and NT.
Step Four: Defining initial values
Some elements start off with certain properties by default, for example PHOT gets a .life value of 680. This is done inside of Simulation.cpp. Navigate to src/simulation/Simulation.cpp and find the function create_part. If you scroll down in this function, you will eventually find case statements that look like this:
case PT_SOAP:
parts[i].tmp = -1;
parts[i].tmp2 = -1;
break;
case PT_ACID: case PT_CAUS:
parts[i].life = 75;
break;
Adding default values is as simple as making a new case statement. HETR doesn't require any default values, but lets pretend we wanted .tmp to start out as "1". We would add a new statement (anywhere in the list, but near the end might be better) that looks like this:
case PT_HETR:
parts[i].tmp = 1;
break;
Don't forget the "break;", without it wouldn't error, but your element might get some properties you didn't want it to have.
Step Five: Defining the Element's Special Properties
This is the part where we actually code what the element does. The HETR.cpp linked above already has an element function, which looks like this:
//#TPT-Directive ElementHeader Element_HETR static int update(UPDATE_FUNC_ARGS)
int Element_HETR::update(UPDATE_FUNC_ARGS)
{
int r, rx, ry;
for (rx = -1; rx < 2; rx++)
for (ry = -1; ry < 2; ry++)
if (BOUNDS_CHECK)
{
r = pmap[y+ry][x+rx];
if (!r || (r&0xFF) == PT_HETR)
r = sim->photons[y+ry][x+rx];
if (!r)
continue;
if (parts[r>>8].temp + (parts[r>>8].temp*0.2f) <= MAX_TEMP)
{
parts[r>>8].temp += parts[r>>8].temp*0.2f;
}
else
{
parts[r>>8].temp = MAX_TEMP;
}
}
return 0;
}
This is a model for what most elements should look like. We can break it down line by line.
//#TPT-Directive ElementHeader Element_HETR static int update(UPDATE_FUNC_ARGS)
int Element_HETR::update(UPDATE_FUNC_ARGS)
{
The first is the line that is read by generator.py and makes it work. Make sure this line is 100% correct or else your element won't compile. If it is not named HETR, you should change Element_HETR to match your element name.
int r, rx, ry;
for (rx = -1; rx < 2; rx++)
for (ry = -1; ry < 2; ry++)
if (BOUNDS_CHECK)
{
These lines start a search around the particle of HETR for things to heat up. It searches the 8 spaces directly surrounding HETR. It also searches the location the HETR itself is in, which is almost always unnecessary. You can fix this by changing the BOUNDS_CHECK line to if (BOUNDS_CHECK && (rx || ry)).
r = pmap[y+ry][x+rx];
if (!r || (r&0xFF) == PT_HETR)
r = sim->photons[y+ry][x+rx];
if (!r)
continue;
These lines get the particle at location (x+rx, y+ry). It first checks if it exists, and then checks whether it isn't another particle of HETR (we don't want HETR heating up other HETR). If there is no particle in that location, it then checks whether any energy particles are in that location. If there isn't an energy particle either, it stops, continue; in C++ skips the entire for loop above and goes onto the next location.
For more information on pmap, photons, r, and i; go to Variables
if (parts[r>>8].temp + (parts[r>>8].temp*0.2f) <= MAX_TEMP)
{
parts[r>>8].temp += parts[r>>8].temp*0.2f;
}
else
{
parts[r>>8].temp = MAX_TEMP;
}
This is the code unique to HETR, the rest was just a base used by almost every element. The temperature of the particle we found is stored in parts[r>>8].temp. We want to multiply this by 1.2. If it's too close to MAX_TEMP, we just want to increase it to MAX_TEMP instead of doing the multiplication though. This code achieves just that.
}
return 0;
}
Not much interesting here, except for the return 0; The function returns an int, so you should always have a return 0; at the end. If your particle gets killed during the update function, you should immediately return 1;. This will let the game know it died, and skip the movement code for it since it's already dead and doesn't need to move.
Fore more complicated element functions, check out the list of useful Functions.
Part Two: Uploading Your Work to GitHub
(NOTE: GitHub is NOT necessary to just add elements, it is for getting code into the official)
1) Open SmartGit (make sure you've saved your changes in Visual Studio).
2) Simulation.cpp and any other files you may have changed should be listed as "Modified".
3) Press "Commit" at the top, list the things you have changed in the text box, and press "Commit".
4) Press "Push" at the top, and press "Push" again.
Now you are done, if you have any more questions, type them at the discussion part of this page.
Welcome to coding the powder toy!