User Tools

Site Tools


hpl3:engine:script

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revision Both sides next revision
hpl3:engine:script [2012/05/16 06:22]
jens
hpl3:engine:script [2014/02/18 07:24]
thomas [Comments]
Line 22: Line 22:
 ||m|| a member variable || class cMyClass {\\ int mlMember;\\ } || ||m|| a member variable || class cMyClass {\\ int mlMember;\\ } ||
 ||g|| a global variable, defined outside of a class or function.|| int glMyGlobal; \\ class cMyClass {} || ||g|| a global variable, defined outside of a class or function.|| int glMyGlobal; \\ class cMyClass {} ||
 +||id|| this is for tID type.|| tID m_idEntity ||
  
 a variable name always starts with a lower case letter, so anything of type not specified must start with a lower case word. Example: a variable name always starts with a lower case letter, so anything of type not specified must start with a lower case word. Example:
Line 61: Line 62:
 cMonster@ pMonster = CurrentHit();​ cMonster@ pMonster = CurrentHit();​
 float fDamage = RandomDamage();​ float fDamage = RandomDamage();​
-fDamage -= pMonster->Defense();+fDamage -= pMonster.Defense();
 if(fDamage<​0) fDamage =0; if(fDamage<​0) fDamage =0;
 fDamage *= mfHitMultiplier;​ fDamage *= mfHitMultiplier;​
-pMonster->DecHealth(fDamage);​+pMonster.DecHealth(fDamage);​
 </​code>​ </​code>​
  
Line 75: Line 76:
 float fDistSqr = vDiff.x*vDiff.x +vDiff.y*vDiff.y;​ float fDistSqr = vDiff.x*vDiff.x +vDiff.y*vDiff.y;​
 </​code>​ </​code>​
 +
 +Only do this in rare cases when it is really hard to figure what the code means. Normally, simply using section comments is enough. If you split the code into nice sections and name them well, that should be more than enough for other people to figure out what it is about.
  
  
Line 160: Line 163:
  
 ==== Handles ==== ==== Handles ====
-For any script that is to be saved (which means all scripts pretty much), handles to script classes can NOT be member variables. So a script file like:\\ + 
-<code c++>​class cMyClass {+ 
 +For any script that is to be saved (which means all scripts pretty much), handles to script classes can NOT be member variables. So a script file like: 
 + 
 + 
 +<code c++> 
 +class cMyClass {
  ...  ...
 } }
Line 167: Line 175:
  ...  ...
  ​cMyClass@ mpMyClass;  ​cMyClass@ mpMyClass;
