[GLOBAL] The ultimate "advanced stuff" guide!

Tutorials for all THUG+ games goes here.
Forum rules
This forum is only for posting tutorials.
Specify what game it is for, and please take a look at this Template.
Post Reply
Morten1337
Site Admin
Posts: 322
Joined: Mon Mar 01, 2010 2:23 pm
Location: Norway

[GLOBAL] The ultimate "advanced stuff" guide!

Post by Morten1337 » Wed Jul 20, 2011 1:56 pm

Okay, so i decided to share most my knowledge on the advanced stuff that you can do in qbscripts.

Table of contents:
  • - Global types
    - %GLOBAL% usage
    - Calculations
    - Creating a Bool
    - Accessing Array data, (Structure index's)
    - Accessing Array data, (Item index)
    - Convert Vector's and Doubles to Float
    - Convert Floats to Vector and Double
Global types:
If you have data that you want to access at any time from any function;
global types is the way to go.

Global types include; Integer, Float, String, Checksum, Array and Structure.
These have to be placed outside any function.

Here are some examples:

Code: Select all

:i $Global_String$ = %s(0,"String01")
:i $Global_Float$ = %f(1.000000)

	:i function $nullscript$
	#// Scroll down for, usage in functions.
	:i endfunction
So, when you have the global values, you can start writing functions to use them.
To "get" the value you use this code:

Code: Select all

($*Checksum*$)
Example:

Code: Select all

	:i function $Example_GlobalString_Message$
		:i call $SendChatMessage$ arguments
				$string$ = ($Global_String$)
	:i endfunction
This function above (Example_GlobalString_Message), will send a chat message, with the text (Global_String) its assigned to. In this case "String01"

The "Change" function.
If you want to change a value in-game you need to use the function (Change)
It takes only one parameter. Like this:

Code: Select all

$*Checksum*$ = *Data Type* 
Example:

Code: Select all

:i call $Change$ arguments
		$Global_Float$ = %f(23.000000)
Errors that may occur while working with global types;
- two checksum names being the same = CRASH


%GLOBAL% Usage:
%GLOBAL% in the qb script is actually a misleading name.
But its very useful.

%GLOBAL% works pretty much like "Global types".
The difference is that the value has to be passed as a parameter into the function, OR it could be defined inside the function itself.

An easy way to explain the "passing as parameter"-part would be;
When you call a function you can add Arguments, the way it works is that you "give" the function data that it can access when its run. Unlike the "Global Types" where it can always be accessed.

You can set the names yourself just like the "Global Types"

Code: Select all

$*Checksum*$ = *Data Type* 
Here's an example:

Code: Select all

#// ...

:i call $Example_GlobalData$ arguments
		$global_data01$ = %s(0,"String01")$global_data02$ = %s(0,"String02")

#// ...

	:i function $Example_GlobalData$
		:i call $SendChatMessage$ arguments
				$string$ = %GLOBAL%$global_data01$

		:i call $SendChatMessage$ arguments
				$string$ = %GLOBAL%$global_data02$
	:i endfunction
This function above (Example_GlobalData), will send teo chat messages, with the text ( %GLOBAL%$global_data01$) and ( %GLOBAL%$global_data02$) . In this case "String01" and "String02".

Great!
Now for defining a new value inside a function.

This works exactly like the "Global Types", you can create;
Integers, Float, Vector, Doubles, Checksum, Arrays and Structures.
Although, the way its written could be different. 3 Ways actually!

Example:

Code: Select all

:i $Data_01$ = %f(1.000000)
$Data_02$ = %f(1.000000)
%GLOBAL%$Data_03$ = %f(3.000000)
Example of usage:

Code: Select all

	:i function $Example_GlobalData02$

		$myframes$ = %f(5.000000)

	:i $wait$%GLOBAL%$myframes$$frames$

#// Wait %GLOBAL% number of frames.

	:i endfunction
This function above (Example_GlobalData02), will run then wait the number of frames assigned to the %GLOBAL% value "myframes".

Actually, there is 3rd way to work add a %GLOBAL% value, its a little more advanced than the others.
If you have a function that is depending on a parameter/value being passed. You can add a "default" value to the "function header".

It works like this; if you have a function that will not work if some parameters are missing, you add a default value, that will only be use if a new one is not presented.

Here are two examples, that do the same thing:

Code: Select all

#//...
	:i call $Example_DefaultGlobal01$ arguments
			$GlobalString$ = %s(0,"String01")
#//...

	:i function $Example_DefaultGlobal01$
		:i call $SendChatMessage$ arguments
				$string$ = %GLOBAL%$GlobalString$
	:i endfunction

Code: Select all

#//...
	:i $Example_DefaultGlobal02$
#//...

	:i function call  $Example_DefaultGlobal02$ arguments
			$GlobalString$ = %s(0,"String01")

		:i call $SendChatMessage$ arguments
				$string$ = %GLOBAL%$GlobalString$
	:i endfunction
Get it? Its not that difficult... Really, its not!
Calculations:
I will keep this section short, because its common sense.

Mathematic calculations use:
Plus(+), Minus (-), Multiply (*), Divide (/).
And works with static Floats and Integers, Global Floats and Integers and %GLOBAL% Floats and Integers. It can be mixed up!

Example:

Code: Select all

:i $Global_Float01$ = %f(1.000000)

#//...
	:i call $Example_DoMathThing$ arguments
			$Float02$ = %f(2.000000)
#//...

	:i function $Example_DoMathThing$

	:i $new_float$ = ( (($Global_Float01$) + %GLOBAL%$Float02$) * %f(2.000000) )
	#// new_float = ((1 + 2) * 2) = 6

	:i endfunction
There are also some more advanced stuff you can do. Like check if one number is bigger/smaller than the other.
using < and >

An example:

Code: Select all

#// ...

	:i $new_float$ = ( (($Global_Float01$) + %GLOBAL%$Float02$) * %f(2.000000) )
	:i if (%GLOBAL%$new_float$ > %f(10.000000))
			#// If %GLOBAL%$new_float$ is BiggerThan 10, do do this.
		:i else
			#// If not, then do do this. Simple
	:i endif
#// ...
You can also calculate other number data types as Vectors and Doubles, but then both have to be the same type.
Example:

Code: Select all

#// ...
	:i $new_vector$ = (%vec3(0.000000,0.000000,0.000000) + %vec3(100.000000,200.000000,300.000000))
#// ...
Creating a Bool:
QB scripts does not really have a bool data type, but "If" statements can handle both Floats and Integers as a bool.
Its really simple, if you setup a Global Integer, either assigned to 0 or 1 it will be handled as True / False.

Code: Select all

:i $bool_test$ = %i(1,00000001)
:i function $Example_ShowHowBoolWorks$

	:i if (bool_test) #//This means "If bool_test = 1"
		:i else
	:i endif

:i endfunction
TADA!

Morten1337
Site Admin
Posts: 322
Joined: Mon Mar 01, 2010 2:23 pm
Location: Norway

Re: [GLOBAL] The ultimate "advanced stuff" guide!

Post by Morten1337 » Thu Jul 21, 2011 9:18 am

Accessing Array data, (Structure index's):
Usually when working with Arrays you will have one Array with several Structure's inside.
I will now show you how you can get any data from this Array.

This is an example of an Array:

Code: Select all

:i $Example_Array01$ = :a{
	:i :s{
			:i $model$ = %sc(0,"peds/Ped_aborigine/Ped_aborigine.skin")
			:i $name$ = %s(0,"Aborigine")
			:i $skeleton$ = $THPS6_Human$
	:i :s}
	:i :s{
			:i $model$ = %sc(0,"peds/Ped_Alien/Ped_Alien.skin")
			:i $name$ = %s(0,"Alien")
			:i $skeleton$ = $THPS6_Human$
	:i :s}
:i :a}
Now, let's say we want the "name".
First set up an %GLOBAL% item in your function, like this:

Code: Select all

#// ...

$pedestrian_name$ = ( ($Example_Array01$ :a{%i(1,00000001):a} ) ->$name$)

#// ...
Now %GLOBAL%-"pedestrian_name" will be the name. In this case "Alien"... Yes, even if its the second item in the array. Because the first item is always 0

Remember you can mix in, the things i talked about earlier in the tutorial.
Like:

Code: Select all

#// ...
	:i $Global_Index$ = %i(2,00000002)
#// ...

:i function $Example_Function02$

	$array_name$ = $Example_Array01$
	$pedestrian_name$ = ( (%GLOBAL%$array_name$ :a{ ( ($Global_Index$) + %i(1,00000001) ):a} ) ->$name$)

	:i call $SendChatMessage$ arguments
			$string$ = %GLOBAL%$pedestrian_name$

:i endfunction
Accessing Array data, (Item index):
Sometimes your array doesn't have structure items. You could for example have an array with only checksum names.
Its really easy to get them, and i'll show you.

It works just the same as the first "Array part".

Lets say this is our array:

Code: Select all

:i $Example_Array02$ = :a{
	:i $Ped_M_Idle1$
	:i $Ped_M_Talk_Dull$
	:i $Ped_M_Talk2_BackThere$
	:i $Ped_M_Talk2_GoAhead$
	:i $Ped_M_Talk2_KnowWhatIMean$
	:i $Ped_M_Talk2_Maybe$
	:i $Ped_M_Talk2_MixIt$
	:i $Ped_M_Talk2_OfCourse$
	:i $Ped_M_Talk2_RightHere$
	:i $Ped_M_Talk2_RoundAndRound$
	:i $Ped_M_Talk2_SureThing$
	:i $Ped_M_Talk2_TheyllTellYou$
	:i $Ped_M_Talk2_UpAbove$
	:i $Ped_M_Talk2_WhatDoYouThink$
	:i $Ped_M_ThumbUp$
	:i $Ped_M_Disgust$
	:i $Ped_M_Talk_Shrug$
	:i $Ped_M_Talk_RaiseArn$
	:i $Ped_M_Talk_WhoKnows$
	:i $Ped_M_Talk_ISupposeSo$
:i :a}
Now I want to "get" the name of the 5th item in this array. Which is "Ped_M_Talk2_Maybe"
All you gotta do is, to set up an %GLOBAL%-item like this:

Code: Select all

$anim$ =  ( $Example_Array02$:a{%i(5,00000005):a} )
Take a look at this topic for another example.
Convert Vector's and Doubles to Float:
When you have a Vector or a Double (which is basically 3 or 2 floats grouped together), and you want to make it into separate Floats, then do like this:

Set up %GLOBAL% items for each value, for a vector: (x, y, z) for double: (x, y):

Code: Select all

	$VectorPos$ = %vec3(10.000000,20.000000,30.000000)
	$Float_X$ =  (%GLOBAL%$VectorPos$->%vec3(1.000000,0.000000,0.000000) ) #// 10
	$Float_Y$ =  (%GLOBAL%$VectorPos$->%vec3(0.000000,1.000000,0.000000) ) #// 20
	$Float_Z$ =  (%GLOBAL%$VectorPos$->%vec3(0.000000,0.000000,1.000000) ) #// 30

Code: Select all

	$DoublePos$ = %vec2(10.000000,20.000000)
	$Float_X$ =  (%GLOBAL%$DoublePos$->%vec2(1.000000,0.000000) ) #// 10
	$Float_Y$ =  (%GLOBAL%$DoublePos$->%vec2(0.000000,1.000000) ) #// 20
EXAMPLE, Do not copy this:

Code: Select all

		:i $LevelEditor$.$GetCursorPosition$
		:i $cursorpos$ = (%GLOBAL%$pos$)
			$vec3x$ =  (%GLOBAL%$cursorpos$->%vec3(1.000000,0.000000,0.000000)) 
			$vec3y$ =  (%GLOBAL%$cursorpos$->%vec3(0.000000,1.000000,0.000000)) 
			$vec3z$ =  (%GLOBAL%$cursorpos$->%vec3(0.000000,0.000000,1.000000))
			$vec3pos$ = %GLOBAL%$cursorpos$

		:i $ObjPos$ =  ((($LevelEditor_NodeArray$):a{%GLOBAL%$item_index$:a}) ->$pos$)
		$lvlvec3pos$ = %GLOBAL%$ObjPos$
		$lvlvec3x$ =  ((%GLOBAL%$ObjPos$->%vec3(1.000000,0.000000,0.000000)) -  ($leveleditor_radius$) ) 
		$lvlvec3y$ =  ((%GLOBAL%$ObjPos$->%vec3(0.000000,1.000000,0.000000)) -  ($leveleditor_radius$) ) 
		$lvlvec3z$ =  ((%GLOBAL%$ObjPos$->%vec3(0.000000,0.000000,1.000000)) -  ($leveleditor_radius$) )
		$outlvlvec3x$ =  ((%GLOBAL%$ObjPos$->%vec3(1.000000,0.000000,0.000000)) +  ($leveleditor_radius$) ) 
		$outlvlvec3y$ =  ((%GLOBAL%$ObjPos$->%vec3(0.000000,1.000000,0.000000)) +  ($leveleditor_radius$) ) 
		$outlvlvec3z$ =  ((%GLOBAL%$ObjPos$->%vec3(0.000000,0.000000,1.000000)) +  ($leveleditor_radius$) )

		:i if ( ((%GLOBAL%$vec3x$ < %GLOBAL%$outlvlvec3x$) AND (%GLOBAL%$vec3x$ > %GLOBAL%$lvlvec3x$)) AND ((%GLOBAL%$vec3y$ < %GLOBAL%$outlvlvec3y$) AND (%GLOBAL%$vec3y$ > %GLOBAL%$lvlvec3y$)) AND ((%GLOBAL%$vec3z$ < %GLOBAL%$outlvlvec3z$) AND (%GLOBAL%$vec3z$ > %GLOBAL%$lvlvec3z$)))
		:i $Obj_Name$ =  ((($LevelEditor_NodeArray$):a{%GLOBAL%$item_index$:a}) ->$name$)
		:i $Obj_Class$ =  ((($LevelEditor_NodeArray$):a{%GLOBAL%$item_index$:a}) ->$class$)
Convert Floats to Vector and Double:
Now, if you have a Float that you want to "put back" into another vector/double. I figured out a little wacky way to do that.
This is useful when you only want to change one of the floats in the vector/double.

So lets say i have a Double like this:

Code: Select all

$XY_Scale$ = %vec2(0.000000,1.520000)
But i want to change that "0.0" to something else, without changing the other. Then simply create a new %GLOBAL% - double:
:

Code: Select all

$Double_01$ = ( %f(5.000000) * %vec2(1.000000,0.000000))
Basically (5 * 1) = 5, but the answer will be returned as a Double, like vec2(5, 0)

Here's another example of it being used:

Code: Select all

:i $index_float$ = (%f(0.000000) + %GLOBAL%$index$)
:i $max_float$ = (%f(0.000000) + ($MAX_number_of_placed_objects$))

:i $scale$ = ((%GLOBAL%$index_float$ / %GLOBAL%$max_float$) * %f(15.000000))

:i $new_scale$ = ( ( (%GLOBAL%$scale$)  * %vec2(1.000000,0.000000))  +  (%f(1.520000) * %vec2(0.000000,1.000000)) ) 
So yeah, This is the first part of this tutorial. There are many more things i could teach you.
But this will be it, for now.

~Morten

Post Reply