Jump to content
Sign in to follow this  
sudslv

Can somebody explain this to me?

Recommended Posts

Hi im kinda new to this arma 2 scripting (3 weeks) and as far i understand then:

_x is for each in list ["obj1", "obj2"]

but my problem is i made a very simple script wich spawns bike near player:

init.sqf

[player] execVM "spawnbike.sqf";

spawnbike.sqf

player addaction ["spawn bike", "bike.sqf"];

bike.sqf

_bike = "MMT_USMC" createVehicle (position player); hint format["You spawned bike",player];

it works in editor/single player ok but i think in multiplayer it would either spawn bike randomly or at 1 random player (i havent tested and hope this is true) so my question is how to make script know which player executed the script and for example spawn bike next to the exact player who executed in server (1-999+ players) i dont know how to acctualy name this so i cant find answer anywere. so what i want to do for now is execute the player addaction on everyone but when anyone of them dieciedes to use it, then spawn bike next to them (not next to everyone or 1 random person) and how to track if he used it? (so people cant just spam with this) i know that i can place the "this execVM "spawnbike.sqf"; into units init line but i want to do it with init.sqf (i have about 80+ playable units placed and dont want to redo it all as im sure there is other way). i hope you get the idea where im stuck. and would be nice if someone explained about: "null", "nill", difference between "this" and "_this".

thank you for reading.

---------- Post added at 00:00 ---------- Previous post was at 00:00 ----------

the bike is just and example. i have several scripts but i dont know how to make them work for each individual player in big multiplayer server.

Solved spawnBike.sqf:

// preventing from spam.
if (isNil "userSpawnedBike") then 
{ 
   userSpawnedBike = objNull; 
}; 

if (!isNull userSpawnedBike) then 
{ 
   if (!isNull (driver userSpawnedBike)) then 
   { 
        (driver userSpawnedBike) action ["eject", userSpawnedBike]; 
   }; 
   deleteVehicle userSpawnedBike; 
};
// spawning bike.
_spawnDir = getDir player;  
_spawnPos = player modelToWorld [0, 3, 0]; 
_spawnPos set [2, 0];   
userSpawnedBike = "MMT_USMC" createVehicle (_spawnPos);
userSpawnedBike setDir _spawnDir;  
hint "You spawned bike";

Edited by sudslv

Share this post


Link to post
Share on other sites

The eventhandler for the action will receive an array like [target, caller, ID, (arguments)] when called.

So all you have to do is:

_bike = "MMT_USMC" createVehicle (position (_this select 1)); hint "You spawned bike";

Then again, it is discouraged to use the short form of createVehicle, use this one instead:

_bike =  createVehicle ["MMT_USMC", getPosATL (_this select 1), [], 0, "NONE"]; hint "You spawned bike";

To prevent spamming the server with bikes either define a quota (each player can spawn X bikes) or delete the action once it has been executed, granting the user to spawn just one time.

How to implement a quota:

// init.sqf
spawnQuota = 5; // any number you want

// bike.sqf
if (spawnQuota > 0) then
{
   spawnQuota = spawnQuota - 1;

   _bike =  createVehicle ["MMT_USMC", getPosATL (_this select 1), [], 0, "NONE"]; 
   hint "You spawned bike";
}
else
{
   hint "You depleted your spawn quota and thus can't spawn bikes anymore";
};

How to implement action removal:

// bike.sqf
_bike =  createVehicle ["MMT_USMC", getPosATL (_this select 1), [], 0, "NONE"]; 
hint "You spawned bike";

(_this select 0) removeAction (_this select 2);

You can also combine those both to prevent the player to even use the action after the quota is depleted.

Edited by XxAnimusxX

Share this post


Link to post
Share on other sites

thank you for reply but i still dont understand: "so my question is how to make script know which player executed the script and for example spawn bike next to the exact player who executed in server" and in your script: "(_this select 1), []" as far i know it selects arrays from 0, so first would be "MMT_USMC" and 2nd "getPosATL (_this select 1)" im little confused.

Share this post


Link to post
Share on other sites

Ah okay, let's do this step for step :)

