Click or drag to resize
Edit Plans

Plans can be used to perform very specific tasks within the context of a particular layer in a particular map. When provided with coordinates in the map editor, a plan can even implement rules for a specific location on a layer. That doesn't necessarily mean, however, that a plan can't be used for global purposes. Since a project can have an "overlay" map defined (a map which is always active in the foreground regardless of which map is the primary focus at the moment) plans can be added to this map, and will always be applied as long as the overlay map is active. One kind of plan that might fit well in that context is a plan that increments a global animation counter (that is linked to all animated tiles).

Edit Plans

Two different aspects of plans are edited in two contexts:

  1. The rules defining the actions a plan takes, and under which conditions, are defined in the edit plans window described here.
  2. The data contained by the plan, namely the coordinates that make up a plan's path or rectangle, and the properties associated with the plan and its coordinates are maintained in the map editor.

To open the edit plans window, you can:

  • Right-click on the "Plans" folder within any layer in the project tree and select new to create a new plan.
  • Select the "Plans" folder and choose "New Object" from the File menu or toolbar to create a new plan.
  • Double-click an existing plan in the "Plans" folder to edit an existing plan.
  • Select an existing plan in the "Plans" folder and choose "Properties" from the View menu or "Edit" from the context (right-mouse) menu.
  • Select an existing plan in the map editor and choose "Selected Plan Details" from the map editor's "Edit" menu or toolbar.

There are two levels to understanding the process of editing plans. This page will describe the user interface itself - generally how plans are edited in this window. However, the more interesting detailed aspects of editing plans are in the individual rule functions that a plan can use. For more information about details of the individual rule functions that a plan can use, see:

Coding Reference

The root page of the coding reference summarizes the process of using the individual rule functions. The remainder of the reference contains detailed descriptions of individual functions.

Defining Plans
Name

A plan name must be unique among all plans on the same layer. Names must begin with a letter and contain only letters, digits and spaces.

Priority

In most cases, a plan should not care when it is executed in relation to other plans, so this setting can be ignored. However, if such a case does arise, this value can be set to control the sequence in which plans are processed. Plans with higher numbers will execute after plans with lower numbers.

Rules Toolbar