-}</​code>​+} 
 +</​code>​ 
 + 
 is NOT supported. The reason for this is that when a script is destroyed any handle to these classes are destroyed too and cannot be retrieved again! is NOT supported. The reason for this is that when a script is destroyed any handle to these classes are destroyed too and cannot be retrieved again!
 +
  
 It is however okay to to pass handles as arguments: It is however okay to to pass handles as arguments:
 +
 +
 <code c++>void MyFunc(cMyClass@ apArg) { <code c++>void MyFunc(cMyClass@ apArg) {
 ... ...
-}</​code>​ +} 
-or use them as local or global variables. ​+</​code>​ 
 + 
 + 
 +or use them as local or global variables. 
 + 
 <code c++> <code c++>
 cMyClass@ gpGlobalVar cMyClass@ gpGlobalVar
 void MyFunc() { void MyFunc() {
 </​code>​ </​code>​
-<code c++> + 
-void MyFunc() {+ 
 +<code c++>void MyFunc() {
  ​cMyClass@ pLocalVar  ​cMyClass@ pLocalVar
  ...  ...
 } }
 </​code>​ </​code>​
-It is only when they are to be saved that problems arise! 
  
-Finally, having handles ​to engine types, ie + 
-<code c++>​class cMyClass {+Its only when they are to be saved that problems arise. 
 + 
 + 
 +==== ID Handles ==== 
 + 
 + 
 +When working with engine types it is recommended to use ID handles instead of class pointers. 
 + 
 + 
 +<code c++> 
 +class cMyClass {
  ​iPhyiscsBody@ mpBody  ​iPhyiscsBody@ mpBody
-}</​code>​  +} 
-is okay!+</​code>​ 
 + 
 + 
 +Using class handler directly like this works but it is unsafe and does not support saving. Instead the handle can be saved like this. 
 + 
 + 
 +<​code>​ 
 +class cMyClass { 
 + tID mBody; 
 +
 +</​code>​ 
 + 
 + 
 +This saves a unqiue identifier to the body. The ID of a object can be retrived by calling GetID() function. There are script functions for converting the ID to a class handle. 
 + 
 + 
 +<​code>​ 
 +void MyFunc() { 
 + 
 + ​iPhysicsBody@ pBody = cLux_ID_PhysicsBody(mBody);​ 
 + 
 + ​if(pBody ​!is null) { 
 + 
 +  ... 
 + } 
 + 
 +
 +</​code>​ 
 + 
 + 
 +This retrives the class handle from the engine so that it can be used. Retriving the class handle from the ID is very fast. 
 + 
 + 
 +Using a ID instead of a class handle has two big advantages. Unlike class handles the ID can be saved. When loading the save file the ID will still work and retrive the same object. 
 + 
 + 
 +If the object that the ID handle points to gets deleted anywhere else in the code the ID will still be safe. When trying to retrive a deleted object the function will return null. Accessing null pointers will never cause the game to crash. When accessing a class handle that has been deleted that leads to accessing deallocated memory and the game will crash. 
 ===== Script Callbacks ===== ===== Script Callbacks =====
  
Line 248: Line 314:
 bool bArg0 = cScript_GetGlobalArgBool(0);​ bool bArg0 = cScript_GetGlobalArgBool(0);​
 cVector3f vArg1 = cScript_GetGlobalArgVector3f(1);</​code>​ cVector3f vArg1 = cScript_GetGlobalArgVector3f(1);</​code>​
-**5)** When calling a global function, it is okay to have one or more asterix in the object name and then several object will be called. For example //"​My*test"//​ would call: //"​MyNiceTest"//​ and //"​MyBadTest"//​. However, this will be a bit slower, so be careful when using it (eg not during things called every update)+**5)** When calling a global function, it is okay to have one or more asterix in the object name and then several object will be called. For example //"​My*test"//​ would call: //"​MyNiceTest"//​ and //"​MyBadTest"//​. However, this will be a bit slower, so be careful when using it (eg not during things called every update)
 + 
 +Asterix is also supported for the class name (eg "​cMyClass*"​). If you do not care about the class of the objects the class param can simply be empty (""​). The following will call MyGlobalFunc in all script modules named "​MyClassObj"​ no matter the class name: 
 + 
 +<code c++> 
 +cScript_RunGlobalFunc("​MyClassObj",​ "",​ "​MyGlobalFunc"​);​ 
 +</​code>​
 ===== Saving ===== ===== Saving =====
  
  
-To skip saving a variable, you must use metadata keyword [nosave] in front of the the variable name. Examples:\\  ​+To skip saving a variable, you must use metadata keyword [nosave] in front of the the variable name. Examples: 
 + 
 <code c++>​[nosave] float mfT; <code c++>​[nosave] float mfT;
-[nosave] cMyClass@ mHandle;</​code>​+[nosave] cMyClass@ mHandle; 
 +</​code>​ 
 + 
 + 
 +If you only want to save the actual pointer for a handle, but not any data, then use the prefix [nodatasave] Example: 
 + 
 + 
 +<code c++>​[nodatasave] cMyClass@ mNoSaveHandle;​ 
 +</​code>​ 
 + 
 +However it is almost always better to use the tID type for these situations!
  
-If you only want to save the actual pointer for a handle, but not any data, then use the prefix [nodatasave] Example:​\\ ​ 
-<code c++>​[nodatasave] cMyClass@ mNoSaveHandle;</​code>​ 
  
 Also, there is a the prefix [volatile], this will do the same as a [nosave] but will also make sure that variable is not even saved during script reload. This should be used on handles where you are never sure if saved variable can invalid, for instance cSoundEntity and cParticleSystem (that can be deleted by the engine). Also, there is a the prefix [volatile], this will do the same as a [nosave] but will also make sure that variable is not even saved during script reload. This should be used on handles where you are never sure if saved variable can invalid, for instance cSoundEntity and cParticleSystem (that can be deleted by the engine).
-<code c++>​[volatile] cSoundEnity@ mpCurrentSoundEntity;</​code>​ 
  
-In case you have an array of handles where none of the properties should be saved, this is NOT possible. Instead save names of IDs of the objects in the array. 
  
 +<code c++>​[volatile] cSoundEnity@ mpCurrentSoundEntity;​
 +</​code>​
 +
 +
 +Instead of using class handle here it is better to store the ID to the object. The ID can always be saved and will work correctly on load even if the object no longer exists. Worst thing that can happen is that when getting the actual class NULL is returned. This leads to an excpection, stopping further execution of the current script file, but does not lead to a crash or similar major failure.
 +
 +
 +<​code>​
 +tID mCurrentSoundEntity;​
 +</​code>​
 +
 +
 +In case you have an array of handles where none of the properties should be saved, this is NOT possible. Instead save names of IDs of the objects in the array.
 ===== Optimizing ===== ===== Optimizing =====
  
Line 281: Line 374:
 }</​code>​ }</​code>​
 That way they script does not need to create the local var for every loop and this can boost performance quite  a bit! That way they script does not need to create the local var for every loop and this can boost performance quite  a bit!
 +
 +**Include only what is needed**\\
 +Make sure that you only include hps files that are really needed. Having includes that are not used can eat up a lot of extra loading time very easily!
 ===== Important notes ===== ===== Important notes =====
  
 C++ scriptable classes with classes in can not be abstract ones. It must always be the top class in the hierarchy that is used and saved. C++ scriptable classes with classes in can not be abstract ones. It must always be the top class in the hierarchy that is used and saved.
 +
 +===== Specific Guidelines =====
 +
 +==== Helper Functions ====
 +
 +  * Helper functions should use degrees, not radians
hpl3/engine/script.txt · Last modified: 2020/07/01 07:07 by thomas