When the player on whom the action is attached activates the action, in this case "Spawn Bike", the scriptfile bike.sqf gets called.

Upon calling bike.sqf, a parameter is delivered to the script which is an array holding different values, with [target, caller, ID, (arguments)] being:

  • target: Object - the object which the action is assigned to
  • caller: Object - the unit that activated the action
  • ID: Integer - ID of the activated action
  • arguments: Anything - arguments given to the script if you are using the extended syntax

I hope you can see now that caller is the object you were searching for. In this case target equals caller, because both the player has the action and activates it.

What you want to do is getting the caller out of the array, so using "_this select 1" is the correct syntax (_this is referencing the parameter-array and index 1 the caller).

Please look into the BIKI article for addAction to understand more of the parameters.

If createVehicle_array confuses you, you're of course free to use the short form.

You'll learn eventually about all the different commands in the future so you don't have to adapt to everything yet :D

"getPosATL (_this select 1)" gets the position of the caller above terrain level (I assume you wouldn't want to spawn a bike over water...).

One could have defined it this way as well:

// bike.sqf
_caller = _this select 1;
_bike =  createVehicle ["MMT_USMC", getPosATL _caller, [], 0, "NONE"];
// ....

Edited by XxAnimusxX

Share this post


Link to post
Share on other sites

you need to set the arrays or they are auto: so on addaction 0 will be targer, 1 will be caller, 2 will be id, 3 will be arguments? i dont understand where are you getting them from? and my initial idea was to make this work with GUI button.

edit:

im looking right now at Celery's bandage script:

//init.sqf
[player,0.14,0,10,true] execVM "cly_heal.sqf";

so player executes the script and the numbers are the "options" (idk how to call them), but at his script he does this:

//script.sqf
_target=_this select 0;
_caller=_this select 1;
_id=_this select 3;

so im confused now.

targer - player

caller - 0.14

id - 0

im newb to all this and would like to get some explanation how it works.

and thank you for replying to me.

Edited by sudslv

Share this post


Link to post
Share on other sites

Yeah, that array is automatically created by the game engine and delivered to the eventhandler you defined. It's the same like using a function:

_spawnBike = {

   _target = _this select 0;
   _caller = _this select 1;
   _id = _this select 2;
   _arguments = _this select 3;

   // createVehicle ....
};

[player, player, 1, nil] call _spawnBike;

This would equal the action-call, just so you can see how it is handled in your case.

Please read the BIKI article about functions to fully understand the system behind it.

edit: he is defining the parameters to deliver by himself, the parameters delivered to your addAction-eventhandler are automatically created.

You have to read the BIKI articles about the specific commands to understand which parameters they expect.

In Celery's case he just defined his own parameter syntax, so can you.

Share this post


Link to post
Share on other sites

thank you very much, you explained alot of things to me :) so basicaly in GUI on button press i execute:

spawnBike = { 

   _target = _this select 0; 
   _caller = _this select 1; 
   _id = _this select 2; 
   _arguments = _this select 3; 

   _bike =  createVehicle ["MMT_USMC", getPosATL _caller, [], 0, "NONE"]; 
}; 

[player, player, 1, nil] call _spawnBike;  

or:

spawnBike = { 

   _target = _this select 0; 
   _caller = _this select 1; 
   _id = _this select 2; 
   _arguments = _this select 3; 

};

_bike =  createVehicle ["MMT_USMC", getPosATL _caller, [], 0, "NONE"]; 

[player, player, 1, nil] call _spawnBike;  

so this will find the exact player who called the createvehicle... and teleport the vehicle to caller as defined player?

it knows the "player"s id or i must replace the getPosATL _id?

edit: im on different computer and cant access any of scripts.

Edited by sudslv

Share this post


Link to post
Share on other sites

HryaKwE.jpg

okay, that was my fault, it is way too confusing to show script examples if the underlying system isn't understood yet :D

Don't mind my example, it was just to show you how the eventhandler is being called.

As for now, just keep this in mind: Whenever you use addAction, the script (sqf-file) you define to be executed when the action gets chosen, should always look like this:

