How to add a new script command

From OHRRPGCE-Wiki
Jump to navigation Jump to search

Adding a new script command can be one of the easiest ways to contribute to the engine, if the implementation of the command itself is simple.

Scripts in plotscr.hsd[edit]

Firstly, consider whether the command can be directly accomplished by adding a script to plotscr.hsd instead of hard-coding it.

  • Previously we preferred to put a lot of the implementation of a new command in plotscr.hsd when we could: for example get enemy stat is a script that calls read enemy data. In hindsight this was often not a good idea. For example, it was a mistake to add the read enemy data command, which now makes it more painful to change the enemy data file format. Also, scripts provide worse error checking, and it often turns out that in future we need to convert a script to a builtin command anyway.
    • However it's generally alright to add more wrappers around commands like read/write general since it seems unlikely that most of that data will change in format.

Built-in commands[edit]

If you need to add a new built-in command:

  • Add a line to the end of the define function block in plotscr.hsd.
    • The format is id, name, number of arguments, default argument values. Number of arguments can be -1 to allow any number. Unfortunately, there's no way to specify which arguments are required. Just set their default values to an invalid value that will throw an error in-game.
    • Use the next available ID number.
  • Change maxScriptCmdID in const.bi
  • Add the command to script_functions in scriptcommands.bas. You'll notice that the commands aren't ordered by ID number, but are in four blocks. It doesn't matter where you put the command; put it at the end unless there's a particular reason not to.
    • The command's return value should be put in scriptret. If you don't set it, it will be 0. If your command can fail (e.g. using an item that the player doesn't have), it's a good idea to set it to true (1) for success, false (0) on failure
      • If the command returns a handle to something it should ideally return 0 on failure, and a non-zero value otherwise. Is 0 is a valid value (e.g. hero party slot), return something invalid instead (e.g. -1).
    • Arguments are available in the retvals() array. Use the valid_* functions to check if an argument should be of a certain (conceptual) type, like an NPC ID/reference. You could add a new valid_* function if you add a new type.
      • Optional arguments are handled by giving them a default value in plotscr.hsd and checking for this default value in script_functions. The get_optional_arg function can only be used when the number of arguments to a command is increased in plotscr.hsd from what it originally was (in that case, the default values in plotscr.hsd don't apply to game scripts compiled against the old version).
      • A lot of valid_* functions take an errlvl argument. In general for new script commands you should use serrBadOp, rather than leaving it as its default value of serrBound (not that it matters much).
    • You can also call scripterror directly to signal other mistakes in calling the command. For new commands, in general use error level serrBadOp (which is the default, so can be omitted).
  • Recompile: run scons game

Common checklist[edit]

  • Test it. Ideally, add a test case if possible to autotest.rpg. Edit testgame/autotest.hss and run scons autotest to compile and import the scripts (and also recompile Game if needed) and run autotest.rpg. Don't press any keys while the game is running. If any test fails the tests will end early, and error messages are printed to g_debug.txt.
autotest.hss contains a huge number of tests which are run in order, so you need to be careful not to break other tests by changing the state of the game. For example if you more the hero you probably need to move it back to where it was after the test. This is admittedly not ideal.

See Also[edit]