A toolbar appears above the hierarchical list of rules to manage the creating, deleting and moving of rules in the list. The same commands appear in the "Plan" menu.

  • Add New Rule: Create a new rule with a default name including a uniquely identifying number. The rule is inserted after the currently highlighted rule in the list, or at the end if no rule is highlighted.
  • Delete Rule: Delete the selected rule. Note that only one rule can be deleted at a time, and subordinate rules are not deleted when a parent rule is deleted. If a rule represents a condition, and contains a number of rules inside it, and you delete the condition, then all the rules inside it move up a level and are executed without checking the condition (because the condition has been deleted and is gone). The rule marking the end of the condition, however, will not be deleted and should be updated appropriately if it is no longer to mark the end of a block.
  • Move Rule Up: Swaps the selected rule with the rule above it. Note that this does not skip over nested rules, or move nested rules as a group. If you move the beginning of a condition, the rule preceding the condition will be moved into the condition block rather than after the end of the entire condition block. Likewise, if you move a rule after the end of the condition up, it will move into the condition instead of jumping over the entire block.
  • Move Rule Down: Swaps the selected rule with the rule below it. Note that this does not skip over nested rules, or move nested rules as a group. If you move the beginning of a condition, the first rule nested within the condition will be moved outside the condition block rather than moving the entire condition block down. Likewise, if you move the rule representing the end of the condition down, it will move the following rule into the condition.
  • Copy Rules: Various copy commands will copy all the details of the specified rule or rules so that the rule can be easily transferred, for example, to another plan. The rule can also be pasted to a sprite definition, but since plan rules are not always compatible with sprite rules, some tweaking may be necessary when doing so. The sub-items in this menu allow you to copy the currently highlighted rule including all the rules contained within it (in the tree node), or excluding them, or copy all the rules displayed in the tree.
  • Cut Rules: Various cut commands will cut all the details of the specified rule or rules so that the rules can be easily transferred or deleted. This is the same as Copy Rules, but also deletes the rules from their current location as they are copied to the clipboard. The sub-items in this menu allow you to affect the currently highlighted rule including all the rules contained within it (in the tree node), or excluding them, or affect all the rules displayed in the tree.
  • Paste Rules: Once rules have been copied from a plan or a sprite definition, they can be pasted into a plan using this command. Note that when pasting sprite definition rules into a plan, some tweaking may be necessary to make the rules conform to the features supported by plans. Not all functions available in a sprite definition are available for plans. The sub-items in this menu allow you to paste the copied rules either before or after the selected rule. If no rule is selected, they will be pasted at the end of the list.
  • Toggle Suspend for This and Child Rules: This will toggle the state of the "Suspend this rule" checkbox for the current rule, and set all the child rules' state to be the same. Normally, toggling the checkbox affects only the current rule, but it often doesn't make sense to turn off a parent rule without also turning off all the children, so this toggle can come in handy for disabling (or re-enabling) entire branches of rules.
  • Convert Rules to Function: There are two versions of this command. One will convert all enabled rules in the tree and the other will convert the currently selected rule and all its children. The command to convert all rules is only available from the menu (not available on the toolbar). If you have too many rules to easily manage in the tree view, you can use this command to convert groups of rules into single functions that can be called with a single rule. The converted function will be added to a source code object (or copied to the clipboard if you prefer to look at the code or add it somewhere manually). This action cannot be reversed, so make sure the rules are set up how you would like, and that you do not want to edit the rules in the tree view any more before converting them. Once the rules are converted, they can only be edited as source code in the Code Editor. Another reason to do this is if you need more control over your rules that the rule editor cannot provide. Editing them directly exposes the full power of the C# language. The converted rules will be implemented as a function specifically available to this plan only. You may manually add up to 3 parameters to the converted function (in the code editor, assuming you are familiar with C#) if you would like to be able to create rules that pass different parameter values to this function (you can use functions from PlanBase as an example), but it will still only be accessible to this plan. However, if your rules are not dependent on anything specific to this plan, layer or map, you may move the code or change the code declaration to put the function in the PlanBase class. Then it will be accessible to all Plans.
Rule List

This displays a list of rules associated with the current plan in a hierarchical view. When a rule represents a condition or a loop that affects a number of nested rules, the nested rules are indented under that rule and can be collapsed into it. Note that a condition (a rule of type "If") can also include an "Else" rule, which defines a series of rules to apply when the "If" condition was false. Since the else also depends on the same condition described in the "If" rule, it (and the statements applying to it) is included as a nested rule along with the rest of the rules nested in the condition. That may be difficult for programmers used to writing indented code to get used to because often times code is written with the "Else" being un-indented to the same level as the "If". But when displaying the rules in a hierarchy it truly is part of the same condition, and therefore is nested within the condition. (The code generated by the rules when the project is compiled *is* indented as a programmer would expect, however.)

Rule Name

The name of a rule is used to uniquely identify the rule within the plan. Therefore the name must be unique among all rules within the same plan. A rule name is not constrained by the same limitations as most names because it does ot represent the name of an object that gets converted into source code. The name of a rule simply becomes a comment in the generated code when the project is compiled. The name of a rule can contain any characters that can be typed into a single line. Some good guildelines or considerations for naming rules will help to quickly understand rules when looking at them in the rule list:

  • Use the word "Else" at the beginning of rules of type "Else" so it's easy to tell when statements in a conditional rule apply to the false case of the condition.
  • Use the word "And" at the beginning of rules of type "And" so its easy to distinguish components of the initial condition from rules that apply within the condition.
  • Use the word "Or" at the beginning of rules of type "Or" so its easy to distinguish components of the initial condition from rules that apply within the condition.
  • Prepend a "* " to the names of rules that have been suspended so its easy to find rules that are not active but could easily be turned on.
  • Include details about the context of a rule in its name so that it won't collide with the names of other rules performing similar things in a different context. For example, instead of naming a rule "Teleport", name it "Teleport player 1" if you will be handling teleportation of multiple players within the same rule.
  • Keep in mind, the more details that are included in the rule names, the more information will be available when reading the rule list. But also keep in mind that there is no word wrapping in the rule list, so space is limited.