_target = _this select 0;
_caller = _this select 1;
_id = _this select 2;
_args = _this select 3;

// .. your code here

Just take this as a rule of thumb. When you learn more about SQF-Scripting you'll eventually find out why :)

So your bike.sqf should look exactly like this:

_target = _this select 0;
_caller = _this select 1;
_id = _this select 2;
_args = _this select 3;

_bike = "MMT_USMC" createVehicle (position _caller); 
hint "You spawned bike";  

This will spawn the bike to the position of the caller and since it's the individual player you'll get the result you wished for.

Additionally I'd suggest to read as much tutorials covering the basics as possible, this subforum has some pinned threads which are worth to read.

You meantioned a GUI button several times, that's a whole different level and is handled in it's own way with another set of parameters.

Maybe I'm not fit to explain all this as I take these as granted, perhaps someone else can explain it the way you can understand it.

I'm really confused right now because I don't know anymore what the original request was :D

Edited by XxAnimusxX

Share this post


Link to post
Share on other sites

thank you :) i got working script with GUI on button click but i still would like to know 4 things: 1. how to make that bike will despawn if player didnt use it for 5 min. check if player already spawned 1 bike so he cant keep spawning them (when he will press the button a hint will pop up saying "you already spawned bike" or it will erase previous bike and spawn new) 3. how to make either when bike spawns player automaticaly gets on it as driver or spawn it 2m infront of players direction. But most important: how to do it only in 1 sqf file? thank you very much.

Share this post


Link to post
Share on other sites

grrr.... There are too much or's in your request, how should I be able to help you if you don't know what you want yourself? :D

So please, can you put your question again but this time, specify the exact sequence?

Something like:

1. Player activates the action "Spawn Bike".

2. If player spawned a bike before, do ......

3. ....

...

No or's, just and's! That would greatly help :)

I mean getting the player into the drive seat and checking if he isn't using the vehicle for a set amount of time contradicts itself :D

Don't be offended though, but asking has to be learned as well ^^

Share this post


Link to post
Share on other sites

okay.

1.how to make it check if already spawned?

2.how to make it despawn after 300 secounds?

Share this post


Link to post
Share on other sites

Well thats quite easy :D

You don't even have to check if the player spawned one if you just remove the action after he did. He won't be able to pick the action, so you don't have to check anything :)

And the despawn is quite easy to script as well. All in all it would lead to this code:

// bike.sqf
_target = _this select 0;
_caller = _this select 1;
_id = _this select 2;

// Remove the action
_target removeAction _id;

// Spawn the bike 5meters in front of the user
_spawnDir = getDir _caller;
_distance = 5;
_spawnPos = player modelToWorld [0, _distance, 0];
_spawnPos set [2, 0];

_bike = createVehicle ["MMT_USMC", _spawnPos, [], 0, "NONE"];
_bike setDir _spawnDir; // just for the beauty :D
_bike setPosATL _spawnPos;

// Now to check if it's unused
_bike spawn {
   _count = 0;
_maxTime = 300;
   waitUntil {sleep 0.5; _count = _count + 1; _count > (_maxTime*2) || !isNull (driver _this);};

if (_count > (_maxTime*2)) then
{
	deleteVehicle _this;
};
};

Share this post


Link to post
Share on other sites

okay but the script is not for addaction. it is executed by GUI onButtonClick. however:

// spawning bike.
_bike spawn {deleteVehicle _this;};
_spawnDir = getDir player;  
_spawnPos = player modelToWorld [0, 3, 0]; 
_spawnPos set [2, 0];   
_bike = "MMT_USMC" createVehicle (_spawnPos);
_bike setDir _spawnDir;  
hint "You spawned bike";

i would like to make something like this but the deleteVehicle part is ignored.

i want the previous spawned bike get deleted and new one to spawn in front of the player (working in MP).

Share this post


Link to post
Share on other sites

Ah okay, if your code gets executed upon clicking at a GUI ctrl, the parameters will change drastically, but we can neglect that because those parameters won't help us much :D

if (isNil "userSpawnedBike") then
{
   userSpawnedBike = objNull;
};

