Oni (folder)/GameDataFolder/IGMD/global: Difference between revisions
m (→Code overriding: even better) |
m (clarifying) |
||
Line 1: | Line 1: | ||
'''global''' is a sort of secret subfolder of [[IGMD|IGMD]]; a regular installation of Oni doesn't have it at all. But if you create it manually, you'll find it can serve a very special purpose: functions in the '''global''' folder can be called from every one of Oni's levels. | '''global''' is a sort of secret subfolder of [[IGMD|IGMD]]; a regular installation of Oni doesn't have it at all. But if you create it manually, you'll find it can serve a very special purpose: functions in the '''global''' folder can be called from every one of Oni's levels. | ||
__NOTOC__ | |||
==Code reuse== | ==Code reuse== | ||
One obvious use for this feature is that when writing a script that affects multiple levels, you can place common BSL functions in '''global''' instead of duplicating that code in each level's BSL files. However, you are still going to have to modify each level's BSL to ''call'' this global function. | One obvious use for this feature is that when writing a script that affects multiple levels, you can place common BSL functions in '''global''' instead of duplicating that code in each level's BSL files. However, you are still going to have to modify each level's BSL to ''call'' this global function. | ||
Line 15: | Line 15: | ||
} | } | ||
You might be tempted to use <tt>fork some_global_function</tt>, but it's usually better to call the function "inline" (that is, no <tt>fork</tt>) to make sure that it fully executes before the original level logic resumes. You can always <tt>fork</tt> what you want to be <tt>fork</tt>ed inside your global function. Just be aware that anything you add, such as a <tt>sleep</tt> command, will delay the execution of the original logic, unless you do decide to use <tt>fork</tt>. | You might be tempted to use <tt>[[BSL:BungieFrameWork_Scripting_Language#Syntax_Overview|fork]] some_global_function</tt>, but it's usually better to call the function "inline" (that is, no <tt>fork</tt>) to make sure that it fully executes before the original level logic resumes. You can always <tt>fork</tt> what you want to be <tt>fork</tt>ed inside your global function. Just be aware that anything you add, such as a <tt>sleep</tt> command, will delay the execution of the original logic, unless you do decide to use <tt>fork</tt>. | ||
==Code overriding== | ==Code overriding== | ||
A less obvious "feature" of the '''global''' folder is overriding. A normally unseen rule in BSL is that <u>global functions override local ones</u>. For instance, place this in a global BSL file and play Chapter 4, Airport Assault: | ===Local overriding=== | ||
A less obvious "feature" of the '''global''' folder is overriding. A normally unseen rule in BSL is that <u>global functions override local ones by the same name</u>. For instance, place this in a global BSL file and play Chapter 4, Airport Assault: | |||
func void bomber_boom(string char_index) | func void bomber_boom(string char_index) | ||
Line 27: | Line 28: | ||
} | } | ||
That function is what causes the explosion of the ramp in the airport. Now, instead of creating an explosion particle and deleting the ramp, Oni just prints that message. Seemingly one could use this method to "patch" level BSL. However.... | That function, in airport1_level_logic.bsl, is what causes the explosion of the ramp in the airport. Now, instead of creating an explosion particle and deleting the ramp, Oni just prints that message. Seemingly one could use this method to "patch" level BSL. However.... | ||
'''Big catch''': there may be unpredictable results; for instance, this override causes random problems in the level, though the dmsg will print appropriately when you reach the point where the ramp is supposed to explode. | '''Big catch''': there may be unpredictable results; for instance, this override causes random problems in the level like changing Konoko's spawn location, though the dmsg will print appropriately when you reach the point where the ramp is supposed to explode. | ||
Here's an even more astounding application of BSL overriding: another rule is that <u>functions declared in BSL override built-in (hardcoded) ones</u>. This means that you can create a pseudo-[[wikipedia:Hooking|hook]], like this one: | ===Built-in overriding=== | ||
Here's an even more astounding application of BSL overriding: you can replace Oni's [[BSL:Functions|built-in functions]]. This is because another BSL rule is that <u>functions declared in BSL files override built-in (hardcoded) ones by the same name</u>. This means that you can create a pseudo-[[wikipedia:Hooking|hook]], like this one: | |||
# | # The built-in env_show function takes two ints, so we'll do that here too | ||
func env_show(int a, int b) | func env_show(int a, int b) | ||
{ | { | ||
Line 39: | Line 41: | ||
} | } | ||
Now Oni's level scripts cannot hide objects in the environment, and as you play a level you will see the effect of this. One obvious change is found in the introductory cutscene in Chapter 2. Ah, that must be the seat the receptionist wanted you to take! ^_^ | Now Oni's level scripts cannot hide objects in the environment by calling env_show ''x'' 0, and as you play a level you will see the effect of this. One obvious change is found in the introductory cutscene in Chapter 2. Ah, that must be the seat the receptionist wanted you to take! ^_^ | ||
'''Big catch''': pseudo-hooks like this are of limited value because there's no way to call the original function once you've overridden its name with your own declaration, | '''Big catch''': pseudo-hooks like this are of limited value because there's no way to call the original function once you've overridden its name with your own declaration. Therefore, you can't add code to the beginning or end of a built-in function as you should be able to with a true hook; you can only prevent the built-in function from running, and run your own code instead. In theory you might be able to reconstruct a built-in call's effects using equivalent BSL commands. This is attempted by Gumby's cutscene-skipping script, which attempts to replace [[BSL:Functions#cutscene|begin_cutscene and end_cutscene]] with its own implementations so it can add a "skip cutscene" key, with somewhat unpredictable results. | ||
Thus, the override "feature" is not recommended for use. | Thus, the override "feature" is not recommended for use. | ||
[[Category:Game directory map]] | [[Category:Game directory map]] |
Revision as of 01:53, 27 April 2013
global is a sort of secret subfolder of IGMD; a regular installation of Oni doesn't have it at all. But if you create it manually, you'll find it can serve a very special purpose: functions in the global folder can be called from every one of Oni's levels.
Code reuse
One obvious use for this feature is that when writing a script that affects multiple levels, you can place common BSL functions in global instead of duplicating that code in each level's BSL files. However, you are still going to have to modify each level's BSL to call this global function.
Let's say you want Oni to run a function every time you load a level. You have to go in every level's IGMD folder, open the file where func void main(void) is declared and modify it as follows :
func void main(void) { some_global_function # <--inserted line # ORIGINAL CODE }
Next you would go to the global folder and create a file by any name with the suffix ".bsl", and the function:
func some_global_function { # Code to run at start of every level }
You might be tempted to use fork some_global_function, but it's usually better to call the function "inline" (that is, no fork) to make sure that it fully executes before the original level logic resumes. You can always fork what you want to be forked inside your global function. Just be aware that anything you add, such as a sleep command, will delay the execution of the original logic, unless you do decide to use fork.
Code overriding
Local overriding
A less obvious "feature" of the global folder is overriding. A normally unseen rule in BSL is that global functions override local ones by the same name. For instance, place this in a global BSL file and play Chapter 4, Airport Assault:
func void bomber_boom(string char_index) { dmsg "Where's the kaboom?!" sleep 60 dmsg "There was supposed to be an Earth-shattering kaboom!" }
That function, in airport1_level_logic.bsl, is what causes the explosion of the ramp in the airport. Now, instead of creating an explosion particle and deleting the ramp, Oni just prints that message. Seemingly one could use this method to "patch" level BSL. However....
Big catch: there may be unpredictable results; for instance, this override causes random problems in the level like changing Konoko's spawn location, though the dmsg will print appropriately when you reach the point where the ramp is supposed to explode.
Built-in overriding
Here's an even more astounding application of BSL overriding: you can replace Oni's built-in functions. This is because another BSL rule is that functions declared in BSL files override built-in (hardcoded) ones by the same name. This means that you can create a pseudo-hook, like this one:
# The built-in env_show function takes two ints, so we'll do that here too func env_show(int a, int b) { dmsg "Env_show has been disabled." }
Now Oni's level scripts cannot hide objects in the environment by calling env_show x 0, and as you play a level you will see the effect of this. One obvious change is found in the introductory cutscene in Chapter 2. Ah, that must be the seat the receptionist wanted you to take! ^_^
Big catch: pseudo-hooks like this are of limited value because there's no way to call the original function once you've overridden its name with your own declaration. Therefore, you can't add code to the beginning or end of a built-in function as you should be able to with a true hook; you can only prevent the built-in function from running, and run your own code instead. In theory you might be able to reconstruct a built-in call's effects using equivalent BSL commands. This is attempted by Gumby's cutscene-skipping script, which attempts to replace begin_cutscene and end_cutscene with its own implementations so it can add a "skip cutscene" key, with somewhat unpredictable results.
Thus, the override "feature" is not recommended for use.