/** * \defgroup Enforce Enforce script essentials * \note \p float ftime; The deltaTime since last frame * \note \p float FLT_MAX; The maximum value for float * \note \p float FLT_MIN; The minimum value for float * @{ */ //! Super root of all classes in Enforce script class Class { /** \brief Returns true when instance is of the type, or inherited one. \param type Class type \returns \p bool true when 'clType' is the same as 'type', or inherited one. @code if (inst && inst.IsInherited(Widget)) { Print("inst is inherited from Widget class!"); } @endcode */ proto native external bool IsInherited(typename type); /** \brief Returns name of class-type \param inst Class \returns \p string class-type @code Man player = g_Game.GetPlayer(); string className = player.ClassName(); Print(className); >> className = 'Man' @endcode */ proto native owned external string ClassName(); string GetDebugName() { return ClassName(); } /** \brief Returns typename of object's class \returns \p typename class-type @code Man player = g_Game.GetPlayer(); typename type = player.Type(); Print(type.ToString()); >> 'Man' @endcode */ proto native external typename Type(); /** \brief Returns typename of object's reference \returns \p typename class-type @code EntityAI e; Print(e.StaticType()); >> 'EntityAI' @endcode */ proto external static typename StaticType(); /** \brief Returns typename of class even without a variable or instance \returns \p typename class-type @code typename eAITypename = StaticGetType(EntityAI); @endcode */ static typename StaticGetType(typename t) { return t; } proto external string ToString(); /** \brief Try to safely down-cast base class to child class. \returns down-casted 'from' pointer when cast is successfull (classes are related), or null if casting is invalid @code // assume that Man inheites from Object Object obj = g_Game.GetPlayer(); Man player = Man.Cast(obj); if (player) { // horay! } @endcode */ proto static Class Cast(Class from); /** \brief Try to safely down-cast base class to child class. \returns \p bool true when 'from' is not null and cast successfull, false when casting is not valid or 'from' is null @code // assume that Man inheites from Object Object obj = g_Game.GetPlayer(); Man player; if (Class.CastTo(player, obj)) { // horay! } @endcode */ proto static bool CastTo(out Class to, Class from); //! This function is for internal script usage private proto static bool SafeCastType(Class type, out Class to, Class from); }; //! TODO doc class Managed { }; //! TODO doc class NonSerialized { }; //! script representation for C++ RTTI types typedef int[] TypeID; //! Module containing compiled scripts. class ScriptModule { private void ~ScriptModule(); /*!dynamic call of function when inst == NULL, it's global function call, otherwise it's method of class returns true, when success The call creates new thread, so it's legal to use sleep/wait */ proto volatile int Call(Class inst, string function, void parm); /*!dynamic call of function when inst == NULL, it's global function call, otherwise it's method of class returns true, when success The call do not create new thread!!!! */ proto volatile int CallFunction(Class inst, string function, out void returnVal, void parm); proto volatile int CallFunctionParams(Class inst, string function, out void returnVal, Class parms); proto native void Release(); /** \brief Do load script and create ScriptModule for it \param parentModule Module \param scriptFile Script path \param listing ?? \returns \p ScriptModule Loaded scripted module @code ??? @endcode */ static proto native ScriptModule LoadScript(ScriptModule parentModule, string scriptFile, bool listing); }; //main script module (contains script.c and this file) //ScriptModule g_Script; class EnScript { private void EnScript() {} private void ~EnScript() {} /** \brief Dynamic read of variable value by its name \param inst When inst == NULL, it's for global variable, otherwise it's class member \param index Is index when variable is array \param[out] result Variable must be of the same type! \returns \p int true when success @code float count = 0; bool success = EnScript.GetClassVar(myClass, "m_Counter", 0, count); Print(count); Print(success); >> count = 5 >> success = 1 @endcode */ static proto int GetClassVar(Class inst, string varname,int index, out void result); /** \brief Dynamic write to variable by its name \param inst when inst == NULL, it's for global variable, otherwise it's class member \param varname \param index Is index when variable is array \param input Input variable must be of the same type! \returns \p int Returns true(1) when success @code Print(myClass.m_Counter); >> m_Counter = 0 bool success = EnScript.SetClassVar(myClass, "m_Counter", 0, 5.0); Print(myClass.m_Counter); Print(success); >> m_Counter = 5 >> success = 1 @endcode */ static proto int SetClassVar(Class inst, string varname, int index, void input); /** \brief Sets variable value by value in string \param[out] var \param value \returns int @code ??? @endcode */ static proto int SetVar(out void var, string value); /** \brief Debug tool for watching certain variable. Invokes debugger whenever is variable used \param var Certain variable for watching \param flags = 1 means it will break even when not modified \return \p void */ static proto void Watch(void var, int flags); }; /** \brief Sorts static array of integers(ascendically) / floats(ascendically) / strings(alphabetically) \param param_array \p array Array to sort \param num \p int How many items will be sorted in array \return \p void @code string arrStr[3] = {"Dog", "Car", "Apple"}; Sort(arrStr, 2) for ( int x = 0; x < 3; x++ ) { Print( arrStr[x] ); } >> 'Car' >> 'Dog' >> 'Apple' @endcode */ proto void Sort(void param_array[], int num); proto void reversearray(void param_array); proto void copyarray(void destArray, void srcArray); /** \brief Parses one token from input string. Result is put into token string, and type of token is returned. Input string is left-truncated by the resulting token length. \param[in,out] input \p string String for parse\ Output is without founded token \param[out] token \p string Founded string token \return \p int Type of token \verbatim Token types: 0 - error, no token 1 - defined token (special characters etc. . / * ) 2 - quoted string. Quotes are removed -> TODO 3 - alphabetic string 4 - number 5 - end of line -> TODO \endverbatim @code string input = "Hello*World"; string token1; string token2; int result1 = ParseStringEx(input, token1); int result2 = ParseStringEx(input, token2); Print( String( "Token1 = '" + token1 + "' Type = " + result1.ToString() ) ); Print( String( "Token2 = '" + token2 + "' Type = " + result2.ToString() ) ); Print( input ); >> 'Toke1 = 'Hello' Type = 3' >> 'Toke1 = '*' Type = 1' @endcode */ proto int ParseStringEx(inout string input, string token); /** \brief Parses string into array of tokens returns number of tokens \param input \p string String for parse \param[out] tokens \p array[] Parsed string in array \return \p int Number of tokens @code string token[2]; int result = ParseString("Hello World", token); for( int i = 0; i < 2; i++ ) { Print(token[i]); } >> 'Hello' >> 'World' @endcode */ proto int ParseString(string input, out string tokens[]); /** \brief Kills thread. \param owner Can be NULL for global threads. \param name Name of the first function on stack \return \p int ??? @code ??? @endcode */ proto native int KillThread(Class owner, string name); /** Yiels execution to other threads and then it continues. Obsolete... */ proto volatile void Idle(); /** \brief Debug function. Returns current function on stack of the thread \param owner Can be NULL for global threads \param name Name of the first function on stack \param backtrace ??? \param linenumber ??? \return \p string ??? @code ??? @endcode */ proto owned string ThreadFunction(Class owner, string name, int backtrace, out int linenumber); //!Helper for passing string expression to functions with void parameter. Example: Print(String("Hello " + var)); string String(string s) { return s; } //!Helper for printing out string expression. Example: PrintString("Hello " + var); void PrintString(string s) { Print(s); } class array { /*! O(1) complexity. \return Number of elements of the array */ proto native int Count(); /*! Destroyes all elements of the array and sets the Count to 0. The underlying memory of the array is not freed. */ proto native void Clear(); /*! Sets n-th element to given value. */ proto void Set(int n, T value); /*! Tries to find the first occurance of given value in the array. \return Index of the first occurance of `value` if found, -1 otherwise */ proto int Find(T value); /*! \return Element at the index `n` */ proto T Get(int n); /*! Inserts element at the end of array. \param value Element to be inserted \return Position at which element is inserted */ proto int Insert(T value); /*! Inserts element at certain position and moves all elements behind this position by one. \param value Element to be inserted \param index Position at which element is inserted. Must be less than Array::GetCardinality() \return Number of elements after insertion */ proto int InsertAt(T value, int index); /** \brief Inserts all elements from array \param from \p array array from which all elements will be added @code TStringArray arr1 = new TStringArray; arr1.Insert( "Dave" ); arr1.Insert( "Mark" ); arr1.Insert( "John" ); TStringArray arr2 = new TStringArray; arr2.Insert( "Sarah" ); arr2.Insert( "Cate" ); arr1.InsertAll(arr2); for ( int i = 0; i < arr1.Count(); i++ ) { Print( arr1.Get(i) ); } delete arr2; delete arr1; >> "Dave" >> "Mark" >> "John" >> "Sarah" >> "Cate" @endcode */ void InsertAll(notnull array from) { for ( int i = 0; i < from.Count(); i++ ) { Insert( from.Get(i) ); } } /*! Removes element from array. The empty position is replaced by last element, so removal is quite fast but do not retain order. \param index Index of element to be removed */ proto native void Remove(int index); /*! Removes element from array, but retain all elements ordered. It's slower than Remove \param index Index of element to be removed */ proto native void RemoveOrdered(int index); /*! Resizes the array to given size. If the `newSize` is lower than current Count overflowing objects are destroyed. If the `newSize` is higher than current Count missing elements are initialized to zero (null). */ proto native void Resize(int newSize); /*! Resizes the array to given size internally. Is used for optimization purposes when the approx. size is known beforehand */ proto native void Reserve(int newSize); /*! Swaps the contents of this and `other` arrays. Does not involve copying of the elements. */ proto native void Swap(notnull array other); /*! Sorts elements of array, depends on underlaying type. */ proto native void Sort(bool reverse = false); /*! Copes contents of `from` array to this array. \return How many elements were copied */ proto int Copy(notnull array from); proto int Init(T init[]); void RemoveItem(T value) { int remove_index = Find(value); if ( remove_index >= 0 ) { RemoveOrdered(remove_index); } } void RemoveItemUnOrdered(T value) { int remove_index = Find(value); if ( remove_index >= 0 ) { Remove(remove_index); } } bool IsValidIndex( int index ) { return ( index > -1 && index < Count() ); } /* T GetChecked( int index ) { if( IsValidIndex( index ) ) return Get( index ); else return null; } */ /** \brief Print all elements in array \return \p void @code my_array.Debug(); >> "One" >> "Two" >> "Three" @endcode */ void Debug() { Print(string.Format("Array count: %1", Count())); for (int i = 0; i < Count(); i++) { T item = Get(i); Print(string.Format("[%1] => %2", i, item)); } } /** \brief Returns a random index of array. If Count is 0, return index is -1 . \return \p int Random index of array @code Print( my_array.GetRandomIndex() ); >> 2 @endcode */ int GetRandomIndex() { if ( Count() > 0 ) { return Math.RandomInt(0, Count()); } return -1; } /** \brief Returns a random element of array \return \p int Random element of array @code Print( my_array.GetRandomElement() ); >> "Three" @endcode */ T GetRandomElement() { return Get(GetRandomIndex()); } void SwapItems(int item1_index, int item2_index) { T item1 = Get(item1_index); Set(item1_index, Get(item2_index)); Set(item2_index, item1); } void InsertArray(array other) { for (int i = 0; i < other.Count(); i++) { T item = other.Get(i); Insert(item); } } void Invert() { int left = 0; int right = Count() - 1; if (right > 0) { while (left < right) { T temp = Get(left); Set(left++, Get(right)); Set(right--, temp); } } } /** \brief Returns a index in array moved by specific number \return \p int Moved index in this array @code Print( "Count: "+ my_array.Count() ); Print( "Moved 1:"+ my_array.MoveIndex(2, 1) ); Print( "Moved 3:"+ my_array.MoveIndex(2, 2) ); >> "Count: 4" >> "Moved index 2 by 1: 3"; >> "Moved index 2 by 2: 0"; @endcode */ int MoveIndex(int curr_index, int move_number) { int count = Count(); int new_index = curr_index; if ( move_number > 0 ) { new_index = curr_index + move_number; } if ( move_number < 0 ) { new_index = curr_index - move_number; if ( new_index < 0 ) { if ( new_index <= -count ) { new_index = (new_index % count); } new_index = new_index + count; } } if ( new_index >= count ) { new_index = (new_index % count); } // move_number is 0 return new_index; } void ShuffleArray() { for (int i = 0; i < Count(); i++) { SwapItems(i,GetRandomIndex()); } } /** \brief Returns an index where 2 arrays start to differ from each other \return \p int Index from where arrays differ @code array arr1 = {0,1,2,3}; array arr2 = {0,1,3,2}; int differsAt = arr1.DifferentAtPosition(arr2); Print(differsAt); >> 2 @endcode */ int DifferentAtPosition(array pOtherArray) { if (Count() != pOtherArray.Count()) { ErrorEx("arrays are not the same size"); return -1; } for (int i = 0; i < pOtherArray.Count(); ++i) { if (Get(i) != pOtherArray.Get(i)) { return i; } } return -1; } }; //force these to compile so we can link C++ methods to them typedef array TStringArray; typedef array TFloatArray; typedef array TIntArray; typedef array TBoolArray; typedef array TClassArray; typedef array TManagedArray; typedef array TManagedRefArray; typedef array TVectorArray; typedef array TTypenameArray; class set { proto native int Count(); proto native void Clear(); /*! Tries to find the first occurance of given value in the set. \return Index of the first occurance of `value` if found, -1 otherwise */ proto int Find(T value); proto T Get(int n); /*! Inserts element at the end of array. \param value Element to be inserted \return Position at which element is inserted */ proto int Insert(T value); /*! Inserts element at certain position and moves all elements behind this position by one. \param value Element to be inserted \param index Position at which element is inserted. Must be less than Array::GetCardinality() \return Number of elements after insertion */ proto int InsertAt(T value, int index); /*! Removes element from array, but retain all elements ordered. \param index Index of element to be removed */ proto native void Remove(int index); proto int Copy(set from); proto native void Swap(set other); proto int Init(T init[]); void InsertSet(set other) { int count = other.Count(); for (int i = 0; i < count; i++) { T item = other[i]; Insert(item); } } void RemoveItem(T value) { int remove_index = Find(value); if (remove_index >= 0) { Remove(remove_index); } } void RemoveItems(set other) { int count = other.Count(); for (int i = 0; i < count; i++) { T item = other[i]; RemoveItem(item); } } void Debug() { Print(string.Format("Set count: %1", Count())); for (int i = 0; i < Count(); i++) { T item = Get(i); Print(string.Format("[%1] => %2", i, item)); } } }; //force these to compile so we can link C++ methods to them typedef set TStringSet; typedef set TFloatSet; typedef set TIntSet; typedef set TClassSet; typedef set TManagedSet; typedef set TManagedRefSet; typedef set TTypenameSet; typedef int MapIterator; /** \brief Associative array template \n usage: @code autoptr map prg_count = new map; // fill project_locations.Insert("dayz", 10); project_locations.Insert("arma", 20); project_locations.Insert("tkom", 1); Print(project_locations.Get("arma")); // prints '20' @endcode */ class map { /*! \return The number of elements in the hashmap. */ proto native int Count(); /*! Clears the hash map. */ proto native void Clear(); /*! Search for an element with the given key. \param key The key of the element to find \return Pointer to element data if found, NULL otherwise. */ proto TValue Get(TKey key); /*! Search for an element with the given key. \param key The key of the element to find \param val result is stored to val \return returns True if given key exist. */ proto bool Find(TKey key, out TValue val); /*! Return the i:th element in the map. Note: This operation is O(n) complexity. Use with care! \param index The position of the element in the map \return The element on the i:th position */ proto TValue GetElement(int index); /*! Return the i:th element key in the map. Note: This operation is O(n) complexity. Use with care! \param i The position of the element key in the map \return Return key of i-th element */ proto TKey GetKey(int i); /*! Sets value of element with given key. If element with key not exists, it is created. Note: creating new elements is faster using Insert function. */ proto void Set(TKey key, TValue value); /*! Removes element with given key. */ proto void Remove(TKey key); /*! Removes i:th element with given key. Note: This operation is O(n) complexity. Use with care! \param i The position of the element key in the map */ proto void RemoveElement(int i); /*! Returns if map contains element with given key. */ proto bool Contains(TKey key); /*! Insert new element into hash map. \param key Key of element to be inserted. \param value Data of element to be inserted. */ proto bool Insert(TKey key, TValue value); proto int Copy(map from); array GetKeyArray() { array keys = new array; for (int i = 0; i < Count(); i++) { keys.Insert( GetKey( i ) ); } return keys; } array GetValueArray() { array elements = new array; for (int i = 0; i < Count(); i++) { elements.Insert( GetElement( i ) ); } return elements; } bool ReplaceKey(TKey old_key, TKey new_key) { if (Contains(old_key)) { Set(new_key, Get(old_key)); Remove(old_key); return true; } return false; } TKey GetKeyByValue(TValue value) { TKey ret; for (int i = 0; i < Count(); i++) { if (GetElement(i) == value) { ret = GetKey(i); break; } } return ret; } bool GetKeyByValueChecked(TValue value, out TKey key) { for (int i = 0; i < Count(); i++) { if (GetElement(i) == value) { key = GetKey(i); return true; } } return false; } proto native MapIterator Begin(); proto native MapIterator End(); proto native MapIterator Next(MapIterator it); proto TKey GetIteratorKey(MapIterator it); proto TValue GetIteratorElement(MapIterator it); }; typedef map TIntFloatMap; typedef map TIntIntMap; typedef map TIntStringMap; typedef map TIntClassMap; typedef map TIntManagedMap; typedef map TIntManagedRefMap; typedef map TIntTypenameMap; typedef map TIntVectorMap; typedef map TStringFloatMap; typedef map TStringIntMap; typedef map TStringStringMap; typedef map TStringClassMap; typedef map TStringManagedMap; typedef map TStringManagedRefMap; typedef map TStringTypenameMap; typedef map TStringVectorMap; typedef map TClassFloatMap; typedef map TClassIntMap; typedef map TClassStringMap; typedef map TClassClassMap; typedef map TClassManagedMap; typedef map TClassManagedRefMap; typedef map TClassTypenameMap; typedef map TClassVectorMap; typedef map TTypeNameFloatMap; typedef map TTypeNameIntMap; typedef map TTypeNameStringMap; typedef map TTypeNameClassMap; typedef map TTypeNameManagedMap; typedef map TTypeNameManagedRefMap; typedef map TTypeNameTypenameMap; typedef map TTypeNameVectorMap; typedef map TManagedFloatMap; typedef map TManagedIntMap; typedef map TManagedStringMap; typedef map TManagedClassMap; typedef map TManagedManagedMap; typedef map TManagedManagedRefMap; typedef map TManagedTypenameMap; typedef map TManagedVectorMap; typedef map TManagedRefFloatMap; typedef map TManagedRefIntMap; typedef map TManagedRefStringMap; typedef map TManagedRefClassMap; typedef map TManagedRefManagedMap; typedef map TManagedRefManagedRefMap; typedef map TManagedRefTypenameMap; typedef map TManagedRefVectorMap; //@}