if (!isNull userSpawnedBike) then
{
   if (!isNull (driver userSpawnedBike)) then
   {
        (driver userSpawnedBike) action ["eject", userSpawnedBike];
   };
   deleteVehicle userSpawnedBike;
};

_spawnDir = getDir player;
_spawnPos = player modelToWorld [0, 3, 0];
_spawnPos set [2, 0];

userSpawnedBike = createVehicle ["MMT_USMC", _spawnPos, [], 0, "NONE"];
userSpawnedBike setDir _spawnDir; // just for the beauty :D
userSpawnedBike setPosATL _spawnPos;  // Don't ommit this line! the direction won't get synched with the server!

// Now to check if it's unused
userSpawnedBike spawn {
   _count = 0;
   _maxTime = 300;
   waitUntil {sleep 0.5; _count = _count + 1; _count > (_maxTime*2) || !isNull (driver _this);};

   if (_count > (_maxTime*2)) then
   {
       deleteVehicle _this;
   };
}; 

Share this post


Link to post
Share on other sites

Thank you :) bike part Is SOLVED:

// preventing from spam.
if (isNil "userSpawnedBike") then 
{ 
   userSpawnedBike = objNull; 
}; 

if (!isNull userSpawnedBike) then 
{ 
   if (!isNull (driver userSpawnedBike)) then 
   { 
        (driver userSpawnedBike) action ["eject", userSpawnedBike]; 
   }; 
   deleteVehicle userSpawnedBike; 
};
// spawning bike.
_spawnDir = getDir player;  
_spawnPos = player modelToWorld [0, 3, 0]; 
_spawnPos set [2, 0];   
userSpawnedBike = "MMT_USMC" createVehicle (_spawnPos);
userSpawnedBike setDir _spawnDir;  
hint "You spawned bike";

But there are few more things i would like to know (fast version could work too).

1. How to use "!(something)", (!something)" and "!something".

2. What is difference between: "Nill" and "Null".

3. What is difference between: "_this" and "this".

Edited by sudslv

Share this post


Link to post
Share on other sites

  1. All of the three are equal, but with slightly different interpretations:
    !(something): The content of the parentheses is evaluated and then logically inversed (negated)
    (!something): Just the term "something" is logically inversed and then the whole parantheses is evaluated
    !something: Just the term "something" is logically inversed.
    Examples:
    !(true or false) would result in false, because: (true or false) equals true and negated: false.
    !(false and true) would result in true, because: (false and true) equals false and negated: true
    (!false and true) would result in true, because: false negated is true, (true and true) is, true :D
    !true is false. Because, well, true negated is false obviously :D
  2. Null is a state in which no valid value is assigned to a variable. There are many specific null-values: objNull, grpNull, taskNull ...
    You can't compare Null-Values with each other, because Null is not equal to anything, not even itself. Using isNull to check is the only way.
    _myVehicle = objNull; // Not yet created
    if (isNull _myVehicle) then {
      _myVehicle = "something";
    };


    Nil is a special variable which means something like "not existent". If you want to check if a variable exists in your scope, you can use isNil to check it.

    if (isNil "myVehicle") then
    {
       myVehicle = objNull; // null != nil. Even using a null-variable means that the variable exists.
    };
    myVehicle = nil; // this deletes the "existence" of myVehicle.
    


  3. Every variable with an preceded underscore is local to its scope. _this and this are special (or "magic") variables which are typically created by the game-engine
    and set everytime you enter a special block of code.
    A rule of thumb: _this is used to reference the parameters delivered to functions, in most of the cases being an array. If you create your own function, _this will reference the parameters
    upon calling/spawning your function. But most of the native commands used in ArmA also rely on _this, for example the event-handlers. Every event has a slightly different set of parameters,
    but all of them are referenced using _this.
    this, at the other hand, is mostly used in init-lines and special cases. You shouldn't rely that much on my rambling though, the best way to figure out which of these this' to use is to look into the BIKI description of the commands.
    Here are two different commands, read the description to find out which of the this' to use:
    http://community.bistudio.com/wiki/addEventHandler
    http://community.bistudio.com/wiki/setWaypointStatements

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×