Of course you are free to devise your own guidelines as well, but these guidelines are used in the included samples and following them will make your rules consistent with any imported samples.

Suspend this rule

This will exclude the rule from being included in the generated project. It will be treated as if it does not exist when compiling and running the project. One reason to do this is to easily turn on and turn off debugging rules. There may be a rule to give the player some object or teleport the player to a certain location to make testing easier. Of course such a rule should be turned off (suspended) when compiling the final project. Another reason to do this may be when creating rules to serve as a template that might be used in other projects. If there is a rule that specifically applies to supporting the use of ladders, but the project doesn't use ladders, the rule can be suspended and then only turned on when using the template to create a project that implements ladders.

Note: It is strongly recommended when suspending a rule that contains nested rules, all the nested rules also be suspended. Unexpected behavior may occur if a rule is suspended without suspending all of the rules nested within it. See the "Toggle Suspend for This and Child Rules" command above.

Rule Type

There are 8 fundamental classes of rules that can be defined using the first dropdown list. If the descriptions of these types seem overwhelming or confusing, skip them for now and just try out some examples (look at some existing sample rules in other projects). These should be relatively self explanatory, but you can refer to these descriptions for detailed information about how they behave and why they exist. Before proceeding, let's establish some terminology. A "Rule Type" is one of these 8 types selected in the first dropdown list. And the term "Rule Function" (described in more detail below) will be used to refer to a specific function selected in the second dropdown list.

DoThis simplest of rule types indicates that some action will be performed rather than defining a condition or loop. Note that rule functions that are normally associated with "If" type rules can also be used with "Do", and any action that they perform will be executed, but the result will be ignored instead of used to define a condition.
IfThis defines the beginning of a condition. Rules that come after an "If" rule will be nested within it until one of the rules uses the "End If" checkbox to end the condition. The set of rule functions available with an "If" type rule is limited. Only functions that return a true or false value can be used with "If". (In the source code, the function must return "bool".) When the rule returns success/true, the conditions nested in the "If" conditions will also apply, otherwise they are skipped. (There are exceptions, see "Else" below.)
AndThis rule type can only be used immediately after an "If", "ElseIf", "While", "And" or "Or" type rule, to extend the condition. The rules contained inside the condition will only be applied if all the rules combined with "And" return success/true. The same list of rule functions will be available for this rule type as are available for the "If" rule type.
OrThis rule type can only be used immediately after an "If", "ElseIf", "While", "And" or "Or" type rule, to extend the condition. The rules contained inside the condition will be applied if any one of the rules combined with "Or" return success/true. The same list of rule functions will be available for this rule type as are available for the "If" rule type.
ElseIfThis rule type can only be used within a block of rules started by "If" or another "ElseIf". It begins a new condition block nested yet another level below that of the current rule. The condition is only checked when the initial condition failed (returned false), and the statements nested under this rule are only applied if the initial condition failed and the condition specified in this rule succeeds (returns true). Because the statements are nested another level, you must remember to include at least two End If rules, one to finish the nested condition and one to finish the initial condition. If there are rules between the end of the inner condition and the end of the outer condition, they will be executed when the outer condition's expression is false regardless of the result of the inner condition.
ElseThis rule type can only be used within a block of rules started by an "If". It causes the rules within the block after this one to be applied only if the condition specified with "If" failed. This is actually more like an "Else Do" than a plain "Else" because it also includes the ability to perform a function within the same rule.
EndNormally when you create a rule, in order to make it the last rule in a nested block of statements (the last rule that depends on an "If" condition, for example) you can check the "End If/End While" box. However, there is no way to indicate that a statement should be the last statement of two nested conditions (for example, the end of an "If" block as well as another "If" block containing that). That's the purpose of the "End" rule type. It's the only rule type that doesn't perfom any action in itself (there's no rule function associated with it). It just ends a block of nested statements that was started by an "If", "ElseIf" or "While".
WhileThis begins a block of statements that will execute repeatedly ("loop") as long as a rule function returns success/true. This can be used in conjunction with "And" and "Or" rule types to form complex conditions that must be met to continue the loop. The same list of rule functions will be available for this rule type as are available for the "If" rule type. It cannot be used in conjunction with ElseIf or Else rules. In other words, you can nest a "While" inside and "If" or an "ElseIf" block, and you can nest an "Else" or "ElseIf" rule inside an "If" block contained within a "While", but you cannot directly include an "Else" or "ElseIf" rule within a "While" block. Be careful with this rule type because it could easily result in endless loops that will make the game freeze if used incorrectly. It can also make the game run slowly.
Not

