C2G: Difference between revisions

11,179 bytes added ,  10 October
Mention of tools > 127 and better example of level ktools
(Mention of tools > 127 and better example of level ktools)
 
(27 intermediate revisions by 4 users not shown)
Line 3: Line 3:
While individual levels are stored in [[C2M]] files, C2G files arrange these levels in [[levelset]]s. C2G files can also be used to specify music tracks, text between levels, and several forms of advanced scripting.
While individual levels are stored in [[C2M]] files, C2G files arrange these levels in [[levelset]]s. C2G files can also be used to specify music tracks, text between levels, and several forms of advanced scripting.


The official set does not use any advanced C2G features, nor did [[Chuck Sommerville]] provide any documentation; there are several features that have not yet been discovered by the community.
The official set does not use any advanced C2G features, nor did [[Chuck Sommerville]] provide any documentation; there may be features still undiscovered by the community.


== Basic usage ==
== Basic usage ==
Line 62: Line 62:
== Advanced scripting ==
== Advanced scripting ==
In addition to the features described above, C2G files can support some additional keywords that provide extra features. '''Note that any information beyond this point may be incomplete or inaccurate.'''
In addition to the features described above, C2G files can support some additional keywords that provide extra features. '''Note that any information beyond this point may be incomplete or inaccurate.'''
=== Syntax ===
The syntax of the .c2m file appears to be a mix of [https://en.wikipedia.org/wiki/Reverse_Polish_notation Reverse Polish Notation] expressions and simple statements.  For example, to set the global "flags" variable to (reg1 + 42) * 3, you would write:
  reg1 42 + 3 * flags =
Other statements, such as "map" or "music" take a parameter after the keyword:
  map "somemap.c2m"
In addition, variables can be formatted into strings in script sections by placing the variable after a string with a printf-style format specifier:
  "flags = %ld" flags
If a variable name is invalid, CC2 will search the substrings of the variable name to find a variable name:
  10 highspeed = ; Same as 10 speed =
=== Variables ===
In most cases, the way C2G scripts interact with gameplay is by writing values to variables.
C2G scrips have access to quite a few variables (see Reference), and some of them are for C2G scripters to use for custom data (reg1 through 4).
All variables are signed 32-bit integers.


=== Score ===
=== Score ===
Line 114: Line 135:
  2564 tools =
  2564 tools =


Note that tool codes > 16 will be reduced to a value <= 16, and key counts > 9 will be reduced to 9. These limits do not apply when either inventory is carried over from the previous level.
Note that tool codes between 17 and 127 will be reduced to a value <= 16. Codes from 128 to 257 produce [[negative items | strange results]]. Key counts > 9 will be reduced to 9.


=== Timed levelset ===
=== Timed levelset ===
Line 122: Line 143:
  <nowiki><#> tleft =</nowiki>
  <nowiki><#> tleft =</nowiki>
Replace "<#>" with the desired time limit for the set. This will ignore any time limits set for individual levels. Time limits will be carried over from one level to the next, and restarting the level does not reset the time limit. [[Time bonus]]es and [[time penalty|time penalties]] can still be used. After the time limit reaches 0, or if a level is skipped, all future levels will be untimed.
Replace "<#>" with the desired time limit for the set. This will ignore any time limits set for individual levels. Time limits will be carried over from one level to the next, and restarting the level does not reset the time limit. [[Time bonus]]es and [[time penalty|time penalties]] can still be used. After the time limit reaches 0, or if a level is skipped, all future levels will be untimed.
=== Conditional execution ===
By default, all of the lines in a C2G script are executed, with the only condition of not being invalid. "do" statements can allow for directives to be executed under conditions.
To do this, the directive which is supposed to be conditioned should be prefixed with:
  <nowiki> <condition> do </nowiki>
Replace <condition> with the expression which should be checked for being true.
  <nowiki>100000 score > do 13 tools =</nowiki>
The above example will give the player a secret eye going into the next level if their overall score is greater than 100000.
=== Goto ===
By default, C2G files are read linearly from top to bottom, but "goto" directives can allow level skipping or looping.
In order to do this, the end point of the jump must be given a label starting with a pound (#) character. For example:
<nowiki>#loop
map "DejaVu.c2m"
map "StuckInALoop.c2m"</nowiki>
In the example above, the levels DejaVu.c2m and StuckInALoop.c2m are given the label "loop".
<nowiki>map "NormalProgression.c2m"
#loop
map "DejaVu.c2m"
map "StuckInALoop.c2m"
goto #loop</nowiki>
In the example above, completing StuckInALoop.c2m will always take you back by one level to DejaVu.c2m.
"goto" directives can be combined with "do" directives, for example:
<nowiki>map ManyKeys.c2m
keys 67306285 != do goto #normalPath
script
"you have found"
"the secret key"
"combination!"
"you should rest"
"a bit"
map RelaxingBeach.c2m
#normalPath
map ManyTools.c2m</nowiki>
In the above example, if after playing ManyKeys.c2m, the last exited player has exactly 1 red, 2 blue, 3 yelow and 4 green keys, they see the text message and play RelaxingBeach.c2m. After that, the secret and normal paths join and in both cases ManyTools.c2m is played next.
=== Entry choices ===
If a level has several [[Player character]]s, C2G scripting can be used to force only one player to appear, and set which player appears based on conditions.
Players are numbered in reading order, starting at 1; there does not appear to be any limit. In order to use the feature, before calling the "map" of the level containing the players, the "enter" variable must be set, for example:
<nowiki><#> enter =</nowiki>
Replace <#> with an expression (which must evaluate to a number) or a number. For example:
<nowiki>1 enter =
0 rand > do 2 enter =
map UltimatePain.c2m</nowiki>
In the above example, with about 50% chance, the second player will appear in the level UltimatePain.c2m instead of the first one.
CC2 crashes if "enter" is set to a value which does not lead to a player. Make sure to reset enter to 0 where necessary!


=== Exit choices ===
=== Exit choices ===
If a level has several [[exit]]s, C2G scripting can be used to send the player to different levels depending on what exit is entered.
If a level has several [[exit]]s, C2G scripting can be used to send the player to different levels depending on what exit is entered.


In order to do this, each level must be given a label starting with a pound (#) character. For example:
Exits are numbered in reading order, starting at 1; there does not appear to be any limit. In order to use the feature, after calling the "map" of the level containing the exits, "do" and "goto" need to be combined in a similar manner:
<nowiki>#bonuslevel
script
"Congratulations!"
"You have reached"
"the secret level!"
map "BonusLevel.c2m"</nowiki>
In the example above, the level BonusLevel.c2m as well as the preceding text are given the label "bonuslevel".
 
Exits are numbered in reading order, starting at 1; there does not appear to be any limit. In order to use the feature, after calling the "map" of the level containing the exits, a line similar to this will be required:
  <nowiki> <#> exit == do goto #label</nowiki>
  <nowiki> <#> exit == do goto #label</nowiki>
Replace <#> with the exit number, and #label with the label name (including the #). For example:
Replace <#> with the exit number, and #label with the label name (including the #). For example:
Line 148: Line 218:
script
script
"This is the end."</nowiki>
"This is the end."</nowiki>
In the example above, the game will load the level stored in the file ChooseYourFuture.c2m; if the player exits using the first exit in reading order, the game will then display the THIS IS THE END. message. If the player exits using the second exit, however, the game will load the level in the file SuperSecretFinalLevel.c2m instead, and the THIS IS THE END message will be displayed after the level has been solved.
In the example above, the game will load the level stored in the file ChooseYourFuture.c2m; if the player exits using the first exit in reading order, the game will then display the THIS IS THE END message. If the player exits using the second exit, however, the game will load the level in the file SuperSecretFinalLevel.c2m instead, and the THIS IS THE END message will be displayed after the level has been solved.


If there are several players in the level, the exit used by the last player to finish the level will be the one used by the C2G script. If an invalid label is called, or no label is assigned for the exit that was used, the game will continue to work through the C2G file as it would normally.
If there are several players in the level, the exit used by the last player to finish the level will be the one used by the C2G script. If an invalid label is called, or no label is assigned for the exit that was used, the game will continue to work through the C2G file as it would normally.
Line 161: Line 231:


If there are several players in the level, the gender of the last one to finish the level will be the one used by the C2G script. If an invalid label is called, or no line is specified for a specific gender, the game will continue to work through the C2G file as it would normally.
If there are several players in the level, the gender of the last one to finish the level will be the one used by the C2G script. If an invalid label is called, or no line is specified for a specific gender, the game will continue to work through the C2G file as it would normally.
=== Goto ===
Goto can also be used in absence of a gender or exit check. For example:
<nowiki>map "NormalProgression.c2m"
#loop
map "DejaVu.c2m"
map "StuckInALoop.c2m"
goto #loop</nowiki>
In the example above, completing StuckInALoop.c2m will always take you back by one level to DejaVu.c2m.


=== Fake level numbers ===
=== Fake level numbers ===
Line 186: Line 247:
map "Normal.c2m"</nowiki>
map "Normal.c2m"</nowiki>
In the example above, Normal.c2m will be level 9.
In the example above, Normal.c2m will be level 9.
No matter how your level numbering is set up, completing a level will always briefly display the current level as being its previous value + 1. This is unavoidable.


=== Speed ===
=== Speed ===
Line 209: Line 272:
The following lines  
The following lines  
  <nowiki>1 level =
  <nowiki>1 level =
50 highspeed = continue replay | silent | flags =</nowiki>
50 speed = continue replay | silent | flags =</nowiki>
added to the beginning of the file (after the set name) will cause the game to automatically replay the recorded solutions for all levels in the set, in extremely high speed. This can be used to quickly verify that all levels are solvable and have recorded replays.
added to the beginning of the file (after the set name) will cause the game to automatically replay the recorded solutions for all levels in the set, in extremely high speed. This can be used to quickly verify that all levels are solvable and have recorded replays.
=== Chaining ===
Scripts can be "chained" using the chain directive; immediately stopping the parsing of the current script and starting again on the first line of the chained script. This can be useful for compartmentalizing long scripts associated with particular levels.
<nowiki>chain "anotherscript.c2g"</nowiki>
<nowiki>chdir "anotherdirectory\"
chain "scriptinanotherdirectory.c2g"</nowiki>
Note that if the first c2g file CC2 reads chains to another script but does not provide a map itself, CC2 will say the levelset is invalid. This is because it specifically checks the first c2g it reads for the use of "map" followed by a valid map. To avoid this, put a valid map ''after'' calling the chain, such that it will never be accessed since the parser will be chained away from the script before reaching it.
=== Level flags ===
Variables reg1 to reg4 can be used to store arbitrary flags, will be stored between chained scripts, and will be included in the player's save data. Here, a "switch palace" level includes two exits, the second of which sets the lowest bit in reg4 to 1, which the script then detects to swap out a later level for an alternate version:
<nowiki>map "SwitchPalace.c2m"
1 exit == do goto #afterpalace
script
"You touched the switch!"
"This will swap some"
"walls and floors in"
"a future level"
1 reg4 | reg4 =
#afterpalace
map "BoringLevel.c2m"
map "NormalLevel.c2m"
map "GreatLevel.c2m"
1 reg4 && do goto #switchon
#switchoff
map "AwesomeLevel.c2m"
goto #afterawesome
#switchon
map "AwesomeLevelAlt.c2m"
#afterawesome
map "OkayLevel.c2m"</nowiki>
Unused bits of the "flags" variable itself are also available, but flipping them is unadvised, as, theoretically, future updates to CC2 could add new purposes to unused flags at any moment.


== Comments box ==
== Comments box ==
Certain C2G scripts, notably ktools and speed can be placed inside a [[C2M|specific level file]]'s comments field, and will apply to the level itself. To do this, the comments field must contain the following line:
Certain C2G scripts, notably ktools and speed can be placed inside a [[C2M|specific level file]]'s comments field, and will apply to the level itself. To do this, the comments field must contain the following line:
  <nowiki>[COM]</nowiki>
  <nowiki>[COM]</nowiki>
followed, on subsequent lines, by the C2G parameters.
followed, on subsequent lines, by the C2G parameters. For example, this will cause all players to start the level with fire boots and flippers.
<nowiki>
[COM]
flags ktools | flags = 1027 tools =</nowiki>
 
== Reference ==
The following is a list of all keywords and tokens recognized by the c2g parser.  The function of some keywords in here is unknown, and some formerly did something but are now just gibberish to the engine (NO_L_DOORS for example).  Note that keywords are case-insensitive.


== Complete set of keywords ==
{| class="wikitable"
On September 19th, 2019, [[Joshua Bone]] posted a complete list of keywords that can be C2G scripting, including numbers and comparison operators. The function of some keywords in here is unknown, and some are just gibberish (NO_L_DOORS for example).
! Token
<nowiki>MUSIC
! Type
GOTO
! Syntax
DO
! Description
==
|-
<=
| MUSIC
>=
| directive
!=
| <pre>music "&lt;filename&gt;"</pre>
=
| Specifies a music file to play for the next script element.
<
|-
>
| GOTO
LEVEL
| directive
GENDER
| <pre>goto #&lt;label&gt;</pre>
EXIT
| Move script execution to the specified #label
ENTER
|-
SCORE
| DO
BONUS
| directive
MENU
| <pre>&lt;conditional&gt; do ...</pre>
CHIPS
| If the preceding condition is true, do the following command.  Example:
START
  <pre>2 exit == do goto #secret</pre>
MALE
|-
FEMALE
| ==<br />&lt;=<br />&gt;=<br />!=<br />&lt;<br />&gt;<br/>&&<br/>&#124;&#124;<br/>+<br/>-<br/>*<br/>/<br/>%<br/>&<br/>&#124;<br/>^
MAP
| binary operator
SCRIPT
| <pre>&lt;expressions...&gt; &lt;operator&gt;</pre>
"
| Pop two values from the preceding expressions and compare them with the specified operator, then push the result.  The operators have the same meanings as in C.
#
|-
0
| =
1
| assignment
2
| <pre>&lt;expression&gt; &lt;variable&gt; =</pre>
3
| Assign the specified value from the preceding expression to &lt;variable&gt;.
4
|-
5
| LEVEL
6
| variable
7
| <pre>level</pre>
8
| Contains the current level number.  The first level is 1.
9
|-
;
| GENDER
//
| variable
END
| <pre>gender</pre>
RESULT
| Contains the player's current gender (male or female).
REG1
|-
REG2
| EXIT
REG3
| variable
REG4
| <pre>exit</pre>
FLAGS
| Contains the most recently used exit (see above).
EDIT
|-
CHAIN
| ENTER
LINE
| variable
CHDIR
| <pre>enter</pre>
SCREEN
| Contains the used playable in the next level (see above).
*
|-
/
| SCORE
+
| variable
-
| <pre>score</pre>
&&
| Contains the current score for the levelset.
&
|-
||
| BONUS
| unknown
|
| Appears to be unused.
|-
| MENU
| variable
| <pre>menu</pre>
| Use is currently unknown.
|-
| CHIPS
| unknown
|
| Appears to be unused.
|-
| START
| unknown
|
| Appears to be unused.
|-
| MALE
| constant
| <pre>male</pre>
| Value: 0x16<br />"male" constant for gender variable.
|-
| FEMALE
| constant
| <pre>female</pre>
| Value: 0x56<br />"female" constant for gender variable.
|-
| MAP
| directive
| <pre>map "&lt;filename&gt;"</pre>
| Specifies the map file to use for the next level.
|-
| SCRIPT
| directive
| <pre>script</pre>
| Begins "script" mode for displaying text (see above).
|-
| "
| string
| <pre>"..."
"... %&lt;format&gt; ..." &lt;value&gt;</pre>
| Strings begin and end with a double-quote (").  There does not appear to be any capability for escaping characters.  However, formatting can be applied with printf-style format strings (see above).
|-
| #
| label
| <pre>#&lt;name&gt;</pre>
| Labels can be jumped to with the "goto" directive.  There appears to be some interaction with the '''end''' directive, but this is untested.
|-
| 0..9
| integer
| <pre>1234</pre>
| Integer literal.  Can only be specified in decimal (digits 0-9).
|-
| ;<br/>//
| comment
| <pre>; comment text
// comment text</pre>
| Comments are ignored until the end of the current line.
|-
| END
| directive
| <pre>end</pre>
| There appears to be some interaction with labels, but this is untested.
|-
| RESULT
| variable
| <pre>result</pre>
| Use is currently unknown.  Possibly contains the result of arithmetic expressions?
|-
| REG1<br />REG2<br />REG3<br />REG4
| variable
| <pre>reg1
reg2
reg3
reg4</pre>
| Variables intended for use for complex operations in scripts.
|-
| FLAGS
| variable
| <pre>flags</pre>
| Specifies flags (bitwise OR'ed) for the current gameplay.  See sections above for details.
|-
| EDIT
| directive
| <pre>edit</pre>
| Start the built-in level editor.
|-
| CHAIN
| directive
| <pre>chain "&lt;filename&gt;"</pre>
| Stops the current script and starts the one specified in &lt;filename&gt;.
|-
| LINE
| variable
| <pre>line</pre>
| The currently processed line in the current C2G script.
|-
| CHDIR
| directive
| <pre>chdir "&lt;path&gt;"</pre>
| Change the game's current working directory to &lt;path&gt;.
|-
| SCREEN
| unknown
|
| Appears to be unused.
|-
| *<br />/<br />+<br />-<br />&amp;&amp;<br />&amp;<br />&#124;&#124;<br />&#124;<br />%<br />^
| binary operator
| <pre>&lt;expressions...&gt; &lt;operator&gt;</pre>
| Pop two values from the preceding expressions and evaluate them with the specified operator, then push the result.  The operators have the same meanings as in C.
|-
| REPLAY
| constant
| <pre>replay</pre>
| Value: 0x2<br />When set in flags, automatically replay recorded solutions.
|-
| CONTINUE
| constant
| <pre>continue</pre>
| Value: 0x1<br />When set in flags, automatically continue to the next level. '''This only works if 0x2 (replay) is also set and the replays make it to the exit''', otherwise exiting a level will do nothing and you will not be able to continue to the next level. This also skips text interludes from the "script" directive.
|-
| SILENT
| constant
| <pre>silent</pre>
| Value: 0x4<br />When set in flags, suppresses popup dialogs like the score improvement one.
|-
| KTIME
| constant
| <pre>ktime</pre>
| Value: 0x20<br />When set in flags, keep the time limit across levels.
|-
| KTOOLS
| constant
| <pre>ktools</pre>
| Value: 0x10<br />When set in flags, keep collected tools (items and keys) across levels.
|-
| TLEFT
| variable
| <pre>tleft</pre>
| Contains the global time limit when ktime is set in flags.
|-
| TOOLS
| variable
| <pre>tools</pre>
| Contains the current tools inventory (see above).
|-
| KEYS
| variable
| <pre>keys</pre>
| Contains the current keys inventory (see above).
|-
| ART
| directive
| <pre>art "..."</pre>
| Was supposed to replace a part of the tileset with custom art. Was removed due to being impossible to implement.
|-
| WAV
| directive
| <pre>wav "..."</pre>
| May have been inteded to load a custom set of sound effects from a path.
|-
| RAND
| pseudo-variable
| <pre>rand</pre>
| When read, generates a pseudo-random integer. (since all variables are signed 32-bit values, the minimal and maximum values are −2,147,483,648 and 2,147,483,647, respectively)
|-
| SPEED
| variable
| <pre>speed</pre>
| Contains the current gameplay speed.  1 = 100% (normal speed).
|-
| NO_BONUS
| constant
| <pre>no_bonus</pre>
| Value: 0x40<br />When set in flags, disables bonus flag pickup (see above for details).
|-
| NO_L_DOORS
| unknown
|
|
%
| Appears to be used. May have been used to debug [[swivel]] behavior.
^
|-
REPLAY
| MAIN
CONTINUE
| directive
SILENT
| <pre>main</pre>
KTIME
| Use is currently unknown.  Appears to jump to "playcc2.c2g" from the current levelset or script.
KTOOLS
|-
TLEFT
| GAME
TOOLS
| directive
KEYS
| <pre>game "&lt;name&gt;"</pre>
ART
| Sets the name of the current levelset to &lt;name&gt;
WAV
|-
RAND
| DLC
SPEED
| directive
NO_BONUS
| <pre>dlc "..."</pre>
NO_L_DOORS
| Use is currently unknown.
MAIN
|}
GAME
DLC</nowiki>


[[Category:File formats]]
[[Category:File formats]]