This checkbox can be used with the "If", "ElseIf", "While", "And" or "Or" rule type to invert the result of the rule. For example, you can check the "Not" box on a rule that reads "If - IsInputPressed" and then the rules contained in this block will only apply when the specified key is not pressed.

Rule Function

The second dropdown list on this form represents the rule function associated with the rule. Here you can select one of the many functions available to define plan behavior, including functions defined yourself by editing files in the "Source Code" folder of the project. For more details about defining your own rule functions, see the coding reference. A number of pre-defined functions exist to perform simple comparisons, calculations and copying of values:

-Subtract the "left operand" in the second parameter from the "right operand" in the first parameter and put the result in the variable provided in "Output to".
!=Compare the values of the first two parameters and return true/success if they are different, or false/failure if they are equal.
+Compute the sum of the first two parameters and output the result to the variable provided in "Output to"
<Compare the values of the first two parameters and return true/success if "left operand" is less than "right operand", or false/failure otherwise.
<=Compare the values of the first two parameters and return true/success if "left operand" is less than or equal to "right operand", or false/failure otherwise.
=Copy the value provided in the first parameter to the variable provided in "Output to"
==Compare the values of the first two parameters and return true/success if they are equal, or false/failure if they are different.
>Compare the values of the first two parameters and return true/success if "left operand" is greater than "right operand", or false/failure otherwise.
>=Compare the values of the first two parameters and return true/success if "left operand" is greater than or equal to "right operand", or false/failure otherwise.

When defining an "If", "While", "And", "Or", "ElseIf", or "While" type rule, the list of functions displays only rules that return a true or false value (sometimes thought of as success or failure). These rule functions are referred to as "boolean" functions. When defining a "Do" type rule, all rule functions are available for use, and if a boolean function is used, the function will perform its usual work (if any) but the result will simply be ignored. This might be useful because some functions actually do something that affects the game and then return a value indicating some true or false value.

After selecting a function, some or all of the parameter fields below will open up for input. Each function has its own set of parameters, and depending on how many parameters it uses and what types of parameters they are, the boxes below will become available and present different options in the dropdown lists. The box immediately below the rule function box will also display a brief description of what the function is and how to use it. Furthermore, if the function can output a number, the "Output to" box will open up and allow you to select a counter, plan parameter or sprite parameter in which to store the result.

If there is an error compiling the project or processing the function name (it's possible to type an arbitrary name into the function field in case you want to call an undocumented function) then the description field will contain a generic error message and all the parameters will be available for input, but without names. This is to allow a function to be specified even if the environment doesn't know that it's valid.

Function Description

After a function is selected, a brief description of the function is displayed in the box below. Don't forget that this box can scroll and there may be more information than is initially displayed. Usually a description will also include information about the meaning of the parameters and output value if any.

Function Parameters

Many rule functions can accept parameters that specify details about how they should operate or what they should affect. In most cases a helpful list of suggested values is provided in the dropdown list for each parameter based on the type of the parameter, but any value can be manually typed because not all possible values can be predicted. For example if you want to call a function to display a message, you obviously won't be able to select the message from the dropdown list, you'll have to type it in. That brings up another important topic. When providing text for a parameter (also known as a "string") you must enclose the text in quotes. This (indirectly) allows you to include special formatting characters in the text. These are inserted with "escape codes". Here are the most important escape codes with which you should be familiar when entering a string into a parameter value:

CodeResultExample parameterExample result
\r\nInserts a line break"Display me on\r\nTwo Lines"Display me on

Two Lines

\"Embeds a double-quote in the text"He said his name was \"Little John\""He said his name was "Little John"

Many other parameter types are available when defining rules for plans. Below is a list, but it is by no means comprehensive because the list is customizable. It can be expanded by adding your own enumerations in the game project's source code folder:

Type Name / SummaryDescription/SourceExample
KeypressPreset list of static values, each value representing a key on the keyboardKey.A
Color ChannelPreset list of color channels that can be affected (Red, Green, Blue or Alpha).PlanBase.ColorChannel.Blue
Relative PositionPreset list of pre-defined corner or centered positions within a rectangle.RelativePosition.BottomCenter
SpriteCan refer to any sprite instance. The dropdown list will contain a list of sprites on the plan's layer.m_ParentLayer.m_Platform_1
Sprite of type <X>Some custom rules added for a specific project may refer to a specific type of sprite. In this case, the dropdown list will only display sprite instances for a particular sprite definition.m_ParentLayer.m_Platform_1
Sprite CollectionDisplays a list of sprite categories defined in the project.ParentLayer.m_SpriteCategories.Enemies
PointDisplays a list of the first coordinates of each plan in the layer; only plans with exactly 1 coordinate are listed. A point representing the mouse position is also listed.m_ParentLayer.m_Door_1[0]
PlanDisplays a list of all the plans on the same map.m_ParentLayer.m_Door_1
CounterDisplays a list of counters in the project.Counter.Lives
Bar drawing styleDisplays a preset list of ways that a bar can be drawn.PlanBase.DrawStyle.RepeatRightToCounter
ColorDisplays a preset list of colors.System.Drawing.KnownColor.Crimson
Sprite InputBitsDisplays a preset list of inputs that can affect a sprite.SpriteBase.InputBits.Button1
MapDisplays a list of maps defined in the project. (They are referred to by type instead of specific map instances because it's conceivable that you could have multiple copies of the same map loaded.)typeof(Level_1_Map)
Sprite DefinitionDisplays a list of Sprite Definitions. This differs from the other sprite parameter types because they require a specific sprite instance on the layer whereas this lists Sprite Definitions which are independent of the maps.typeof(Sprites.Explosion)
Sprite StateDisplays a list of all states in a particular sprite (if no previously specified parameters have specified a sprite, this won't display a list).(int)Sprites.Player.State.Left
IntegerDisplays a list of all counters, all parameters of any sprite that has been specified in another parameter, and miscellaneous other shared integer variables (CurrentView, for example, represents the currently active view number in projects where there are multiple views, and is included in this list). Some rules may want to alter a parameter value that is passed in (receive the parameter "by reference" so it can be changed). In these cases the values in the list are preceded by "ref" indicating that the variable that is provided may have a different value afterwards (failing to pass a variable by reference where a reference is required will result in an error.) Counters cannot be provided to a parameter requiring a reference to an integer, but another version of the rule function may be available that accepts a counter, or the value can subsequently be copied into the counter with an "=" rule.Counter.Lives.CurrentValue
TilesetDisplays a list of Tilesets defined within the project.Tileset.FireText
Output to

Some functions output integer values. For those that do, this field is enabled to allow you to specify where to put the result. If you don't need to put it any place permanent, but just want to use it in a subsequent rule (if nothing else interferes) you can use a temporary variable that is provided by default named SharedTemp1. If necessary, you can add more such shared variables by adding them after "SharedTemp1" in PlanBase.cs in the SourceCode folder. Variables declared with "static" are shared among all plans while variables declared without "static" are specific to the current plan and can be set with a particular initial value in the map editor. Any counter value and many other values listed after "Integer" type parameters above are also available.

Whereas parameters are all required, the "Output to" box can be left blank if you don't care about storing or using the result of a rule function.

End If / End While

If you want to mark this rule as the last rule in a block that was started with an "If", "ElseIf", or "While" type rule, check this box. Note that if you need to end two (or more) blocks at once, you will need to also add an "End" type rule after this. The "End" type rule will allow you to add another rule that has no function or parameters, and just checks the "End If / End While" box.

Take care to match every "If", "ElseIf" and "While" with one and only one matching rule that has the "End If / End While" box checked. The code generator will automatically close the remainder of your blocks if you have some unfinished blocks at the end of your plan, but other failures to match the beginnings of blocks with an end could result in unwanted behavior. One occasion when this can be particularly tricky is when deleting a rule that begins or ends a block. Be careful to find the corresponding rule at the other end of the block and delete or adjust it appropriately too.